使用gprof分析Fortran代码:scancel终止后无gmon.out的原因
为什么scancel终止不生成gmon.out,脚本限时却可以?
核心原因在于gprof只有在程序触发退出清理流程时,才会把内存里的性能采样数据写入gmon.out,两种终止方式触发的流程完全不同:
1. scancel终止的问题
scancel默认给Slurm任务发SIGTERM信号(进程没反应的话,后续会发SIGKILL强制杀死):
- 用
ifort -pg编译的程序,gprof自带的运行时库没默认处理SIGTERM信号,进程收到这个信号后直接终止,根本没机会把内存里的采样数据写到磁盘。 - 如果scancel最终发的是
SIGKILL(信号9),这是操作系统级的强制终止,进程连执行一行清理代码的机会都没有,肯定出不来gmon.out。 - 另外Slurm用scancel发信号时,可能直接终止了
srun进程,srun没来得及把信号转发给你的Fortran程序,就算转发了,SIGTERM也不在gprof的处理列表里。
2. 脚本内限时能生成的原因
你在脚本里限制运行3分钟的方式(比如用timeout命令,或者Slurm的--time参数),刚好触发了gprof能识别的退出流程:
- 要是用的
timeout命令,不少版本默认发的是SIGINT信号,而gprof的运行时库专门处理了SIGINT——收到这个信号后,会先调用_mcleanup()把采样数据写入文件,再终止程序。 - 要是用的Slurm
--time参数,任务超时后Slurm会先发SIGUSR1预警,之后才发SIGTERM,有些情况下SIGUSR1会触发程序的清理逻辑;或者你的脚本在时间到了之后,是通过主动触发程序退出的方式终止,让程序走了正常的清理流程。
解决小技巧
如果想让scancel终止后也能拿到gmon.out,可以试试:
- 用
scancel -S SIGINT命令发送SIGINT信号,而不是默认的SIGTERM,gprof会自动处理并生成文件。 - 自己给Fortran程序加个SIGTERM的信号处理函数,在函数里调用gprof的
_mcleanup()函数(注意要确保编译时正确链接了gprof的库)。
内容的提问来源于stack exchange,提问作者velenos14
相关产品推荐
相关产品推荐

