c++ - callgrind 有合理的替代品吗?

标签 c++ profiling valgrind

我有一个带有内部循环的程序,由于它执行的迭代次数需要非常快。为了分析此代码,我一直在使用 valgrind/callgrind。我发现它是一个很棒的工具。不幸的是,我在优化方面的努力使我开始使用新的指令集,例如 fma (intel)/fma4 (amd),每当我使用这些 callgrind 时就会崩溃,因为它不支持这些指令。

我知道一种解决方案是简单地不使用这些内在函数,并让编译器发出不包含这些指令的代码,但老实说,我认为这样做没有任何意义,我想按原样分析代码, valgrind 无法处理它。

这引出了我的问题。 是否有任何开源或免费的分析器可以像 valgrind/callgrind 一样出色?我了解 gprof,但据我了解,它本质上只是偶尔停止程序并查看它在哪里,并计算它看到每个东西的次数,与 callgrind 给我的东西相比,这就像撕掉一只眼睛。

最佳答案

我可能会坚持使用 valgrind/callgrind:

在不同的处理器上尝试编译标志 mavxmfma4 也会给我带来问题:FMA4 主要是 AMD 功能,尽管对它的支持正在过滤到 Intel 芯片中,而 AVX 主要是 Intel 功能(支持被过滤到 AMD 芯片中),但是在 AMD 上的基准测试中,当支持 AVX 时,实际上执行速度比使用 SSE1/2/3/4 慢(FMA4 填充 SSE5 123 )。

使用这两种优化可能不是最好的方法,并且很可能会导致您遇到的行为,因为它们实际上是相互对立的,主要是为特定品牌的处理器设计的。如果您正在为支持 AVX 的 Intel CPU 进行编译,请尝试删除 FMA4;如果您正在为支持 FMA4 的 AMD 处理器进行编译,请尝试使用 FMA4。

话虽如此,编译器不允许将乘法和加法组合到 FMA 中,因为这会将 FMA 中的 2 舍入减少为 1 舍入,因此,您需要使用宽松的浮点模型(类似于 - ffast-math *) 或通过转换 lutiply 并添加到 FMA 来导致 IEEE 浮点合规性失败。不确定当您专门调用内在函数时它是如何工作的,但编译器可能不会根据标志优化它们,因为它们是非常具体的指令。

我的 Intel CPU 上的 FMA 标志 (mfma4) 可靠地产生相同的结果,valgrind 抛出与您发布的类似的嘶嘶声,但它在 AMD CPU 机器上表现良好,(我想你的处理器是英特尔的?):

vex amd64->IR: unhandled instruction bytes: 0xC4 0x43 0x19 0x6B 0xE5 0xE0 0xF2 0x44
vex amd64->IR:   REX=0 REX.W=0 REX.R=1 REX.X=0 REX.B=1
vex amd64->IR:   VEX=1 VEX.L=0 VEX.nVVVV=0xC ESC=0F3A
vex amd64->IR:   PFX.66=1 PFX.F2=0 PFX.F3=0

这是来自下面的测试代码。

FMA3 内在函数:(AVX2 - Intel Haswell)

_mm_fmadd_pd(), _mm256_fmadd_pd()
_mm_fmadd_ps(), _mm256_fmadd_ps()

除此之外还有很多很多......

FMA4 内在函数:(XOP - AMD Bulldozer)

_mm_macc_pd(), _mm256_macc_pd()
_mm_macc_ps(), _mm256_macc_ps()

除此之外还有很多很多......

注释

FMA 为计划成为 SSE5 一部分的功能提供支持,例如:

XOP:整数 vector 乘法累加指令、整数 vector 水平加法、整数 vector 比较、移位和旋转指令、字节排列和条件移动指令、浮点分数提取。 FMA4:浮点 vector 乘法累加。 F16C:半精度浮点转换。

测试代码

float vfmaddsd_func(float f1, float f2, float f3){
  return f1*f2 + f3;
}


int main() {
  float f1,f2,f3;
        f1 = 1.1;
        f2 = 2.2;
        f3 = 3.3;
        float f4 = vfmaddsd_func(f1,f2,f3);
        printf("%f\n", f4);
        return 0;
}

关于c++ - callgrind 有合理的替代品吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/22801787/

相关文章:

java - 您将如何分解和记录应用程序不同部分的执行时间?

ruby - 使用 rack-perftools_profiler 分析 Sinatra(使用 net/http)

python - 使用 memory_profiler 分析 Flask 应用程序中的行

c - 了解 Valgrind 输出

c++ - 将 fopen() 与绝对路径指针一起使用

c++ - 使用 rtsp、visual studio OpenCv 2.4.5 访问 IP 摄像机?

c++ - 从二进制文件中读取 std::string

c++ - 如何在不违反封装的情况下合法访问和修改私有(private)字段 vector 和 map?

c - Valgrind:地址 0x0 未被堆叠、分配或(最近)释放仅用于较大的输入值

c++ - MPI 和 Valgrind 不显示行号