opencl中的本地和全球工作规模

时间:2015-01-29 16:17:47

标签: parallel-processing opencl gpgpu

我正在尝试学习开放式课程,但有一个 我不明白的混乱之源 现在,它与这些行有关

size_t global_item_size = LIST_SIZE; // Process the entire lists 
size_t local_item_size = 64; // Divide work items into groups of 64 
ret = clEnqueueNDRangeKernel(command_queue, kernel, 1, NULL, 
        &global_item_size, &local_item_size, 0, NULL, NULL); 

我明白在LIST_SIZE线程上调用内核(我的意思是我执行了LIST_SIZE内核,希望是paralel)[对吧?]  但是什么意思

size_t local_item_size = 64; // Divide work items into groups of 64 

这是否意味着每个线程/ kernell执行64通道类似simd的波前? (如果是这样,我可以称之为双重并行化,但也许我会混淆一些东西)

有人可以澄清/帮助理解吗?,[也许可以添加一些关于在调度扭曲这些内核时需要注意什么?)

1 个答案:

答案 0 :(得分:1)

工作组大小为64意味着整个工作负载将被分成64个组。波前比工作组大小更低级,并且受硬件/驱动程序控制 - 即开发人员无法更改波前大小

工作组可以在其自身内共享本地内存,但不能与外部组共享。本地内存通常比设备的全局内存快一个数量级。无论何时需要多次读取值,都需要将该值缓存在本地内存中。

我打算列出一个长篇大论的例子,说明本地内存和工作组何时有助于提高性能,但它偏离了你的问题范围。如果你想要我,我仍然可以发布它。


修改 如果没有示例,我觉得这些信息不是很有用。假设您需要在1920x1080图像上运行模糊滤镜。假设每个像素(5x5盒子)和32位像素(类型:浮点数)周围有2像素半径。

选项1 让每个工作项加载像素的正方形区域,处理目标输出像素,并将结果写回全局内存。这将生成正确的结果,但效率低下。源图像中的每个像素将被各种工作项读取多达25次,您的全局写入也将被分散。我将列出的其他选项不描述全局写入,只描述读取性能提升。 请注意,在幕后,opencl实现仍然将您的工作划分为工作组,即使您没有在代码中使用它们。

选项2a 利用本地内存和工作组来绕过全局内存瓶颈。与现代设备上的全局内存一样快,本地内存仍然快一个数量级。本地存储器通常以或接近设备的时钟速度运行。如果使用工作组大小64处理同一图像,则工作项可以协作处理输出图像的8x8区域。工作项可以将12x12像素区域加载到本地存储器中一次,并且从本地存储器读取处理像素所需的25次读取,从而大大加快了性能。每个像素的平均全局读取数为1.497(对比25!)。 240x135工作组可以这种方式处理整个1920x1080图像。

选项2b 使用工作组大小为64,您的论坛可以处理更大的图片区域。上述2a使用工作组来处理8×8输出区域,但它仅使用12 * 12 * sizeof(浮点)(= 576字节)的本地存储器。通过增加工作组的输出区域,可以减少双倍或四倍读取的边框像素。 opencl规范说设备需要32kb的本地内存。一些数学运算确定每个工作组可以安全地处理90x90平方的像素区域 - floor(sqrt(32768 / sizeof(float))= 90.每个像素的平均全局读取现在是1.041。只需要22x12个工作组。

当您能够将全局读取数量减少近24:1时,即使是低端GPU也会突然变为ALU性能限制。