C++ FMA性能与原始计算的比较
我试图比较FMA性能(C++ FMA性能与原始计算的比较,c++,fma,C++,Fma,我试图比较FMA性能(math.h中的FMA())与浮点计算中的简单乘法和加法。测试很简单。对于大的迭代次数,我将重复相同的计算。为了进行精确的检查,我必须做到两件事 计数时间中不应包括其他计算 简单的乘法和加法不应优化为FMA 迭代不应该被优化。i、 迭代应该完全按照我的预期进行 为了实现上述目标,我做了以下工作: 函数是内联的,只包含所需的计算 使用g++-O0选项不优化乘法。(但当我查看转储文件时,它似乎为两者生成了几乎相同的代码) 已使用易失性 但结果显示,与简单的乘法和加法相比,几乎没
math.h
中的FMA()
)与浮点计算中的简单乘法和加法。测试很简单。对于大的迭代次数,我将重复相同的计算。为了进行精确的检查,我必须做到两件事
-O0
选项不优化乘法。(但当我查看转储文件时,它似乎为两者生成了几乎相同的代码)易失性
- Ubuntu 14.04.2
- G++4.8.2
- 英特尔(R)核心(TM)i7-4770(3.4GHz,8MB三级缓存)
#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;
}
#包括
#包括
#包括
#包括
使用名称空间std;
使用名称空间计时;
内联双随机数发生器(){
返回static_cast(rand())/rand_MAX;
}
挥发性双组分a、b、c;
内联void pure_fma_func(){
fma(a、b、c);
}
内联无效非函数(){
a*b+c;
}
int main(){
整数n=100000000;
a=兰德·根();
b=兰特·根();
c=兰德·根();
自动t1=系统时钟::现在();
对于(int i=0;i 是的,你做了一些完全错误的事情。至少有两件事。但让我们保持简单
Used g++ -O0 option not to optimize the multiplication
有趣的事实是:在这两种情况下,函数调用的成本都可能高于计算的成本
从根本上说,没有启用优化的基准测试的结果是完全没有意义的。你不能仅仅关闭它们,然后期待最好的结果。它们绝对必须启用
其次,FMA与常规乘法和加法的比较是一个复杂的情况——在延迟与吞吐量等问题上,乘法和加法可以成为赢家
简而言之,您的基准根本不是基准,它只是一堆随机指令,它们产生了无意义的垃圾
如果你想要一个准确的基准测试,你必须准确地再现实际的使用环境-完全。包括周围的代码,编译器优化,整个过程。是的,你做了一些完全错误的事情。至少有两件事。但让我们保持简单
Used g++ -O0 option not to optimize the multiplication
有趣的事实是:在这两种情况下,函数调用的成本都可能高于计算的成本
从根本上说,没有启用优化的基准测试的结果是完全没有意义的。你不能仅仅关闭它们,然后期待最好的结果。它们绝对必须启用
其次,FMA与常规乘法和加法的比较是一个复杂的情况——在延迟与吞吐量等问题上,乘法和加法可以成为赢家
简而言之,您的基准根本不是基准,它只是一堆随机指令,它们产生了无意义的垃圾
如果你想要一个准确的基准测试,你必须完全准确地再现实际的使用环境。包括周围的代码,编译器优化,整个系统。我用:g++test.cpp-mfma-O0-o test编译,结果显示两者都大约250ms。带-O0
的基准测试毫无价值使用-O0
和-O2
或-O3
从rom-O0
中删除多少垃圾。尤其是跳转、加载和存储,这可能会很昂贵。您的测试有点臃肿。我使用以下工具编译:g++test.cpp-mfma-O0-o test
,结果显示这两个工具都大约250ms。使用-O0
的基准测试毫无价值。比较一下用-O2
或-O3
从-O0
中删除,然后查看删除了多少垃圾。尤其是跳跃、加载和存储,这可能会很昂贵。您的测试有点臃肿。