我已经尝试过这些代码来测试OpenMP中的SIMD指令。
#include <iostream>
#include <sys/time.h>
#include <cmath>
#define N 4096
#define M 1000
using namespace std;
int main()
{
timeval start,end;
float a[N],b[N];
for(int i=0;i<N;i++)
b[i]=i;
gettimeofday(&start,NULL);
for(int j=0;j<M;j++)
{
#pragma omp simd
for(int i=0;i<N;i++)
a[i]=pow(b[i],2.1);
}
gettimeofday(&end,NULL);
int time_used=1000000*(end.tv_sec-start.tv_sec)+(end.tv_usec-start.tv_usec);
cout<<"time_used="<<time_used<<endl;
return 1;
}
但要么是我用
编译的g++ -fopenmp simd.cpp
或
g++ simd.cpp
他们对“time_used”的报告几乎是一样的。看起来我使用的SIMD指令没有任何用处? 谢谢!
其他问题: 我换了
a[i]=pow(b[i],2.1);
通过
a[i]=b[i]+2.1;
当我按
编译它们时g++ -fopenmp simd.cpp
“time_used”的输出大约是12000。 当我按
编译它们时g++ simd.cpp
“time_used”的输出大约是12000,几乎和以前一样。
我的电脑:Haswell i5,8g内存,ubuntu kylin 16.04,gcc 5.4.0
答案 0 :(得分:1)
编译器无法自动向量化函数调用。它只能矢量化可以使用SIMD指令完成的特定算术运算。
因此,您需要一个使用SIMD指令实现pow
函数的矢量数学库。 Intel provides one。我不确定pow
是否是向量优化提供的功能之一,但我想是的。您还应该注意,英特尔的数学库可能不是AMD处理器的最佳选择。
You claim您尝试将pow
函数调用更改为简单添加,但未看到结果有任何改进。我不太确定这是怎么可能的,因为如果你改变内循环:
a[i]=pow(b[i],2.1);
,说:
a[i] += b[i];
或:
a[i] += (b[i] * 2);
然后GCC, with optimizations enabled, notices that you never use the result and elides the entire thing。它无法使用pow
函数调用执行此优化,因为它不知道函数是否有任何其他副作用。但是,对于优化器可见的代码,它可以......好吧,优化它。在某些情况下,它可能能够对其进行矢量化。在这种情况下,它可以完全删除它。
如果您尝试了优化程序完全删除此循环的代码,并且您仍然没有看到基准测试得分的改进,那么显然这不是代码中的瓶颈而您不必担心试图对其进行矢量化。