使用 mpirun 时,如何使分析器(valgrind、perf、pprof)拾取/使用带有调试符号的本地版本库?

Posted

技术标签:

【中文标题】使用 mpirun 时,如何使分析器(valgrind、perf、pprof)拾取/使用带有调试符号的本地版本库?【英文标题】:How to make profilers (valgrind, perf, pprof) pick up / use local version of library with debugging symbols when using mpirun? 【发布时间】:2011-10-01 19:04:04 【问题描述】:

编辑: 添加了关于调试 MPI 应用程序的重要说明

系统安装的共享库没有调试符号:

$ readelf -S /usr/lib64/libfftw3.so | grep debug
$

因此,我在我的主目录中编译并安装了我自己的版本,启用了调试 (--with-debug CFLAGS=-g):

$ $ readelf -S ~/lib64/libfftw3.so | grep debug
  [26] .debug_aranges    PROGBITS         0000000000000000  001d3902
  [27] .debug_pubnames   PROGBITS         0000000000000000  001d8552
  [28] .debug_info       PROGBITS         0000000000000000  001ddebd
  [29] .debug_abbrev     PROGBITS         0000000000000000  003e221c
  [30] .debug_line       PROGBITS         0000000000000000  00414306
  [31] .debug_str        PROGBITS         0000000000000000  0044aa23
  [32] .debug_loc        PROGBITS         0000000000000000  004514de
  [33] .debug_ranges     PROGBITS         0000000000000000  0046bc82

我已将 LD_LIBRARY_PATH 和 LD_RUN_PATH 都设置为首先包含 ~/lib64ldd program 确认应使用本地版本的库:

$ ldd a.out | grep fftw
        libfftw3.so.3 => /home/narebski/lib64/libfftw3.so.3 (0x00007f2ed9a98000)

有问题的程序是并行使用MPI(消息传递接口)的数值应用程序。因此,要运行此应用程序,必须使用mpirun 包装器(例如mpirun -np 1 valgrind --tool=callgrind ./a.out)。我使用 OpenMPI 实现。

尽管如此,各种分析器:Valgrind、CPU profiling、google-perfutils 和 perf 中的 callgrind 工具并没有找到那些调试符号,导致或多或少 无用 输出:

钙磨:

$ callgrind_annotate --include=~/prog/src --inclusive=no  --tree=none
[...]
--------------------------------------------------------------------------------
            Ir  file:function
--------------------------------------------------------------------------------
32,765,904,336  ???:0x000000000014e500 [/usr/lib64/libfftw3.so.3.2.4]
31,342,886,912  /home/narebski/prog/src/nonlinearity.F90:__nonlinearity_MOD_calc_nonlinearity_kxky [/home/narebski/prog/bin/a.out]
30,288,261,120  /home/narebski/gene11/src/axpy.F90:__axpy_MOD_axpy_ij [/home/narebski/prog/bin/a.out]
23,429,390,736  ???:0x00000000000fc5e0 [/usr/lib64/libfftw3.so.3.2.4]
17,851,018,186  ???:0x00000000000fdb80 [/usr/lib64/libmpi.so.1.0.1]

谷歌性能工具:

$ pprof --text a.out prog.prof
Total: 8401 samples
     842  10.0%  10.0%      842  10.0% 00007f200522d5f0
     619   7.4%  17.4%     5025  59.8% calc_nonlinearity_kxky
     517   6.2%  23.5%      517   6.2% axpy_ij
     427   5.1%  28.6%     3156  37.6% nl_to_direct_xy
     307   3.7%  32.3%     1234  14.7% nl_to_fourier_xy_1d

性能事件:

$ perf report --sort comm,dso,symbol
# Events: 80K cycles
#
# Overhead  Command         Shared Object                                        Symbol
# ........  .......  ....................  ............................................
#
    32.42%  a.out     libfftw3.so.3.2.4     [.]            fdc4c
    16.25%  a.out             7fddcd97bb22  [.]     7fddcd97bb22
     7.51%  a.out     libatlas.so.0.0.0     [.] ATL_dcopy_xp1yp1aXbX
     6.98%  a.out     a.out                 [.] __nonlinearity_MOD_calc_nonlinearity_kxky
     5.82%  a.out     a.out                 [.] __axpy_MOD_axpy_ij

编辑 添加于 11-07-2011: 我不知道这是否重要,但是:

$ file /usr/lib64/libfftw3.so.3.2.4
/usr/lib64/libfftw3.so.3.2.4: ELF 64-bit LSB shared object, x86-64, version 1 (SYSV), dynamically linked, stripped

