当我使用太多寄存器获取内核时,我基本上可以做3个选项:
对于选项3,我想知道内核的哪个部分需要最大数量的寄存器。是否有任何工具或技术可以识别这部分?读取PTX代码(我在NVidia上开发)没有帮助,寄存器有很多高数字,说实话,我能做的最好的事情就是确定汇编代码的哪一部分映射到C代码的哪一部分。 / p>
只是注释掉一些代码并不是一个很好的方法 - 例如,我注意到如果我只是将代码放入循环中,寄存器的数量会急剧增加,而不仅仅是循环控制变量的一个。我个人怀疑NVidia编译器来自不完美的变量活体分析,但当然我对此无能为力: - )
答案 0 :(得分:1)
如果您在NVidia硬件上运行,您可以将-cl-nv-verbose编译选项传递给clBuildProgram,然后传递clGetProgramInfo CL_PROGRAM_BINARIES以获取有关编译的人类可读文本。在那里它会说它使用的寄存器数量。请注意,NVidia缓存编译并且只在内核源实际更改时才生成该注册信息,因此您可能希望在源代码中注入一些多余的更改以强制它进行完整分析。
如果您在AMD硬件上运行,只需设置环境变量GPU_DUMP_DEVICE_KERNEL = 1即可。它将在编译期间生成IL的文本文件。不确定它是否明确说明了所使用的寄存器数量,但这相当于上面的NVidia技术。
当查看该输出时(至少在nvidia上),您会发现它似乎使用了无数个寄存器(如果您按寄存器编号)。实际上,它会进行流分析并实际重用寄存器,这在查看IL时并不明显。
答案 1 :(得分:0)
这在任何语言中都是一个棘手的问题,而且可能没有一个正确的答案。但是有一些事情要考虑:
尝试获取“跨越”深度范围的变量,并尽可能使它们不跨越范围。例如,如果你有这样的东西:
int i = func1();
int j = func2(); // perhaps lots of live registers here
int k = func3(i,j);
如果func2有很多活动寄存器,你可以尝试重新排序前两行。当func2正在运行时,这会将i从实时寄存器集中移除。当然,这是一个微不足道的模式,但希望它是说明性的。 考虑摆脱只保留简单计算结果的变量。您可以在需要时重新计算这些内容。例如,如果你有类似int i = get_local_id(0)的东西,你可能只需要使用get_local_id(0)就可以使用i。
如果没有这种东西的好工具,它最终会成为艺术而不是科学。但希望其中一些有用。