2016-11-18 5 views
2

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

Итак, знаем ли мы, когда происходит передача данных с хоста на устройство openCL? Можете ли вы сказать мне точную операцию переноса памяти функций ниже (то есть, какие данные передаются или создаются, если таковые имеются, когда эти функции вызываются?):

clCreateBuffer()

clSetKernelArg()

clEnqueueNDRangeKernel()

Первые два даже не создают события, поэтому мы не можем их разучить, но, безусловно, здесь происходит передача данных.

Есть ли способ передачи данных на устройство без предварительной установки его в качестве аргумента ядра?

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

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

ответ

2

Буферные копии связаны с командами. Командные очереди синхронизируются с хостом, используя finish() как самый простой способ.

clCreateBuffer() 

    clEnqueueWriteBuffer() <-------- you can get event data from this 
     (set blocking parameter to false to queue everything quickly) 
     (set blockinig to true if you sync write here) 

clSetKernelArg() 

    clEnqueueWriteBuffer() <----- it could be here too 

clEnqueueNDRangeKernel() 

    clEnqueueWriteBuffer() <----- or here (too quickly re-set an array?) 

clFinish() <--------- this ensures all queued commands are executed before this 

now you can query data of that event to check when it started and when ended 

Чтобы оставить буфер в устройстве, вы должны сначала его создать на устройстве, а затем не перенести его на другое устройство. Использование только CL_MEM_READ_WRITE флага в createBuffer() достаточно, чтобы сделать его реальным буфером на стороне устройства, пока вы не отпустите этот буфер.

CL_MEM_USE_HOST_PTR или CL_MEM_ALLOC_HOST_PTR использует память хоста, поскольку устройство сопоставляет его с его ядрами. Это быстрее для потоковой передачи данных из и из-за отсутствия необходимости в дополнительных перемещениях данных на стороне хоста. Если вам нужно использовать память устройства, такую ​​как быстрый gddr5 или hbm, то вы не должны использовать эти флаги.

Скопируйте устройство на устройство один раз, используйте столько, сколько хотите. Конечно, если у устройства есть своя память. Например, Intel HD Graphics 400 не имеет собственной памяти и разделяет оперативную память, поэтому гораздо быстрее использовать флаги CL_MEM _..._ HOST_PTR и особенно USE_HOST_PTR.

Чтобы проверить, имеет ли устройство общую память с процессором, вы запрашиваете свойство CL_DEVICE_HOST_UNIFIED_MEMORY устройства.

Оказывается (от предварительного тестирования моего), что объект ает созданного с CL_MEM_USE_HOST_PTR получает непосредственно манипулировать устройства

Даже без карты/Unmap команды pror ядра исполнения, мой компьютер ведет себя одинаково, но я использую map/unmap только для того, чтобы быть в безопасности, и он не начисляет слишком много циклов.

Редактировать: Если вы хотите, чтобы команда не запускалась до того, как вы захотите, вы можете добавить пользовательское событие в входной параметр списка событий команды bufferwrite. Затем вы можете инициировать событие пользователя, чтобы начать запись, потому что команды ожидают, что все события в списке будут запущены + завершены до продолжения (если есть какие-либо указанные в входном параметре списка событий)

Смежные вопросы