我对OpenCL如何划分大量计算任务感到困惑。我不确定如何正确地提出问题,所以请让我从我认为OpenCL如何工作开始,然后我会根据这个例子问一个具体的问题。以下是我认为它的工作原理:
假设我想使用内核(无论它是什么)来解决给定数量的问题。我手动设置local_item_size
,然后设置global_item_size
,使其为local_item_size
大于number of problems
的倍数。像这样:
// Set work item population
local_item_size = 8;
global_item_size = (number_of_problems / local_item_size + 1) * local_item_size;
// Run
clEnqueueNDRangeKernel(queue, kernel, 1, NULL, &global_item_size, &local_item_size, 0, NULL, NULL);
所以,如果有number_of_problems = 25
,那么global_item_size = 32
。这是因为大于8
的{{1}}的最小倍数是25
。好的,很简单,内核运行,我们忽略了一些项目的结果,完成了工作。
现在让我们假设我希望我也这样做,但对于大量的工作项目。举个例子,假设我想为某些大型数组中的每个索引组合运行内核:
32
如果number_of_problems = getCombinations(input);
// Set work item population
local_item_size = _____;
global_item_size = (number_of_problems / local_item_size + 1) * local_item_size;
很大,那么input
会非常大 - 你会想到我的想法。我想明白如何明智地选择number_of_problems
。
最后,我的两部分问题:
1)使用GPU时,OpenCL:
如果答案是 a ,那么我该如何设置local_item_size
明智地以便尽可能多地使用资源(没有工作组也是如此)大)?
如果答案是 b ,那么我很困惑(我认为OpenCL有一些神奇的功能可以自动拆分工作项)!我应该重新构建内核并运行它多次,相应地改变输入吗?如果这是最好的方法,那么如何选择重建内核的次数明智地?
感谢阅读,我期待着解决这个问题!
答案 0 :(得分:1)
问题的第1部分:
您应该根据使用clGetKernelWorkGroupInfo()
功能获得的以下信息选择本地工作尺寸:
您可以使用clGetDeviceInfo()
功能查询设备中的部分信息:
换句话说,您不能使本地大小大于CL_KERNEL_WORK_GROUP_SIZE或CL_DEVICE_MAX_WORK_GROUP_SIZE,并且本地大小应该是CL_KERNEL_PREFERRED_WORK_GROUP_SIZE_MULTIPLE的倍数。无论是否存在大量问题,您都应该使用此信息来确定您的本地大小。
问题的第2部分:
主要取决于工作组的数量(即全球规模除以当地规模)。工作组通常在GPU计算单元(又称流式多处理器或SIMD核心)上执行,因此如果您的GPU具有足够的计算单元,它将以大致同时的方式安排您的工作组,如果没有,它可以处理一些工作组在每一次。
但是,性能方面最重要的方面实际上是本地大小,它决定了计算单元处理完整工作组的速度。每个计算单元都有许多处理元素(a.k.a着色器单元,CUDA核心或SIMD通道),通常可以确定可以同时执行的工作组中的工作项数量。这称为warp size(NVidia)或wavefront(AMD),是CL_KERNEL_PREFERRED_WORK_GROUP_SIZE_MULTIPLE返回的值。如果您的本地大小是此值的倍数,您的GPU将能够以最佳方式计划计算单元中的工作项,并尽快处理工作组。
请注意,这是一个简化的解释,但如果您使用CL_KERNEL_PREFERRED_WORK_GROUP_SIZE_MULTIPLE提示,则很可能会获得优化的计算。