我制作了这段代码来测试特征加法器与普通旧标量加法器的性能。
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在特征中的使用,我预计它会更快一些。本征真的很慢,还是我做错了什么?
答案 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,esi
为f
变量的值。
您需要一些方法来禁用循环优化。除此之外,对单个标量执行8次操作总是比8个元素的数组上的一次操作更快,因此我建议将f
变量转换为数组f[8]
,以实现与向量代码的奇偶校验。一旦你这样做,你会发现Eigen明显快于非矢量化代码。