我在内核中使用大量无符号字符,我使用clCreateBuffer创建内存对象。比我通过clEnqueueWriteBuffer将一大块无符号字符复制到此内存对象。而且我调用循环从这个内存对象读取的内核,做一些逻辑并将新数据写入同一个地方(我在这个循环中不调用clEnqueueWriteBuffer或clEnqueueReadBuffer)。这是内核代码:
__kernel void test(__global unsigned char *in, unsigned int offset) {
int grId = get_group_id(0);
unsigned char msg[1024];
offset *= grId;
// Copy from global to private memory
size_t i;
for (i = 0; i < 1024; i++)
msg[i] = in[ offset + i ];
// Make some computation here, not complicated logic
// Copy from private to global memory
for (i = 0; i < 1024; i++)
in[ offset + i ] = msg[i];
}
循环完成后(循环运行cca 1000次)然后我通过clEnqueueReadBuffer从内存对象中读取结果。
可以优化此代码吗?
答案 0 :(得分:2)
一些建议:
in += get_group_id(0) * offset
。答案 1 :(得分:1)
您可以尝试使用矢量版本(uchar8而不是uchar),但编译器可能会以这种方式对其进行优化。 最重要的是始终对您的代码进行分析和实验。
修改的
现在甚至支持uchar16: http://www.khronos.org/registry/cl/sdk/1.1/docs/man/xhtml/vectorDataTypes.html
答案 2 :(得分:0)
首先跨越头脑的是,展开你的循环可以帮助你跳过条件评估。您可以使用this pragma来简化操作。
在Nvidia芯片上使用共享内存也可能会有很大帮助(如果您当前的本地内存默认情况下不使用共享内存)
答案 3 :(得分:0)
对于优化,您需要解释您执行的计算类型。通过将计算分组到工作组中并让它们处理本地内存,可以获得性能的最大好处。您需要非常注意私有内存(最小)和本地内存(小)的大小。
你的内核多久被调用一次?所有内核都使用相同的数据吗?可以想到一个本地内存缓冲区,其中工作组中的所有线程将一部分数据读入本地内存并随后共享数据。你需要注意同步。
我建议您查看SDK供应商的示例。我只知道nVidia SDK。那里的样本非常复杂,但读起来非常有趣。
像float4shall这样的向量类型的更改适用于ATI板。据说nVidia在标量和内部编译器优化方面效果最佳。这是稍后使用分析器进行微调的内容。您可以通过内存优化获得大量的性能。