2017-06-08 12 views
0

OpenMPでSIMD指令をテストするためにこれらのコードを試しました。なぜ私の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 

で私が使用したSIMDディレクティブがないように、ほぼsame.Itが見えている "time_used" のための彼らの報告書を、それをコンパイル何か使いますか? ありがとう!

追加質問: 私は

a[i]=b[i]+2.1; 

によって

a[i]=pow(b[i],2.1); 

を交換し、私は

g++ -fopenmp simd.cpp 

することによって、それらをコンパイルするときに "time_used" の出力を約12000 ときです私はそれらをコンパイルします

g++ simd.cpp 

「time_used」の出力は、以前とほぼ同じ12000です。

マイコンピュータ:ハスウェルi5,8g RAM、Ubuntuのは、GCC 5.4.0

+1

関数呼び出しは、関数がSIMD呼び出しのために明示的にコンパイルされるまでベクトル化されません。そして、 'std :: pow'はおそらくその複雑さが単純な加算/乗算のレベルではないからではありません。... Btw:測定時間を"ほぼ同じ "と非常に曖昧にしてください。 – Shadow

+2

これまでのコメントのヒントとして、このような場合にはベクトル化の利点を得るために、Intel C++によって提供されるsimd mathライブラリが必要です。 – tim18

+0

@Shadow私はfuncion "pow"を単純な追加に変更しますが、以前のように加速はしません。 – manus7

答えて

1

コンパイラが自動ベクトル化機能がを呼び出すことができない、16.04を麒麟。 SIMD命令を使用して実行できる特定の算術演算のみをベクトル化できます。

したがって、SIMD命令を使用してpow関数を実装するベクトル演算ライブラリが必要です。 Intel provides onepowがベクトル最適化で提供される関数の1つであるかどうかはわかりませんが、それは想像しています。また、インテルの数学ライブラリは、AMDプロセッサでは最適でないかもしれないことに注意してください。

You claimpow関数呼び出しを単純な追加に変更しようとしましたが、結果に改善が見られませんでした。

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関数呼び出しで実行することができませんでした。ただし、オプティマイザに表示されるコードでは、... を最適化できます。場合によっては、ベクトル化できます。この場合、完全に削除することができました。

オプティマイザがこのループを完全に削除したコードを試しても、ベンチマークスコアが向上していない場合は、コード内のボトルネックではないことを明確に示しているため、ベクトル化を心配する必要はありませんそれ。

+0

申し訳ありませんアセンブリ言語を読むことができません... "#pragma omp simd"の使用方法はありますか?ありがとう! – manus7

+0

プラグマomp simdの使用法は、icpcでは問題ありません。 -fp-model sourceなどのオプションが設定されていても、-O2以上でsimdショートベクトルライブラリを呼び出すことになります。前述のように、-O0は多くのコンパイラでプラグマomp simdを無効にしている可能性があります。 g ++は通常、ライブラリ関数の呼び出し時にプラグマsimdを無視します。他の人が指摘しているように、最適化コンパイラは、副作用がないことが明らかである場合には、ループを0回または1回繰り返すことができます。 – tim18

+0

@ tim18インテルのコンパイラは、 '#pragma omp simd'であっても、不透明な関数呼び出しを自動ベクトル化しません。違いは、インテルの数学ライブラリを使用して 'pow'関数をインライン化していることです。これは、(もう不透明ではないため)最適化できることを意味します。そして、この例では、それが使用されていないことを検出するので、内部ループ内のコールを完全に削除します。あなたが[コードが使用されるように構築する](https://godbolt.org/g/YWHXef)、それはループをアンロールし、内部ライブラリ関数 '__svml_pow2'への呼び出しを出します。これは' pow '。 –

関連する問題