首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >无法识别文件的gperftools

无法识别文件的gperftools
EN

Stack Overflow用户
提问于 2015-07-11 01:59:17
回答 2查看 518关注 0票数 1

是否有一种方法可以避免Google性能工具将文件列表为“?:?”,即找不到包含它报告的函数的文件?如何计算出包含正在调用的函数的哪个库?

代码语言:javascript
复制
$ env LD_PRELOAD="/usr/lib/libprofiler.so.0" \
   CPUPROFILE=output.prof python script.py
$ google-pprof --text --files /usr/bin/python output.prof 
Using local file /usr/bin/python.
Using local file output.prof.
Removing _L_unlock_13 from all stack traces.
Total: 433 samples
 362  83.6%  83.6%      362  83.6% dtrsm_ ??:?
  58  13.4%  97.0%       58  13.4% dgemm_ ??:?
   1   0.2%  97.2%        1   0.2% PyDict_GetItem /.../Objects/dictobject.c
   1   0.2%  97.5%        1   0.2% PyParser_AddToken /.../Parser/parser.c
...

我的目标是能够在一个包含许多编译C扩展模块的python包中分析C代码。在上面的玩具示例中,我要做什么来跟踪"dtrsm_“是在哪里定义的?如果有多个加载的库包含具有相同名称的函数,是否有任何方法可以判断正在调用哪个版本?

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2015-09-07 17:24:50

如果相同的预处理源文件(例如包含扩展的#)包含相同符号的重复定义,C/C++将不会编译。(请注意,在C++的情况下,根据编译器特定的方案,符号会被损坏,以合并参数签名,以便于重载函数,否则无法区分。)

链接器只关注未解决的符号(因此不应该有任何事情阻止多个库同时调用它们各自的内部定义函数,并使用符合的名称)。如果一个文件调用了一个已声明但未定义的函数,并且多个可用库实现了这个符号,那么链接器就可以自由地选择哪个版本在搜索路径中被替换(比如搜索路径中的优先级)。(顺便说一句,这也是分析器(如gperftools或hpctoolkit )能够注入自己并改变另一个应用程序的正常行为的相同机制。)

由于不同的库被映射到不同的内存页,所以应该能够识别(从内存地址)包含函数的执行版本的库。实际上,GNU调试器可以识别代码所包含的库,即使它无法命名函数。

代码语言:javascript
复制
$      gdb python
(gdb)  run -c "from numpy import *; linalg.inv(random.random((1000,1000)))"
CTRL-C
(gdb)  backtrace
#0 0x00007ffff5ba9df8 in dtrsm_ () from /usr/lib/libblas.so.3
...
#3 0x00007ffff420df83 in ?? () from /.../numpy/linalg/_umath_linalg.so

Linux (或者更确切地说是GNU库)提供了“回溯”调用(用于从调用堆栈获取指针列表),以及用于自动将每个指针转换为描述性字符串的"backtrace_symbols“调用,如:

代码语言:javascript
复制
"/lib/x86_64-linux-gnu/libc.so.6(__libc_start_main+0xf5) [0x7fc429929ec5]"

Gperftools (从github镜像上的查询判断)可以调用通用的“回退跟踪”,但不是"backtrace_symbols“,而是”分叉到pprof来执行实际的符号化“。这是一个相当史诗式的perl脚本,看起来很可能在哪里“?”来自于。

关键的是,google-pprof试图报告定义函数的源文件(和行号),而不是包含机器代码的二进制文件(通常在堆栈跟踪中引用)。它调用"nm“实用程序。在我的系统中(通过运行"nm -l -D"),与libc和python二进制不同的是,libblas已经删除了这样的调试符号(可能是为了优化),从而解释了结果。

要回答最初的问题:调用堆栈示例应该明确和明确地指定要调用的版本。可以使用几个月前在google中添加的选项来转储这些数据,或者(对于时间密集型的函数)可以通过使用gdb进行手动重采样来粗略确定。(甚至可以想象,可以调整g-pprof,以显式地标识输出摘要中的二进制路径。)或者,您可以在候选二进制文件/库上运行"nm“(和grep) (其中一个短列表可以通过对分析器的原始输出运行”字符串“来获得,以及其他方法)。如果源是可以访问的( grep)或者库是流行的(在网络上),那么当然(并且按照Mike ),只查询函数名可能是最简单的。理论上"??:?“可以通过仔细重新编译违规对象来解决。

票数 1
EN

Stack Overflow用户

发布于 2015-08-31 21:26:46

只需搜索令人反感的函数名。上面显示的内容在LAPACK中定义。dtrsm用于求解矩阵方程。dgemm用于乘矩阵。

你需要知道的是: 1)为什么要调用它们,2)矩阵有多大。

为了找出它们被调用的原因,我只需要检查单个堆栈样本,https://stackoverflow.com/a/4299378/23771

矩阵大小重要的原因是,如果它们很小,这些LAPACK例程实际上可以花费相当大一部分时间来分类它们的输入,例如调用函数LSAME。

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/31352682

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档