Как использовать закрепленную память/карту памяти в OpenCL

Чтобы сократить время передачи от хоста к устройству для моего приложения, я хочу использовать закрепленную память. Руководство по лучшей практике NVIDIA предлагает отображать буферы и записывать данные, используя следующий код:

cDataIn = (unsigned char*)clEnqueueMapBuffer(cqCommandQue, cmPinnedBufIn, CL_TRUE,CL_MAP_WRITE, 0, memSize, 0, NULL, NULL, NULL);

for(unsigned int i = 0; i < memSize; i++) 
{ 
    cDataIn[i] = (unsigned char)(i & 0xff); 
}

clEnqueueWriteBuffer(cqCommandQue, cmDevBufIn, CL_FALSE, 0, 
szBuffBytes, cDataIn, 0, NULL, NULL);

Руководство по оптимизации Intel рекомендует использовать вызовы clEnqueueMapBuffer и clEnqueueUnmapBuffer вместо вызовов clEnqueueReadBuffer или clEnqueueWriteBuffer.

Каков правильный способ использования закрепленной памяти/карты памяти? Нужно ли писать данные с помощью enqueueWriteBuffer или достаточно enqueueMapBuffer?

Кроме того, в чем разница между CL_MEM_ALLOC_HOST_PTR и CL_MEM_USE_HOST_PTR?

Ответы

Ответ 1

Это интересная тема, в которой очень мало деталей. Я попытаюсь точно определить, как это работает.

Прикрепленная память относится к памяти, которая также находится на устройстве, существует в хосте, поэтому между этими двумя памятью возможна запись DMA. Увеличение производительности копии. Вот почему в параметрах создания буфера требуется CL_MEM_ALLOC_HOST_PTR.

С другой стороны, CL_MEM_USE_HOST_PTR будет принимать указатель хоста для создания буфера, это неясно спецификацией, если это может или не может быть закрепленной памятью. Но, вообще говоря, он не должен быть закрепленной памятью, созданной таким образом, поскольку указатель узла не был зарезервирован API OpenCL и не ясен, где он находится в памяти.


Относительно вопроса "Карта/Чтение". Оба в порядке. И они дадут такую ​​же производительность. Разница между обоими методами заключается в том, что:

  • Для карты /Unmap : вам нужно нарисовать карту перед записью/чтением и затем распаковать. Таким образом, вы обеспечиваете согласованность данных. Это API-вызовы и требуется время для завершения, а также для асинхронности. Хорошо, что вам не нужно держать какую-либо другую вещь, а не буферный объект.
  • Для карты + чтение/запись. При создании зоны памяти вам необходимо сделать карту и сохранить значение указателя. Затем при уничтожении буфера вам нужно сначала размонтировать, а затем уничтожить его. Вы должны держать buffer+Mapped_Buffer все время. Хорошо, что теперь вы можете просто clEnqueueRead/Write сопоставить указатель. API будет ждать согласованных данных, а затем подумать об этом. Это проще в использовании, поскольку это похоже на создание карты + unmap за один кадр.

Режим чтения/записи проще в использовании, особенно для повторяющихся чтений, но не настолько универсален, как опция ручной карты, так как вы НЕ МОЖЕТЕ писать карту read only или не читать карту write only. Но для общего использования переменные, которые читаются, никогда не будут записаны, а наоборот.


Я понимаю, что рекомендация Intel относится к "Использовать карту, а не просто читать/писать" , а не ". Когда вы используете Map, не используйте Read/Write over Mapped указатели" .

Вы проверили эту рекомендацию nVIDIA по Intel HW? Я думаю, что это должно сработать, однако я не знаю, действительно ли операция была бы оптимальной (как в AMD или nVIDIA HW).