背景: 我有一个名为“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]);
执行时间:66ms 没有基于编译器的矢量化
但是,如果我将行更改为:
result_tuples += (dense_id[bucket] - dense_id[bucket]);
执行时间:2ms 由编译器矢量化(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,而无需再次将其复制到主机?
如果需要,我可以在此处添加更多代码。我试图只使用必需的部分,因为我不想让你淹没在不相关的代码中。
最佳答案
我尝试了使用 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]);
到 0。
感谢您到目前为止的见解!
关于c++ - 设备上的opencl重复内存对象,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/30666132/