为什么我在分析器中看到 __scalbnf?

Why do I see __scalbnf in my profiler?

我正在使用 perf 分析一些 C++ 代码,我发现 __scalbnf__wrap_scalbnf 占用了 运行 的大部分时间。我查了一下这些函数是什么,我最好的猜测是我通过调用 std::exp 来调用它们。但是我希望能够确认这一点。有什么地方可以让我看到实现 std::exp 的 C++ 代码来确认这一点吗?或者对我(C++ 业余爱好者)来说,开始深入研究并了解正在发生的事情的最佳方式是什么?

谢谢。

要确认 std::exp__scalbnf__wrap_scalbnf 的原因,您可以将 std::exp 调用替换为:

  • 一个恒等函数 returns 输入值
  • 或通过替代 exp 实现(例如 fm_exp,发现 here

然后,如果您仍然在探查器输出中看到 __scalbnf__wrap_scalbnf,则表示它不是来自 std::exp。

__scalbn 上设置断点。 运行 你的程序。查看回溯(在 GDB 中,bt。调用树将显示 exp()__scalbn.

的父函数

如果一个函数有多个调用者,第一个命中可能不是来自您正在分析的"hot"函数。

要真正弄清楚哪个上层函数(包括它的子函数)负责使用大量时间,请参阅 linux perf: how to interpret and find hotspots。自上而下的分析可以找到昂贵的函数,这些函数在调用其他函数时完成所有工作,即使这些其他函数也有 "innocent" 个调用者。 (例如 memcpy 被大量使用并且通常是不可避免的,但是您想要找到的是调用者使用它太多并且可以更好地优化。或者根本不调用。)


顺便说一句,是的,glibc 的数学库 exp() 实现确实在内部使用了 __scalbn。我不确定实现有多糟糕,但我没有看到 x86-64 的 asm 版本,只有这个纯 C 版本。 https://code.woboq.org/userspace/glibc/sysdeps/ieee754/dbl-64/wordsize-64/s_scalbn.c.html. (For __scalbnl(long double) there's https://code.woboq.org/userspace/glibc/sysdeps/x86_64/fpu/s_scalbnl.S.html,对 80 位浮点数使用 x87 fscale 指令。但是其他尺寸只有 i386 asm 文件。和 IA-64 (Itanium),但不是 x86-64。

glibc 确实有一些向量化的 EXP 代码,但是,比如 SSE4 SVML 版本 https://code.woboq.org/userspace/glibc/sysdeps/x86_64/fpu/multiarch/svml_d_exp2_core_sse4.S.html#_ZGVbN2v_exp_sse4


如果你想要更高的性能 exp() 而没有完美的准确性,请参阅 (那是 float,而不是 double。我忘记了是否有这样的答案双重版本)。

还相关:.