У меня проблема с производительностью для моей оболочки opencl C ++, мне нужно как можно быстрее перенести данные из буфера d в буфер b (используя map / unmap для достижения скорости DMA pci-e 6 ГБ / с), а затем скопировать эти данные в буфер a (при скорости устройства около 40 ГБ / с)
*********************************
* device(discrete gpu) *
* *
* (enqueueCopyBuffer) *
* a <---->b *
*********************************
^
|(map/unmap)
|
***************
* d------>c *
* (memcpy) *
* *
* host *
* *
***************
Я перепробовал много комбинаций ALLOC_HOST_PTR, COPY_HOST_PTR, … для a, b и c, но не смог найти оптимального решения.
Вот что я попробовал:
d---->c (memcpy 10GB/s)
c----->b(map/unmap CL_ALLOC_HOST_PTR)(6GB/s) , b---->a (enqueueCopyBuffer ~5 GB/s)
(I think ALLOC makes b host buffer)
d---->c (memcpy 10GB/s)
c------>b(map/unmap CL_READ_WRITE)(1.4GB/s) , b---->a (enqueueCopyBuffer 40GB/s)
(now b is device buffer but map/unmap is not good and buggy)
d------>a(enqueueWriteBuf CL_READ_WRITE)(1.7GB/s)
(I started the new project with this)
(multithreaded read/write does not go beyond 2GB/s)
но мне нужно:
d----->c(memcpy 10GB/s)
c----->b(map/unmap CL_???_PTR)(6GB/s) , b---->a (enqueueCopyBuffer 40 GB/s)
Причина разделения a и b состоит в том, что для выполнения ядра необходимо использовать память устройства.
Причина разделения d и c заключается в том, что я реализую ускорение графического процессора в проекте с открытым исходным кодом, и я не хочу менять целостность массива проекта.
Есть по крайней мере дюжина из a, b, c, d, которые я должен использовать. 2 для скоростей, 1 для давления, …
Вопрос: Какую структуру буфера я должен реализовать, чтобы достичь цели «узкая часть не должна быть меньше 6 ГБ / с в любом месте». Должен ли я объединить все b вместе (то же самое для c) в больший буфер, чтобы сделать одно чтение / запись / отображение / удаление для всех них?
Ваше требование к фиксированной пропускной способности очень строго.
Если & b оба буфера на стороне устройства, мой совет использовать техника закрепленной памяти с простыми флагами выделения CL_MEM_READ_WRITE. Хотя лучшие результаты, которые я когда-либо достигал, составляли около 5,3 ГБ / с на PCIe 2.0 x16. Принимая во внимание, что передача памяти обычно происходит за микросекунды, вы можете сделать это с неблокирующей передачей памяти с ожиданием события на стороне хоста. Такое конвейерное выполнение задач обычно показывает хорошую пропускную способность.
Обычно (для a, b, c & d буферы), мой совет — использовать отдельную очередь команд для каждого типа трафика памяти, чтобы получить преимущества от передач DMA. Обычно достаточно 3 очереди команд — хост-устройство, устройство-устройство & Хост-узел.
Контроллеры памяти GPU предназначены для обеспечения высокой пиковой пропускной способности с высокими задержками, поэтому массивные асинхронные передачи памяти, как правило, быстрее. Старайтесь избегать любых синхронных операций, они замораживают все это.
Других решений пока нет …