我正在做的是WebGL上的GPGPU,我不知道我要说的访问模式适用于一般的图形和游戏程序。在我们的代码中,经常会遇到需要对每个输出texel进行汇总或归约的数据。一个非常简单的例子是矩阵乘法,在此期间,对于每个输出纹理像素,您返回一个值,该值是一个输入的行与另一输入的列的点积。
这不是性能的关键所在,因为它不是计算量而是数据访问量的倍增。因此,我一直试图找到一种可以加快此操作速度的读取或数据布局模式,但我一直没有成功。
我将在下面描述一些假设和一些方案。所有这些的示例代码都在https://github.com/jeffsaremi/webgl-experiments下 不幸的是,由于大小原因,我无法使用StackOverflow的“代码段”功能。注意:所有示例都写入控制台而不是html页面。
基本matmul实现:示例:[2,3] x [3,4]-> [2,4]。这会以简单的形式生成(w:3,h:2)和(w:4,h:3)的2个纹理。对于每个输出纹理像素,我将沿左侧纹理的X轴读取,但沿右侧纹理的Y轴读取。 (请参阅webgl-matmul.html)
假设GPU访问的数据类似于CPU(逐块),如果我沿着纹理的宽度读取,则应该经常访问缓存。 为此,我将以仅对相应行(沿纹理宽度)进行点积处理的方式对两个纹理进行布局。示例:[2,3] x [4,3]-> [2,4]。请注意,现在对正确纹理的数据进行了转置,以便对于每个输出纹理像素,我将对左侧的一行和右侧的一行进行点积运算。 (请参阅webgl-matmul-shared-alongX.html)
为确保上述假设确实有效,我还创建了一个否定测试。在此测试中,我将沿着左右纹理的Y轴进行读取,这应该有史以来最差的性能。数据已预先转置,因此结果有意义。例如:[3,2] x [3,4]-> [2,4]。 (请参阅webgl-matmul-shared-alongY.html)。
因此,我运行了这些命令-希望您也能看得出来-并且我发现没有证据支持此类缓存行为的存在或不存在。您需要运行每个示例几次,以获得一致的结果进行比较。
然后我来到了这篇论文http://fileadmin.cs.lth.se/cs/Personal/Michael_Doggett/pubs/doggett12-tc.pdf,简而言之,我声称GPU将数据缓存在块(或我称为它们的切片)中。
基于这个有希望的线索,我创建了一个matmul(或点积)版本,该版本使用2x2的块进行计算。当然,在使用此功能之前,我必须将输入重新排列为这种布局。我的比较中不包括重新安排的费用。假设我可以这样做一次,然后运行多次。即使不采取任何措施,即使该方案也不会对性能有任何贡献。 (请参阅webgl-dotprod-tiled.html)。
至此,我完全没有想法,任何提示将不胜感激。 谢谢