优化的SIMD向量库是通过等效标量操作执行的吗?

时间:2015-03-14 00:40:29

标签: c++ eigen simd

我制作了这段代码来测试特征加法器与普通旧标量加法器的性能。

int x, y;
cin >> x; cin >> y;
typedef int theType;
Array<theType, 8, 1> theArray; theArray << 0,0,0,0,0,0,0,0;
StopWatch sw;
sw.Start();
for(int k = 0; k < y*1000000; k++){
    theArray << 0,0,0,0,0,0,0,0;
    for (int i = 0; i < 10 *x; i++){
        theArray += 2;
    }
}
sw.Stop();
cout << theArray << " : " << sw.MilliSeconds() << endl;

theType f = 0;
sw.Start();
for(int k = 0; k < y*1000000; k++){
    f = f-1;
    for (int i = 0; i < 80 * x; i++){
        f += 2;
    }
}
sw.Stop();
cout << f << " : " << sw.MilliSeconds();

我正在运行使用g ++ -O2的代码。我用命令行设置x和y,并将它们用作for循环中的上限,这样编译器就不会优化for循环。特征测试产生一个包含8个值的数组,并添加一个恒定的分量。标量测试只是递增标量值,但它的执行次数是本征测试的8倍。

结果(使用x = 1,y = 1):

使用int作为类型:52 ms Eigen与1ms标量

使用short作为类型:54 ms Eigen与1ms标量

为什么Eigen较慢?由于SIMD在特征中的使用,我预计它会更快一些。本征真的很慢,还是我做错了什么?

1 个答案:

答案 0 :(得分:1)

你的内心循环:

for (int i = 0; i < 80 * x; i++){
    f += 2;
}

由编译器优化。在VC ++ for x86上进行编译,整个循环折叠成一个单独的汇编指令:

lea esi, DWORD PTR [esi+ecx*2]

ecx的值为80 * x,esif变量的值。

您需要一些方法来禁用循环优化。除此之外,对单个标量执行8次操作总是比8个元素的数组上的一次操作更快,因此我建议将f变量转换为数组f[8],以实现与向量代码的奇偶校验。一旦你这样做,你会发现Eigen明显快于非矢量化代码。