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 过滤器将包括多个工作组。