优化的 SIMD 向量库是否由等效的标量运算执行?
Optimized SIMD vector library is out performed by equivalent scalar operations?
我编写此代码是为了测试特征加法与普通旧标量加法的性能。
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 毫秒本征与 1 毫秒标量
使用短作为类型:54 毫秒本征与 1 毫秒标量
为什么 Eigen 比较慢?由于在 eigen 中使用 SIMD,我预计它会更快一些。 eigen真的这么慢,还是我做错了什么?
你的内部循环:
for (int i = 0; i < 80 * x; i++){
f += 2;
}
被编译器优化掉了。在 VC++ 上为 x86 编译整个循环折叠成一条汇编指令:
lea esi, DWORD PTR [esi+ecx*2]
其中ecx
是80*x的值,esi
是f
变量的值。
您将需要一些方法来禁用循环优化。除此之外,对单个标量执行 8 次操作总是比对 8 元素数组执行一次操作快,因此我建议将您的 f
变量转换为数组 f[8]
,以实现与矢量代码的奇偶校验。执行此操作后,您会发现 Eigen 明显快于非矢量化代码。
我编写此代码是为了测试特征加法与普通旧标量加法的性能。
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 毫秒本征与 1 毫秒标量
使用短作为类型:54 毫秒本征与 1 毫秒标量
为什么 Eigen 比较慢?由于在 eigen 中使用 SIMD,我预计它会更快一些。 eigen真的这么慢,还是我做错了什么?
你的内部循环:
for (int i = 0; i < 80 * x; i++){
f += 2;
}
被编译器优化掉了。在 VC++ 上为 x86 编译整个循环折叠成一条汇编指令:
lea esi, DWORD PTR [esi+ecx*2]
其中ecx
是80*x的值,esi
是f
变量的值。
您将需要一些方法来禁用循环优化。除此之外,对单个标量执行 8 次操作总是比对 8 元素数组执行一次操作快,因此我建议将您的 f
变量转换为数组 f[8]
,以实现与矢量代码的奇偶校验。执行此操作后,您会发现 Eigen 明显快于非矢量化代码。