2016-11-16 7 views
8

を阻害する:OpenMPのparalelization私はOpenMPのに新しいですし、私は、OpenMPを使用して、次のコードをparalelizeしようとしていますベクトル

#pragma omp parallel for 
for(int k=0;k<m;k++) 
{ 
    for(int j=n-1;j>=0;j--) 
    { 
     outX[k+j*m] = inB2[j+n * k]/inA2[j*n + j]; 

     for(int i=0;i<j;i++) 
     { 
      inB2[k*n+i] -= inA2[i+n * j] * outX[k + m*j]; 
     } 
    } 
} 

Paralelize外側のサイクルは非常に単純明快ですが、それを最適化するために、私はparalelizeしたかったです最も内側のサイクル(iを反復するサイクル)も同様です。私はこのようなことをしようとするとき、しかし:

#pragma omp parallel for 
for(int i=0;i<j;i++) 
{ 
    inB2[k*n+i] -= inA2[i+n * j] * outX[k + m*j]; 
} 

をコンパイラは、それが遅くなる可能インナーサイクル(「ための可能なエイリアシングのベクトル化のためのバージョン管理ループ」)、ベクトル化されません。私はそれを使用してコンパイルしましたgcc -ffast-math -std=c++11 -fopenmp -O3 -msse2 -funroll-loops -g -fopt-info-vec prog.cpp

ありがとうございました!

EDIT:配列に__restrictキーワードを使用しています。

EDIT2興味深いのは、プラグマのみを内側のサイクルに置き、外側から削除すると、gccがそれをベクトル化するということです。ですから、私は両方のサイクルをパラレル化しようとすると、問題が発生します。

EDIT3:#pragma omp parallelをsimdに使用すると、コンパイラはループをベクトル化します。しかし、内部ループを並列化しないよりもまだ遅いです。

+0

手動でベクトル化する方が、並列化する方が簡単です。なぜそれをしないのですか? (そして自動並列化を維持する) –

答えて

1

お返事ありがとうございます。私は#pragma omp parallel for simdを使って内部ループをベクトル化することができましたが、プログラムは並列化しないよりも遅かったです。私は最終的に、はるかに速く、問題を解決するために少し異なるアルゴリズムを発見した。 あなたの助けをいただきありがとうございます!

+1

通常は、VIPO(Vectorize Inner、Parallel Outer)が最適です。内部ループ上の純粋なSIMD(No 'parallel for')、そして外部ループを並列化するかどうかは、通常、test-it-n-endevourを参照してください。帯域幅が限られている状況では、プリフェッチが役立つことがありますが、キャッシュミスではほとんど実用的でないコアが多数発生します。一方、単一のコアでは、まれに簡単に正しいと推測されます。 – Holmz

1

私の推測では、内部ループを並列化した後で、コンパイラがinA2inB2およびoutXのトラックを失ったと思います。デフォルトでは、ポインタによって指し示されたメモリの領域が互いに重複していると想定しています。 C言語では、C99標準はrestrictキーワードを導入しました。これは、ポインタが他のポインタによって指し示されていないメモリブロックを指し示していることをコンパイラに知らせます。 C++にはこのようなキーワードはありませんが、幸いにもg++には適切な拡張子があります。ループによって触れられたポインタの宣言に__restrictを追加しようとします。例えば、

double* __restrict outX; 
+0

不幸なことに、これは当てはまりません。私は__restrictを使用しています。良い点、私はそれをOPに追加します。 –

1

double* outX; 

を交換するあなたが最初vecotorzed内側のループを作ってみましたがありますか?その後、

#pragma omp parallel for 
for(int k=0;k<m;k++) 
{ 
    for(int j=n-1;j>=0;j--) 
    { 
     outX[k+j*m] = inB2[j+n * k]/inA2[j*n + j]; 
Q1 = k*n 
Q2 = n*j 
Q3 = m*j + k 
#pragma omp declare simd private(i,j,k,m,Q1,Q2,Q3) linear(i) uniform(outX,inA2,inB2) shared(inB2,inA2,outX) 
     for(int i=0;i<j;i++) 
     { 
      inB2[Q1+i] -= inA2[Q2+i] * outX[Q3]; 
     } 
    } 
} 

それは常に正しいなどの共有、国民との#pragmaを取得私にいくつかの時間がかかる(キャッシュミスに応じて、パフォーマンスが低下する可能性がある)平行部を追加...そして私はテストしていませんこの。

+0

アイデアありがとう。 EDIT3で触れたように、私は単純に#pragma omp parallelを使ってベクトル化してベクトル化しています。しかし、内部ループをパラレル化しないよりもまだ遅いです。 –

+0

これは、計算上制限されているのではなく、帯域幅が制限されていることを示している可能性があります。 – Holmz

関連する問題