我在堆栈溢出处看到了一些问题,处理相同的问题,但没有明确的答案。我想我会再问一些问题。所有这些都与手头的主题有关。
那么,我们知道从主机到openCL设备的数据传输何时发生?你能告诉我下面函数的确切内存传输操作(也就是说,调用这些函数时传输或创建的数据,如果有的话)?:
clCreateBuffer()
clSetKernelArg()
clEnqueueNDRangeKernel()
前两个甚至不会产生事件,所以我们无法计时,但肯定会在这里进行一些数据传输。
有没有办法将数据传输到设备而不先将其设置为内核arg?
从我自己的初步测试中看来,用CL_MEM_USE_HOST_PTR
创建的mem对象被设备直接操纵。为什么这是不可取的,因为这样,我们可以避免进一步的数据传输命令(当然驱动程序以最有效的方式实现这一点)?
在内核返回后,传输的数据(例如,作为内核arg的参数)是否保留在设备上以进行进一步操作?如果没有,有没有办法做到这一点?
答案 0 :(得分: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没有自己的内存并共享RAM,因此使用CL_MEM _..._ HOST_PTR标志,尤其是USE_HOST_PTR要快得多。
要检查设备是否与CPU共享RAM,请查询设备的CL_DEVICE_HOST_UNIFIED_MEMORY属性。
(从我自己的初步测试中)看来是一个mem对象 使用CL_MEM_USE_HOST_PTR创建的直接操作由 设备
即使没有map / unmap命令支持内核执行,我的计算机也表现相同,但我使用map / unmap只是为了安全,并且它不会对太多周期征税。
编辑:如果您想确保命令没有在您想要之前启动,您可以在bufferwrite命令的事件列表输入参数中添加用户事件。然后你可以触发用户事件让写入开始,因为命令等待列表中的所有事件在继续之前被触发+完成(如果在事件列表输入参数中有任何指定)