Ric*_*cky 3 c compiler-construction sse intel
我有一个关于我的核心i7 920的FP峰值性能的问题.我有一个应用程序执行大量的MAC操作(基本上是卷积操作),我无法通过一个因素达到CPU的峰值FP性能当使用多线程和SSE指令时,大约是8倍.当试图找出原因是什么时,我最终得到了一个简化的代码片段,在单个线程上运行而不使用同样糟糕的SSE指令:
for(i=0; i<49335264; i++)
{
data[i] += other_data[i] * other_data2[i];
}
Run Code Online (Sandbox Code Playgroud)
如果我是正确的(数据和other_data数组都是FP),这段代码需要:
49335264 * 2 = 98670528 FLOPs
Run Code Online (Sandbox Code Playgroud)
它执行时间约为150毫秒(我非常确定这个时间是正确的,因为C计时器和英特尔VTune Profiler给出了相同的结果)
这意味着此代码段的性能如下:
98670528 / 150.10^-3 / 10^9 = 0.66 GFLOPs/sec
Run Code Online (Sandbox Code Playgroud)
这个CPU的峰值性能应该是2*3.2 GFlops/sec(2 FP单元,3.2 GHz处理器)对吗?
这个巨大的差距有什么解释吗?因为我无法解释它.
非常感谢,我真的可以使用你的帮助!
我会用SSE.
编辑:我自己运行了一些测试,发现你的程序既不受内存带宽的限制(理论上的限制比你的结果高3-4倍),也没有浮点性能(甚至更高的限制),它是有限的通过操作系统延迟分配内存页面.
#include <chrono>
#include <iostream>
#include <x86intrin.h>
using namespace std::chrono;
static const unsigned size = 49335264;
float data[size], other_data[size], other_data2[size];
int main() {
#if 0
for(unsigned i=0; i<size; i++) {
data[i] = i;
other_data[i] = i;
other_data2[i] = i;
}
#endif
system_clock::time_point start = system_clock::now();
for(unsigned i=0; i<size; i++)
data[i] += other_data[i]*other_data2[i];
microseconds timeUsed = system_clock::now() - start;
std::cout << "Used " << timeUsed.count() << " us, "
<< 2*size/(timeUsed.count()/1e6*1e9) << " GFLOPS\n";
}
Run Code Online (Sandbox Code Playgroud)
翻译g++ -O3 -march=native -std=c++0x.该计划给出
Used 212027 us, 0.465368 GFLOPS
Run Code Online (Sandbox Code Playgroud)
作为输出,虽然热循环转换为
400848: vmovaps 0xc234100(%rdx),%ymm0
400850: vmulps 0x601180(%rdx),%ymm0,%ymm0
400858: vaddps 0x17e67080(%rdx),%ymm0,%ymm0
400860: vmovaps %ymm0,0x17e67080(%rdx)
400868: add $0x20,%rdx
40086c: cmp $0xbc32f80,%rdx
400873: jne 400848 <main+0x18>
Run Code Online (Sandbox Code Playgroud)
这意味着它是完全矢量化的,每次迭代使用8个浮点数,甚至利用AVX.在玩了movntdq一些没有买任何东西的流指令后,我决定用某些东西初始化数组 - 否则它们将是零页面,只有在写入时才会映射到实际内存.改变#if 0以#if 1立即产生
Used 48843 us, 2.02016 GFLOPS
Run Code Online (Sandbox Code Playgroud)
这与系统的内存带宽非常接近(4个浮点数每两个FLOPS 4个字节= 16 GBytes/s,理论上限为DDR3的2个通道,每个10,667 GBytes/s).