何时进行OpenCL数据传输?

时间:2016-11-18 22:46:13

标签: c opencl gpgpu

我在堆栈溢出处看到了一些问题,处理相同的问题,但没有明确的答案。我想我会再问一些问题。所有这些都与手头的主题有关。

那么,我们知道从主机到openCL设备的数据传输何时发生?你能告诉我下面函数的确切内存传输操作(也就是说,调用这些函数时传输或创建的数据,如果有的话)?:

clCreateBuffer()

clSetKernelArg()

clEnqueueNDRangeKernel()

前两个甚至不会产生事件,所以我们无法计时,但肯定会在这里进行一些数据传输。

有没有办法将数据传输到设备而不先将其设置为内核arg?

从我自己的初步测试中看来,用CL_MEM_USE_HOST_PTR创建的mem对象被设备直接操纵。为什么这是不可取的,因为这样,我们可以避免进一步的数据传输命令(当然驱动程序以最有效的方式实现这一点)?

在内核返回后,传输的数据(例如,作为内核arg的参数)是否保留在设备上以进行进一步操作?如果没有,有没有办法做到这一点?

1 个答案:

答案 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命令的事件列表输入参数中添加用户事件。然后你可以触发用户事件让写入开始,因为命令等待列表中的所有事件在继续之前被触发+完成(如果在事件列表输入参数中有任何指定)