Performance OpenCL全局工作补偿意味着性能受到影响?
我有一个处理大型图像的内核(OpenCL1.1,数据类型是image2d\u t)。有时我只想处理这个图像的一个区域。显而易见的解决方案是使用全局工作偏移。我希望这会带来性能提升,但到目前为止,使用非零偏移量只能得到更糟糕的执行时间Performance OpenCL全局工作补偿意味着性能受到影响?,performance,opencl,Performance,Opencl,我有一个处理大型图像的内核(OpenCL1.1,数据类型是image2d\u t)。有时我只想处理这个图像的一个区域。显而易见的解决方案是使用全局工作偏移。我希望这会带来性能提升,但到目前为止,使用非零偏移量只能得到更糟糕的执行时间 // Image is 4096x4096 pixels. Local work size is 8x8. // // Example A: globalWorkSize = { 4096, 4096 }; globalWorkOffset = { 0, 0 };
// 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
//图像为4096x4096像素。本地工作大小为8x8。
//
//示例A:
globalWorkSize={40964096};
globalWorkOffset={0,0};
//执行时间为38秒
//
//例B:
globalWorkSize={32963296};
globalWorkOffset={400400};
//执行时间为58秒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中计算单元数的精确倍数,则同一个计算单元可能无法从一级缓存中的最后一条扫描线获取缓存数据(请记住高斯滤波器之类的Z顺序访问和相邻访问)
但这并不能保证,只是为了最大的内核占用而分配工作项的本能,gpu的每个内核都通过迭代的工作分配来平均加载,而不是:先填充,然后填充第二个,然后填充第三个,等等。。。。填充第一个堆芯有助于提高堆芯效率,但让其他堆芯空置将破坏imho拥有更多堆芯的优势。这还需要一个远程过滤内核。5x5过滤器将仅受益于边缘像素,而51x51过滤器将包括多个工作组。尽管使用图像似乎是正确的选择,但可能并非总是如此
如果不需要像素之间的插值,也不需要边界颜色处理,那么最好在图像上使用缓冲区
即使您需要处理边界颜色,您也可以使用单独的内核来处理边缘区域和缓冲区,这可能会提供更好的性能
提高图像性能的原因在于能够从内存一次加载多个像素,在某些体系结构中,指令一次可以加载128位
说到实际问题,
我猜hw确实使用偏移量和工作id计算每个像素的实际坐标。我们可以看到您的内核吗(不一定是所有内核,但是输入、输出、循环的一般结构等等)?这里没有太多的内容。我将尝试制作一个最小的示例来演示这个问题。您是否尝试过将偏移量与64对齐?任何未对齐的东西都会破坏GPU的性能。非常有趣!你有访问CL内核的程序集的权限吗?
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