opencl
Управление памятью хоста
Поиск…
Вступление
В этом разделе рассматриваются различные способы размещения данных где-нибудь, где ваше устройство может получить к нему доступ.
Чтение массива
Чтобы прочитать массив с устройства обратно на хост, один вызывает
clEnqueueReadBuffer($queue, $memobj, $blocking, $offset, $size, $target, 0, null, null);
$ Queue - это CommandQueue, который использовался для выделения памяти на устройстве. $ Memobj содержит адрес памяти устройства, $ offset и $ size, далее определяют, где и сколько данных копируется. $ Target - указатель на память хоста, в котором будут храниться данные. Целевая задача $ target должна быть выделена и иметь соответствующий размер.
Чтение текстуры
Чтение изображения почти похоже на чтение массива. Единственное отличие заключается в том, что размер и смещение должны быть трехмерными.
clEnqueueReadImage($queue, $memobj, $blocking, $offset, $size, $stride, $slice_pitch, $target, 0, null, null);
$ Stride определяет, сколько байтов имеет строка. Обычно это просто ширина * (байты на пиксель), но кто-то может захотеть изменить это, чтобы выровнять данные с банками памяти. То же самое касается $ slice_pitch, только это значение для третьего измерения.
Написание 2D-текстуры
Чтобы скопировать текстуру на устройство, необходимо выполнить два шага
- Выделите память на устройстве
- Скопируйте изображение на устройство
_mem = clCreateImage2D($context, $mem_flags, $image_format, $width, $height, $stride, $source, &err);
$ Mem_flags определяет, как распределяется память. Это может быть только чтение, запись только или и то, и другое. Кроме того, вы можете определить, где и как распределяется память. $ width, $ height и $ stride довольно понятны.
Если ваши mem_flags копируют данные, все готово. Если вы хотите сделать это вручную в более поздней точке, вам нужно будет вызвать другую функцию, когда вы будете готовы.
err = clEnqueueWriteImage($queue, _mem, $blocking, $offset, $size, $stride, $slice_pitch, $source, 0, null, null);
$ Offset и $ size определяют область изображения, которую вы хотите скопировать в целевую память. $ Stride определяет, сколько байтов имеет строка. Обычно это просто ширина * (байты на пиксель), но кто-то может захотеть изменить это, чтобы выровнять данные с банками памяти. То же самое касается $ slice_pitch, только это значение для третьего измерения. И $ stepide, и $ slice_pitch должны соответствовать вашим входным данным.
Флаги памяти
При распределении памяти вы можете выбирать между различными режимами:
- Только для чтения памяти
- Запись только памяти
- Чтение / запись памяти
Память только для чтения выделяется в области памяти __constant, а две другие - в нормальном __global регионе.
В дополнение к доступности вы можете определить, где выделена ваша память.
- Не указано: Ваша память распределена в памяти устройства, как и следовало ожидать. Указатель $ source может быть установлен в null.
- CL_MEM_USE_HOST_PTR: Это указывает устройству, что данные находятся в ОЗУ системы и не должны перемещаться. Вместо этого данные обрабатываются непосредственно в ram.
- CL_MEM_COPY_HOST_PTR: Сообщает устройству копировать все значения по указанному адресу в память устройства или, используя CL_MEM_ALLOC_HOST_PTR, в отдельную область памяти в системном табло.
- CL_MEM_ALLOC_HOST_PTR: Сообщает устройству о распределении пространства в системном RAM. Если используется как единственный параметр, указатель $ source может быть установлен в null.
Скоростной доступ к глобальной памяти устройства является самым быстрым. Но вам также нужно дважды позвонить ему, чтобы скопировать данные. Использование Host-указателя является самым медленным, в то время как Alloc_host_ptr предлагает более высокую скорость.
При использовании use_host_ptr устройство выполняет именно это: оно использует ваши данные в системном плунжере, который, конечно же, вызывается сервером os. Поэтому каждый вызов памяти должен проходить через процессор, чтобы обрабатывать потенциальные ошибки. Когда данные доступны, процессор копирует его в закрепленную память и передает его на контроллер DMA с использованием часовых тактовых импульсов процессора. Напротив, alloc_host_ptr выделяет фиксированную память в системном RAM. Эта память размещается за пределами механизма pageswap и поэтому имеет гарантированную доступность. Поэтому устройство может полностью пропустить CPU при доступе к системному плунжеру и использовать DMA для быстрой копирования данных на устройство.
Написание массива
Запись массива состоит из двух шагов:
- Выделение памяти
- Копирование данных
Чтобы выделить память, просто позвонить
_mem = clCreateBuffer($queue, $mem_flags, $size, $host_ptr, &err);
достаточно. Если вы решили скопировать указатель узла через mem_flags, все готово. В противном случае вы можете копировать данные, когда захотите.
err = clEnqueueWriteBuffer($queue, _mem, $blocking, $offset, $size, $source, 0, null, null);