0

我已经在 OpenCl 程序中工作了很长一段时间,但我陷入了一个有趣的问题。重要的是,虽然我是一名爱好者,但我在编码/编程方面没有深厚的背景。

CodeXL 提出的程序瓶颈是 VGPR 寄存器的大量使用。因此,我正在重写代码以尽可能基于标量操作运行:

CodeXL 统计打印输出

我已经成功地将几行代码从基于向量的操作转换为标量操作。例如:

**((uint8 *)VectorArray)[0] = ((__global uint8 *)InputData)[0];**

标量变为:

 s0 = ((__global uint *)InputData)[0];  
 s1 = ((__global uint *)InputData)[1];  
 s2 = ((__global uint *)InputData)[2];  
 s3 = ((__global uint *)InputData)[3];  
 s4 = ((__global uint *)InputData)[4];  
 s5 = ((__global uint *)InputData)[5];  
 s6 = ((__global uint *)InputData)[6];  
 s7 = ((__global uint *)InputData)[7];

s0-s7 进一步用于一堆操作。这无缝地工作,项目的性能只提高了一个档次。我知道我可以直接访问 VectorArray.s0,但“s0”是一个具有多个读/写访问权限的局部变量。

最后,我坚持的部分是:

((uint4*)VectorArray)[4] = ((__global uint4*)InputData)[4];`

考虑到上述相同的逻辑,标量加载操作将是:

    s4 = ((__global uint *)InputData)[4];
    s5 = ((__global uint *)InputData)[5]; 
    s6 = ((__global uint *)InputData)[6];  
    s7 = ((__global uint *)InputData)[7]; 

然而,它惨遭失败。我尝试了超过 40 种组合,似乎我遗漏了一些要点。Radeon GPU Analyzer 指出 ISA 是一个s_load_dwordx4操作,操作数为s[4:7], s[6:7], 0x40。我假设 0x40 是 64 位的参考偏移量,因此位置应该在同一范围内偏移。然而,我已经做过的一项试验是考虑s5 = ((__global uint *)InputData)[4];——这是失败的原因之一。

ISA 文档对此事的了解非常少,我几乎一无所知。

任何提示或意见?非常感激。

谢谢你。埃德。

4

1 回答 1

0

据我记得,AMD GPU 中的“标量”寄存器用于线程之间共享的数据。所以这通常是循环计数器之类的东西,编译器可以保证这些值在跨线程的锁步中是相同的。

如果你看到太多的向量寄存器压力,这通常意味着你使用了太多的private“内存”。例如,您将数组声明为private,或者您有长期存在的变量,其“内存”(向量寄存器)不能用于其他变量。

我推荐阅读 AMD 的优化指南;据我记得,它详细介绍了向量和标量寄存器之间的差异,以及它们的用途。正如您所发现的,您建议的代码转换类型通常没有效率。您没有解释代码的作用或所有这些向量寄存器的用途,但根据用例,您可能需要考虑将更大、寿命更长的数组从private内存local中移动。(请记住,这是在工作项之间共享的)

于 2020-10-07T08:10:41.093 回答