Mac和相对强大的桌面之间令人费解的性能差异

mav*_*ick 6 c++ performance c++11

编写这段代码的初衷是测量整个数组由函数操作而不是操作数组的各个元素时的性能差异.

即比较以下两个陈述:

function_vector(x, y, z, n); 
Run Code Online (Sandbox Code Playgroud)

VS

for(int i=0; i<n; i++){
        function_scalar(x[i], y[i], z[i]);
}
Run Code Online (Sandbox Code Playgroud)

function_*一些实质但相同的计算在哪里.

随着-ffast-math开机后,标版本大约是2倍快上我已经测试在多台机器.

然而,令人费解的是两台不同机器上的时序比较,两者都使用gcc 6.3.0:

# on desktop with Intel-Core-i7-4930K-Processor-12M-Cache-up-to-3_90-GHz
g++ loop_test.cpp -o loop_test -std=c++11 -O3
./loop_test 
vector time = 12.3742 s
scalar time = 10.7406 s

g++ loop_test.cpp -o loop_test -std=c++11 -O3 -ffast-math
./loop_test 
vector time = 11.2543 s
scalar time = 5.70873 s


# on mac with Intel-Core-i5-4258U-Processor-3M-Cache-up-to-2_90-GHz
g++ loop_test.cpp -o loop_test -std=c++11 -O3
./loop_test 
vector time = 2.89193 s
scalar time = 1.87269 s

g++ loop_test.cpp -o loop_test -std=c++11 -O3 -ffast-math
./loop_test 
vector time = 2.38422 s
scalar time = 0.995433 s
Run Code Online (Sandbox Code Playgroud)

无论如何,第一台机器在高速缓存大小,时钟速度等方面都是优越的.在第二台机器上代码运行速度仍然快5倍.

题:

这可以解释一下吗?或者我在这里做错了什么?

链接到代码:https://gist.github.com/anandpratap/262a72bd017fdc6803e23ed326847643

编辑

在ShadowRanger的评论之后,我添加了__restrict__关键字to function_vector-march=nativecompilation标志.这给出了:

# on desktop with Intel-Core-i7-4930K-Processor-12M-Cache-up-to-3_90-GHz
vector time = 1.3767 s
scalar time = 1.28002 s

# on mac with Intel-Core-i5-4258U-Processor-3M-Cache-up-to-2_90-GHz 
vector time = 1.05206 s
scalar time = 1.07556 s
Run Code Online (Sandbox Code Playgroud)

Sha*_*ger 2

指针别名可能会限制向量​​化情况下的优化。

尝试将 的声明更改function_vector为:

void function_vector(double *__restrict__ x, double *__restrict__ y, double *__restrict__ z, const int n){
Run Code Online (Sandbox Code Playgroud)

使用对与C99关键字匹配的功能的g++非标准支持restrict

如果没有它,function_vector可能必须假设写入可能x[i]会修改y或中的值z,因此它无法进行预读来获取值。

  • @maverick:布莱奇,抱歉。今晚我显然无法阅读,现在看版本。是的,“-march=native”可以极大地提高性能(当然以牺牲可移植性为代价)。`-mtune` 可用于生成在给定架构上最佳的代码,而不牺牲可移植性(当然通常会生成更大的代码),因此这也是一种选择。无论如何,当您谈论矢量化代码时,您肯定需要“-march”或“-mtune”;如果没有它,编译器实际上无法使用 SSE2 后引入的现代向量指令(x86-64 上的最小基线)。 (2认同)