我正在使用perf
对一些C ++代码进行概要分析,并且发现__scalbnf
和__wrap_scalbnf
占用了大量的运行时间。我查看了这些功能是什么,我最好的猜测是我通过调用std::exp
来调用它们。但是,我希望能够确认这一点。在哪里可以看到C ++代码实现std :: exp来确认这一点?还是对我(C ++业余爱好者)来说,开始深入研究并了解正在发生的事情的最佳方法是什么?
谢谢。
答案 0 :(得分:1)
要确认std::exp
是__scalbnf
和__wrap_scalbnf
的原因,您可以用以下任一方法替换std::exp
调用:
然后,如果您仍然在探查器输出中看到__scalbnf
和__wrap_scalbnf
,则表明它不是来自std :: exp。
答案 1 :(得分:1)
在__scalbn
上设置一个断点。运行程序。查看回溯(在GDB中,bt
)。调用树将显示exp()
是__scalbn
的父函数。
如果一个函数有多个调用者,则第一个匹配项可能不是您正在分析的“热门”函数。
要真正弄清楚哪个上级功能(包括其子级)是造成大量时间的原因,请参见linux perf: how to interpret and find hotspots 。自上而下的概要分析可以找到昂贵的函数,这些函数可以在对其他函数的调用中完成所有工作,即使这些其他函数也具有“无辜的”调用者。 (例如memcpy
经常被使用并且经常不可避免,但是您想要找到的调用者使用它过多并且可以进行更好的优化。或者根本不被调用。)
顺便说一句,是的,glibc的math lib exp()
实现确实在内部使用__scalbn
。我不确定实现的糟糕程度,但是我看不到x86-64的asm版本,只有这个纯C版本。 https://code.woboq.org/userspace/glibc/sysdeps/ieee754/dbl-64/wordsize-64/s_scalbn.c.html。 (对于__scalbnl(long double)
,有https://code.woboq.org/userspace/glibc/sysdeps/x86_64/fpu/s_scalbnl.S.html,使用x87 fscale
指令进行80位浮点运算。但是只有其他大小的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()
而又没有完美的准确性,请参阅Fastest Implementation of Exponential Function Using AVX(这是针对float
的,而不是double
的。我忘记了是否有SO答案是双版本)。