在设备上复制OpenCL内存对象

3
背景: 我有一个名为“buildlookuptable”的内核,它进行一些计算并将其结果存储在名为“dense_id”的int数组中。
创建cl_mem对象:
cl_mem dense_id = clCreateBuffer(context, CL_MEM_READ_WRITE, (inCount1) * sizeof(int), NULL, &err); errWrapper("create Buffer", err);

设置内核参数:

errWrapper("setKernel", clSetKernelArg(kernel_buildLookupTable, 5, sizeof(cl_mem), &dense_ids));

后续的其他内核都使用dense_ids。由于内存对齐不良,性能大幅下降。

以下内核以如下方式访问dense_id:

result_tuples += (dense_id[bucket+1] - dense_id[bucket]);

执行时间:66毫秒 没有基于编译器的向量化。

但是,如果我将该行更改为:

result_tuples += (dense_id[bucket] - dense_id[bucket]);

执行时间:2毫秒 通过编译器矢量化(4条)。 两个内核都在Geforce 660ti上运行。

因此,如果我删除重叠的内存访问,则速度大大提高。 线程N访问内存N,没有重叠。

为了获得正确的结果,我想复制cl_mem对象dense_id。 因此,以下内核中的行将是:

result_tuples += (dense_id1[bucket+1] - dense_id2[bucket]);

其中dense_id1和dense_id2是相同的。 另一个想法是将dense_id1的内容移动一个元素。 因此,核心代码行为:

result_tuples += (dense_id1[bucket] - dense_id2[bucket]);

作为一个小型内存对象,dense_id 可以通过复制来提高执行时间,但需要付出一定的内存代价。
问题: 在“buildlookuptable”内核执行后,我想在设备端复制结果数组 dense_id。直接的方式是在主机端使用 ClEnqueueReadBuffer 获取 dense_id,创建一个新的 cl_mem 对象并将其推回到设备端。是否有一种方法可以在“buildlookuptable”完成后复制 dense_id,而无需再次将其复制到主机端?
如果需要,我可以在此添加更多代码。我尝试只使用所需部分,因为我不想让您淹没在无关的代码中。

1
创建一个内核,它接受两个缓冲区,并将其中一个缓冲区复制到另一个缓冲区中。 - Yakk - Adam Nevraumont
1
这个(dense_id[bucket] - dense_id[bucket]);很可能被编译器简化为0,这就是你的速度来源,而不是内存读取。哦,而且复制也没有任何好处。你应该在这些情况下使用本地内存。 - DarkZeros
感谢您的评论。很抱歉回复晚了。我的电脑最近坏了,我还在重新设置OpenCL。即使编译器将其优化为0,它仍然显示这行代码占用了执行时间的大部分。我将尝试首先使用ClenqueCopyBuffer,第二个选项是另一个复制内核。 - Käptn Freiversuch
我尝试使用复制缓冲区来实现这个功能,你说得没错。性能没有改善。所以看起来编译器将其优化为零。在进行一些复制操作时,又出现了另一个问题。为了不让事情变得更复杂,我又提了一个新的问题。 - Käptn Freiversuch
1个回答

0

我尝试了使用Clenqueuecopybuffer命令的解决方案,这个解决方案达到了预期效果。 我的问题得以解决的方法是:

clEnqueueCopyBuffer(command_queue, count_buffer, count_buffer3, 1, 0, (inCount1 + 1) * sizeof(int), NULL, NULL, NULL);

在不使用另一个内核的情况下,可以仅在设备端复制内存对象。

为了实现这一点,您必须先在主机端创建另一个cl_mem对象:

cl_mem count_buffer3 = clCreateBuffer(context, CL_MEM_READ_WRITE, (inCount1 + 1) * sizeof(int), NULL, &err); errWrapper("create Buffer", err);

由于我需要等待复制完成,所以我使用了

clFinish(command_queue);

让程序等待其终止

正如DarkZeros所暗示的那样,性能提升为0,因为编译器优化了该行代码。

result_tuples += (dense_id[bucket] - dense_id[bucket]);

归零。

非常感谢您迄今为止的见解!


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接