Существует несколько различных применений параметра host_ptr, в зависимости от значения, переданного в параметр flags. Два флага, которые его используют: CL_MEM_USE_HOST_PTR
& CL_MEM_COPY_HOST_PTR
. Если флаги не содержат ни одного из них, а host_ptr не равен NULL, функция выдаст ошибку CL_INVALID_HOST_PTR
(см. Ошибки внизу страницы clCreateBuffer ).
CL_MEM_COPY_HOST_PTR
Это в основном делает, как вы описали, копирует host_ptr в память устройства. Это обеспечивает удобство, эффективно комбинируя clCreateBuffer
& clEnqueueWriteBuffer
. Обратите внимание, что вам не нужна очередь команд, как того требует clEnqueueWriteBuffer
, данные будут скопированы на все устройства в контексте, прежде чем их использовать, насколько это удобно!
Как следует из названия, это COPY. Если вы записываете в эту память на устройстве, память в host_ptr никогда не увидит эти записи (если вы не выполните clEnqueueReadBuffer ). Аналогично, если вы записываете в host_ptr после создания буфера, память на устройстве не будет видеть эти записи (если вы не выполните clEnqueueWriteBuffer ).
CL_MEM_USE_HOST_PTR
Вместо этого для создания буфера в памяти устройства OpenCL будет использовать память, указанную напрямую host_ptr. Если ваше устройство является выделенным графическим процессором с подключением P CIe, это означает, что каждый раз, когда вы читаете или записываете в эту память код устройства, данные должны отправляться через P CIe (медленно). , OpenCL позволяет устройству создавать кеш данных во время выполнения ядра, что несколько помогает. Если ваше устройство совместно использует физическую память с хостом, как встроенный графический процессор, таких издержек не должно быть.
Обратите внимание, хотя вы должны быть осторожны, чтобы обеспечить согласованность памяти. Если хост изменяет host_ptr, когда ядро работает с памятью, связанной с ним (или наоборот), вы получаете неопределенное поведение.
Что использовать?
Это зависит от того, что вы делаете и на каком оборудовании вы работаете. Если вы не слишком беспокоитесь о производительности копирования памяти и хотите простой и безопасный способ, используйте CL_MEM_COPY_HOST_PTR
.
Если устройство перегружено P CIe (или другой интерфейс)
Для больших массивов я обычно использую CL_MEM_COPY_HOST_PTR
и ставлю в очередь чтение / запись по мере необходимости. Если я просто пишу в int или небольшую структуру, я бы использовал CL_MEM_USE_HOST_PTR
, просто будьте осторожны с согласованностью памяти.
Если вы действительно заинтересованы в производительности памяти, вы можете приходится изучать такие методы, как закрепление памяти ( Справочник по графическим процессорам AMD ).
Если устройство совместно использует память хоста (встроенный графический процессор или просто процессорное устройство)
Если вы уверены, что хост и устройства не будут читать, пока другой пишет, вы можете использовать CL_MEM_USE_HOST_PTR
для объектов памяти любого размера. Для максимальной производительности вам может потребоваться убедиться, что host_ptr выровнен и кратен определенному размеру (для устройств Intel выровнен по границе 4 КБ и кратен 64 байтам). Здесь - дополнительная информация для нулевого копирования на оборудовании Intel.