零基础入门GPGPU-SIM的Debug方法

零基础入门GPGPU-SIM的Debug方法

CAUTION:本文没有任何理论价值,且包含个人强烈观点,请谨慎阅读!!

会单步调试GPGPU-SIM非常重要,授人以鱼不如授人以渔,与其看别人对GPGPU-SIM代码的解析,倒不如我们自己单步调试模拟器程序自己领悟。B站上有一个视频叫《不要围观别人的人生》,我学习GPGPU的体系结构自己实现模拟器是我的人生,我学习别人实现好的GPGPU-SIM是围观别人的人生,我阅读别人对GPGPU-SIM总结的二手资料是围观-围观别人的人生,有的人不学习GPGPU的体系结构而只是给N卡和苏堤卡对比跑个分然后去群里黑摩尔线程,这就是围观-围观-围观-围观-围观-围观别人的人生。我们应该做尽量贴近核心圈里的事而少围观别人的人生。

另外当我们想要给模拟器增加新的功能却引入了bug的时候,也需要对代码进行调试。一个非常重要的点是GPGPU-SIM按时钟周期的节拍和部件对GPGPU硬件的各个组成部分进行精确的模拟,各个部件完全解耦,仅通过消息进行传递,很难找到一个串联起各个部件的函数调用链,其调试起来也远比指令级的模拟器更加复杂。因此需要在debug的时候选择好要切入的时间点和要关注的部件,才可以有效又精准地定位到故障。

本文书接上回:《零基础入门Likely-Convergence SIMT Stack》,以当时遇到的这个问题举例,在时钟周期为2217拍的时候,SIMT Stack第二个条目的Active Mask值不符合预期,期望是全0。下面是debug的实录。(我发誓我不是故意写出来这个bug的,,,)

首先要以debug模式重新编译GPGPU-SIM,在模拟器代码根目录下执行如下命令,这样可以在调试的时候加载GPGPU-SIM的符号表。

source setup_environment debug

make -j65536

然后将源码中的.gdbinit拷贝一份到待调试的CUDA APP的根目录下,修改~/.gdbinit,如下增加一行,将CUDA APP的根目录下的.gdbinit脚本在gdb运行时能包括进来,这样我们在调试时可以使用GPGPU-SIM提供给我们的dp <id>等命令dump出pipeline的信息。

add-auto-load-safe-path /your/cuda_app_path/.gdbinit

然后执行gdb开始调试我们的CUDA APP程序。

gdb -args ./<your_cuda_app_name>

如果出现有”loading GPGPU-Sim debugging macros...”则说明.gdbinit脚本已经被gdb成功地加载进来了。

我们先随意在程序最开始的某处打一个无关紧要的断点,然后执行r,这样的目的主要是让程序加载进全局符号表后就立刻停下,以便于我们修改变量g_single_step。

b cuda_runtime_api.cc:193

r

然后,我们修改g_single_step全局变量(注意是关注的周期数减1)然后输入c继续执行,这代表程序当运行到这个时钟周期的时候会暂停,这样可以使得我们精确地切入进我们关心的节拍数。

p g_single_step=2216

c

下面我们在我们关心的部件的代码处再打一个断点然后输入c继续执行,例如下面我们给simt_stack::update()的函数开始位置增加一个断点,然后从此处开始调试,这样我们就可以调试第2217拍下SIMT Stack部件的执行情况了。

b abstract_hardware_model.cc:1050

c

剩下的就是一路n了,最终我发现bug的root cause在于没有reset SIMT Stack新增条目的active mask,居然有这么多1,原来是bitset忘记初始化所导致的问题啊,这回我完全搞懂了。

最终我增加了一行代码,问题解决。开心。


参考文献:

[1] Mahmoud Khairy, Zhesheng Shen, Tor M. Aamodt, Timothy G Rogers. Accel-Sim: An Extensible Simulation Framework for Validated GPU Modeling. In proceedings of the 47th IEEE/ACM International Symposium on Computer Architecture (ISCA), May 29 - June 3, 2020.

编辑于 2023-07-17 10:35・IP 属地日本