$ file ~/lib64/libfftw3.so.3.2.4
/home/narebski/lib64/libfftw3.so.3.2.4: ELF 64-bit LSB shared object, x86-64, version 1 (GNU/Linux), dynamically linked, not stripped

【问题讨论】:

如果你使用Zoom 或this method of finding time drains 你不需要你的库有符号,因为你可以解决的任何问题是代码中的一行或几行,而不是外部库,并且这些线是精确的。 【参考方案1】:

如果 /usr/lib64/libfftw3.so.3.2.4 列在 callgrind 输出中,则您的 LD_LIBRARY_PATH=~/lib64 没有效果

使用export LD_LIBRARY_PATH=$HOME/lib64 重试。还要注意您调用的任何 shell 脚本,这可能会重置您的环境。

【讨论】:

你是对的。我正在使用来自 OpenMPI 的mpirun,它确实将/usr/lib:/usr/lib64: 添加到'LD_LIBRARY_PATH'(我通过运行mpirun -np 1 printenv 进行了检查)。我必须使用--prefix-x 选项来mpirun【参考方案2】:

您和受雇的俄罗斯人几乎肯定是对的; mpirun 脚本在这里搞砸了。两种选择:

实际上,大多数 x86 MPI 实现只运行可执行文件

./a.out

一样

mpirun -np 1 ./a.out.

他们不必这样做,但 OpenMPI 肯定会这样做,MPICH2 和 IntelMPI 也是如此。因此,如果您可以串行进行调试,则应该能够

valgrind --tool=callgrind ./a.out.

但是,如果您确实想使用 mpirun 运行,问题可能在于您的 ~/.bashrc (或其他)正在获取,撤消对LD_LIBRARY_PATH 等的更改。最简单的方法是在运行期间将更改的环境变量临时放入~/.bashrc

【讨论】:

不,不是这样。就是mpirun在PATH和LD_LIBRARY_PATH中添加“前缀”,可以使用mpirun -np 1 printenv查看。 如果我理解正确valgrind --tool=callgrind ./a.out 也会配置 mpirun 部分,这是我不想要的;虽然我没有检查它是否有很大的障碍。 前缀应该只是 OpenMPI 的路径,这应该是无关紧要的(除非你把 fftw 和 MPI 库放在同一个地方)。 valgrind --tool=callgrind ./a.out 不会神奇地调用 mpirun;它将启动 a.out 可执行文件。 OpenMPI 使用 '/usr' 前缀,mpirun prefixes '/usr/bin' 到 PATH,以及 '/usr/lib' 和 '/usr/lib64 '(在 x86_64 上)到 LD_LIBRARY_PATH... 这意味着 mpirun ... ./a.out 使用了没有调试信息的剥离系统安装库,而不是用户安装的带有调试信息的库。 所以你确实把所有东西都安装在了同一个地方。这不是一个好主意,但如果你只是使用包管理器为你做的任何事情,那将会发生;太糟糕了。无论如何,再一次,可以通过不运行 mpirun 来避免该问题,因为您不需要它来执行 1 个任务。如果你不相信我,试试看。【参考方案3】:

最近的分析工具通常处理这种情况的方式是查阅外部匹配的非剥离版本的库。

在基于 debian 的 Linux 发行版上,这通常是通过安装带有 -dbg 后缀的软件包版本来完成的;在基于 Redhat 的情况下,它们被命名为 -debuginfo

对于您上面提到的工具;如果调试信息包已安装在标准位置,它们通常会 Just Work (tm) 并找到库的调试符号。

【讨论】:

如果有问题的发行版是 Gentoo(我不是管理员)怎么办? @Jakub:当然在perf report 的情况下,您可以使用--symfs 选项指定一个替代位置来查找调试信息文件。您必须检查您的其他工具是否支持类似的选项。 我想我必须升级perf 才能访问--symfs 选项;至少对于 2.6.36,文档中未提及此选项。

以上是关于使用 mpirun 时,如何使分析器(valgrind、perf、pprof)拾取/使用带有调试符号的本地版本库?的主要内容,如果未能解决你的问题,请参考以下文章

mpirun - 没有足够的可用插槽

使用 CMake 编译后无法从 mpich2 使用 mpirun

无法将所有内核与 mpirun 一起使用

结束 mpirun 进程会终止 bash 循环

C:分析C程序的瓶颈

使用 maven surefire 使用 mpirun 运行 Junit 测试