В чем разница между созданием буферного объекта с помощью CLCREATEBUFFER + CL_MEM_COPY_HOST_PTR VS. CLCREATEBUFFER + CLENQUEUEURITEBUFFER?

StackOverflow https://stackoverflow.com/questions/3832963

  •  26-09-2019
  •  | 
  •  

Вопрос

Я видел оба версиях в руководствах, но не смог найти, какие их преимущества и недостатки являются. Какой из них является правильным?

cl_mem input = clCreateBuffer(context,CL_MEM_READ_ONLY,sizeof(float) * DATA_SIZE, NULL, NULL);
clEnqueueWriteBuffer(command_queue, input, CL_TRUE, 0, sizeof(float) * DATA_SIZE, inputdata, 0, NULL, NULL);

против.

cl_mem input = clCreateBuffer(context,CL_MEM_READ_ONLY | CL_MEM_COPY_HOST_PTR, ,sizeof(float) * DATA_SIZE, inputdata, NULL);

Спасибо.

Обновлять

я добавил CL_MEM_COPY_HOST_PTR, до второго примера, чтобы сделать это правильным.

Это было полезно?

Решение

Я предполагаю, что входные данные не нуль.

В этом случае второй подход не должен работать вообще, поскольку спецификации говорится, что CLCREATEBUFFER возвращает NULL и ошибку, если:

Cl_invalid_host_ptr Если host_ptr null и cl_mem_use_host_ptr или cl_mem_copy_host_ptr установлено в флагах или если host_ptr не нулевой, а cl_mem_copy_host_ptr или cl_mem_use_host_ptr не устанавливаются в флагах.

так что вы имеете в виду либо

clCreateBuffer(context,CL_MEM_READ_ONLY | CL_MEM_COPY_HOST_PTR,sizeof(float) * DATA_SIZE, inputdata, NULL);

или

clCreateBuffer(context,CL_MEM_READ_ONLY | CL_MEM_USE_HOST_PTR,sizeof(float) * DATA_SIZE, inputdata, NULL);

Первый должен быть более или менее таким же, как первый подход, который вы показали, в то время как второй на самом деле не скопируют данные, а вместо этого используют прилагаемое местоположение памяти для хранения буферов (кэширование порций или все это в памяти устройства) Отказ Какой из этих двух лучше, зависит от сценария использования очевидно.

Персональный я предпочитаю, используя два шага подходом сначала выделения буфера и впоследствии заполняет его писателем, поскольку мне легче видеть, что происходит (конечно, один шаг может быть быстрее (или это может, это просто угадать)))

Другие советы

Во время моей работы с Opencl я нашел очень важное различие между

cl_mem CT = clCreateImage3DContext, CL_MEM_READ_ONLY | CL_MEM_COPY_HOST_PTR , Volume_format, X, Y, Z, rowPitch, slicePitch, sourceData, &error);

а также

cl_mem CT = clCreateImage3D(Context, CL_MEM_READ_ONLY , Volume_format, X, Y, Z, 0, 0, 0, &error);
error = clEnqueueWriteImage(CommandQue, CT, CL_TRUE, origin, region, rowPitch, slicePitch, sourceData, 0, 0, 0);

Для первого подхода OPENCL будет скопировать указатель хоста не направлять на GPU. Сначала он выделит второй временный буфер на хосте, который может вызвать проблемы, если вы загружаете большие вещи, как CT для GPU. В течение короткого времени необходимая память в два раза удваивается размер CT. Также данные не копируются во время этой функции. Он скопирован во время настройки аргумента в функцию ядра, которая использует объект 3D Image.

Второй подход прямой копирует данные в GPU. Не существует дополнительных распределений OpenCl. Я думаю, что это, вероятно, то же самое для нормальных буферных объектов.

Приятный аспект первого подхода, заключается в том, что «ClenceueUriteBuffer» позволяет назначить событие к копии буфера. Итак, скажем, вы хотите измерить время, необходимое для копирования данных в GPU, используя параметры GPU_PROFILL, вы сможете сделать это с первым подходом, но не со вторым.

Второй подход более компактный, легче прочитать и требует меньшей строки к коду.

Одна серьезная разница в том, что я столкнулся с:

cl_mem input = clCreateBuffer(context,CL_MEM_READ_ONLY,sizeof(float) * DATA_SIZE, NULL, NULL); clEnqueueWriteBuffer(command_queue, input, CL_TRUE, 0, sizeof(float) * DATA_SIZE, inputdata, 0, NULL, NULL);

Этот первый набор команд создаст пустой буфер и enqueue команда в вашей команде, чтобы заполнить буфер.

cl_mem input = clCreateBuffer(context,CL_MEM_READ_ONLY | CL_MEM_COPY_HOST_PTR, ,sizeof(float) * DATA_SIZE, inputdata, NULL)

Эта вторая команда создаст буфер и немедленно заполнит его. Обратите внимание, что в этом списке аргументов нет командной очереди, поэтому он использует содержимое входных данных, как и сейчас.

Если вы уже работали CL-код, и ваш указатель источника зависит от предыдущей команды в завершение команды командной очереди (например, встроенный прочитанный предыдущий выходной буфер), вы определенно хотите использовать 1-й метод. Если вы попытаетесь создать и заполнить буфер в одну команду, вы получите состояние гонки, в котором содержимое буфера не будет должным образом ждать завершения вашего предварительного прочитанного буфера.

Ну, главное отличие этих двух в том, что первый выделяет память на устройстве, а затем копирует данные в эту память. Второй только выделен только.

Или вы имели в виду clCreateBuffer(context,CL_MEM_READ_ONLY | CL_MEM_COPY_HOST_PTR,sizeof(float) * DATA_SIZE, inputdata, NULL);?

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top