2

我有一个处理大图像的内核(OpenCL 1.1,数据类型是 image2d_t)。有时我只想处理这个图像的一个区域。显而易见的解决方案是使用全局工作偏移。我希望这会产生性能提升,但到目前为止,我只会在非零偏移量下得到更差的执行时间!

// Image is 4096x4096 pixels. Local work size is 8x8.
//
// Example A:
globalWorkSize = { 4096, 4096 };
globalWorkOffset = { 0, 0 };
// Execution time is 38 seconds
//    
// Example B:
globalWorkSize = { 3296, 3296 };
globalWorkOffset = { 400, 400 };
// Execution time is 58 seconds <------------------ ?!
//
// Example C: Cropped image @ 3296x3296 pixels
globalWorkSize = { 3296, 3296 };
globalWorkOffset = { 0, 0 };
// Execution time is 28 seconds

有人可以解释为什么我得到这些结果吗?

4

2 回答 2

1

Lubo Antonov 关于数据访问对齐对性能很重要的观点是正确的。但另一个参数是以跨步模式访问内存。

从 x=400 和 y=400 开始的示例是:

. = item
x = work item
c = memory channel
stride = 4096 between y_item=1 and y_item=2 and in this stride, 
some of memory channels are left in "." areas and unused

  unused channel
  ^
  | 
  c c c c c c c c c c
  . . . . . . . . . . 
  . x x x x x x x x x
  . x x x x x x x x x
  . x x x x x x x x x
  . x x x x x x x x x
  . x x x x x x x x x
  . x x x x x x x x x
  . x x x x x x x x x
  . x x x x x x x x x
  . x x x x x x x x x

当然,前 400 个未使用的像素中有更多通道,但其中一些通道​​的数量少于“x”工作区域中的其他通道。例如,通道 2、3、4、5、6、7 在“x”中被访问了 20 次,但通道 1 被访问了 25 次,这迫使对它进行比其他通道更序列化的访问。

如果跨步区域的内存通道数量与非跨步区域不同,则高 2 次方跨步内存访问使用较少的内存通道/存储库并降低性能。


硬件对性能的 Z 排序支持的优势也可能在工作区的左边缘被破坏。


如果每个扫描线不是 gpu 中计算单元数量的精确倍数,则同一计算单元可能无法从 L1 缓存中的最后一个扫描线获取缓存数据(请记住 Z 排序访问和高斯滤波器之类的邻居访问)

   c = compute unit, S=selected compute unit for observation
   kernel is accessing neighbour pixels too, for filtering, for example

   gpu has 10 compute units   

   strided: L1 cache not hit
   ..........
   .cccSccccc
   .ccccScccc
   .cccccSccc
   .ccccccScc
   .cccccccSc
   .ccccccccS

   non-strided: pixel[y-1] is already in L1, cache hit, more performance
   ..........
   cccScccccc
   cccScccccc
   cccScccccc
   cccScccccc
   cccScccccc

但这并不能保证,只是一种关于工作项的本能是为了最大核心占用而分配的,其中 gpu 的每个核心都通过迭代工作分配来平均加载,而不是这样:先填充,然后填充第二个,然后填充第三个,等等....填充第一个核心将有利于该核心效率,但让其他核心空置会破坏拥有更多核心恕我直言的优势。这也需要一个远程过滤内核。5x5 过滤器将仅受益于边缘像素,而 51x51 过滤器将包括多个工作组。

于 2017-03-12T16:36:38.010 回答
1

尽管使用图像似乎是正确的选择,但可能并非总是如此。

如果您不需要像素之间的插值并且不需要边框颜色处理,那么在图像上使用缓冲区可能会更好。

即使您有边界颜色要处理,您也可以使用单独的内核来处理边缘区域和缓冲区,这可能会提供良好的整体性能。

使用图像获得更好性能的原因来自于从内存中一次加载多个像素的能力,在某些架构中,指令一次可以加载 128 位。

谈到实际问题,我的猜测是 hw 确实使用偏移量和工作 ID 计算每个像素的实际坐标。

于 2017-03-12T19:23:21.260 回答