与天真计算相比,FMA表现

Jon*_*ark 0 c++ fma

我试图在浮点计算中比较FMA性能(fma()in math.h)与朴素乘法和加法.测试很简单.我将为大迭代次数迭代相同的计算.我需要做两件事才能进行精确检查.

  1. 在计算时间时不应包括其他计算.
  2. 天真的乘法和加法不应该优化为FMA
  3. 迭代不应该优化.即迭代应该完全按照我的预期进行.

为了实现上述目标,我做了以下事情:

  1. 函数是内联的,仅包含所需的计算.
  2. 使用g ++ -O0选项不优化乘法.(但是当我查看转储文件时,它似乎为两者生成几乎相同的代码)
  3. 用过volatile.

但结果显示,fma()与天真的乘法和加法相比几乎没有差异,甚至更慢.它是我想要的结果(即它们在速度方面没有真正的不同)或者我做错了什么?

规格

  • Ubuntu 14.04.2
  • G ++ 4.8.2
  • Intel(R)Core(TM)i7-4770(3.4GHz,8MB L3缓存)

我的守则

#include <iostream>
#include <cmath>
#include <cstdlib>
#include <chrono>
using namespace std;
using namespace chrono;

inline double rand_gen() {
    return static_cast<double>(rand()) / RAND_MAX;
}

volatile double a, b, c;
inline void pure_fma_func() {
    fma(a, b, c);
}
inline void non_fma_func() {
    a * b + c;
}


int main() {
    int n = 100000000;

    a = rand_gen();
    b = rand_gen();
    c = rand_gen();

    auto t1 = system_clock::now();
    for (int i = 0; i < n; i++) {
        non_fma_func();
    }
    auto t2 = system_clock::now();
    for (int i = 0; i < n; i++) {
        pure_fma_func();
    }
    auto t3 = system_clock::now();

    cout << "non fma" << endl;
    cout << duration_cast<microseconds>(t2 - t1).count() / 1000.0 << "ms" << endl;
    cout << "fma" << endl;
    cout << duration_cast<microseconds>(t3 - t2).count() / 1000.0 << "ms" << endl;
}
Run Code Online (Sandbox Code Playgroud)

Pup*_*ppy 7

是的,你做的事情完全错了.至少有两个人.但是让我们保持简单.

Used g++ -O0 option not to optimize the multiplication
Run Code Online (Sandbox Code Playgroud)

这使得您的整个结果完全无关紧要.有趣的事实:在任何一种情况下,函数调用的成本可能都大于计算的成本.

从根本上说,未启用优化的基准测试结果完全没有意义.你不能把它们关掉,希望最好.绝对必须启用它们.

其次,FMA与常规的乘法和加法是一个复杂的情况 - 有一些事情,如延迟与吞吐量和其他事项,其中乘法和加法可以是胜利者.

简而言之,您的基准测试根本不是基准,它只是一堆产生无意义垃圾的随机指令.

如果您需要准确的基准测试,则必须完全准确地重现实际使用情况.包括周围的代码,编译器优化,整个shebang.