对于opencl优化,我的想法是尝试匹配
1个工作组(内核编码)作为计算单元(GPU硬件) 1个工作项(内核编码)作为流程元素(GPU硬件) (也许我的想法不正确,请教我)
例如: 我的全球工作规模是4000乘3000。 2.我的GPU opnecl设备的最大工作组大小为8192。 3.我用所需的local-work-size(以及所有其他必要参数)调用clEnqueueNDRangeKernel 4.通过fucntion电话: 一个。 clGetKernelWorkGroupInfo(kernel,device,CL_KERNEL_WORK_GROUP_SIZE,sizeof(size_t),(void *)& workGroupSizeUsed,NULL); 湾clGetKernelWorkGroupInfo(kernel,device,CL_KERNEL_PREFERRED_WORK_GROUP_SIZE_MULTIPLE,sizeof(size_t),(void *)& workGroupSizeUsed,NULL);
a和b之上的返回8192。 最大工作组大小,CL_KERNEL_WORK_GROUP_SIZE,CL_KERNEL_PREFERRED_WORK_GROUP_SIZE_MULTIPLE均为8192。
我不知道我应该遵循什么来定义我的本地工作规模...
(Q1)设置本地工作规模有什么好主意吗? (10x10?40x30,X by Y)
clEnqueueNDRangeKernel(command_queue,kernel,2,NULL,global_work_item_size,local_work_item_size,0,NULL,NULL); 很难定义这个" local_work_item_size" clEnqueueNDRangeKernel函数。
(Q2) 如果我将局部工作量设置为1,1之间,有人可以解释这种区别 当地工作规模= 4000,3000?
提前谢谢!
答案 0 :(得分:2)
(Q1)设置本地工作规模有什么好主意吗? (10x10?40x30,X by Y)
正如pmdj所指出的,这在很大程度上取决于你的应用程序。由于目前还不清楚您如何选择 global_work_size 并且它还链接到 local_work_size ,我想首先解释一下。通常,您要做的是将要处理的数据的大小映射到 global_work_size 。例如。如果你有一个包含1024个值的数组,你也可以选择1024的 global_work_size ,因为这样你就可以轻松地将全局id用作OpenCL程序中的索引:
int index = get_global_id(0);
input_array[index]++; // your data processing
但是, global_work_size 限制为最多2 ^ 32 - 1.如果要处理的数据多于此数据,则可以将 global_work_size 和数据大小作为参数并使用如下所示的循环:
int index = get_global_id(0);
for (int i = index; i < data_size; i += global_work_size) {
input_array[i]++; // your data processing
}
global_work_size 的最后一个重要事实是它需要由 local_work_size 分割。这可能会导致您的 global_work_size 大于您的数据大小,例如:当 local_work_size 为32时,你可以得到1000个值。然后你可以使你的 global_work_size 1024并确保通过上面的条件(i&lt; data_size)来表示冗余工作项目没有做任何奇怪的事情,比如访问未分配的内存区域。
local_work_size 取决于您的平台。首先,你应该总是有一个 local_work_size ,对于NVIDIA来说是32的倍数,对于AMD GPU来说是64的倍数。这表示无论如何一起安排的操作量。如果你使用不同的数字,GPU将拥有空闲线程,除了降低你的性能之外什么都不做。
不仅要考虑制造商,还要考虑GPU的特定类型,以找到最佳 local_work_size 。 global_work_size 除以 local_work_size 是工作组的数量。每个工作组由CPU / GPU内的一个线程执行。如果您使用OpenCL在强大的硬件上运行应用程序,则需要确保它尽可能并行运行。例如。如果您使用带有8个线程的Intel i7,您需要确保至少有8个工作组(global_work_size / local_work_size&gt; = 8)。如果您使用带有1280个CUDA核心的NVIDIA GeForce GTX 1060,您可能希望拥有至少1280个工作组。但绝不会以 local_work_size 小于32为代价,这更重要!
如果您拥有的工作组多于您的硬件具有无关紧要的线程,则会按顺序处理它们。因此,对于大多数应用程序,您始终可以将 local_work_size 设置为32/64。唯一的例外是您需要在多个工作项之间进行同步。例如。障碍只在工作组内部工作,而在不同的工作组之间。示例:如果您需要在继续算法之前总结1024个值的块,则需要将 local_work_size 设置为1024,以使屏障能够按需运行。
(Q2)如果我在本地工作规模= 4000,3000之间设置本地工作规模= 1,1,有人可以解释这种差异吗?
global_work_size 和 local_work_size 都可以有多个维度。如果使用或不完全取决于程序员的偏好。所有算法也可以在一个维度上实现,并且工作组的数量通过乘以维度来计算,例如,如果你的 global_work_size 是20 * 20且你的 local_work_size 是10 * 10,你将使用(20 * 20)/(10 * 10)= 400个工作组来运行程序。
如果我正在处理具有多个维度的数据,我个人喜欢使用维度。想象一下,您的输入是一个二维图像,您可以简单地将其宽度和高度用作 global_work_size (例如1024 * 1024)和 local_work_size (例如32 * 32) 。在您的代码中,您可以使用以下索引:
int x = get_global_id(0);
int y = get_global_id(1);
input_array[x][y]++; // your data processing