2011-11-07 2 views
5

私は私のC++コードでのOpenMPを使用して非常に奇妙な問題を抱えている:OpenMP - 簡単ループですが、無限大ですか?

void update(double *source, double *target, int n) 
{ 
    target[0] = source[0]; 
    target[n-1] = source[n-1]; 
    #pragma omp parallel for 
    for(int i = 1; i < n-1; ++i) 
     target[i] = (1.0/3.0) * (source[i-1] + source[i] + source[i+1]); 
} 

両方のソースとターゲットは、n個の要素を持つ二重の配列です。コードはOpenMPなしで使用するとうまく動作します。しかし、私がプラグマを使用するとすぐに、コードがこのループに詰まっているようです。事は次のとおりです:私は絶対になぜIDEAを持っていません。誰も私を助けることができるといいですか

+0

コンパイルし、GCC 4.6.1で正常に実行します。どのコンパイラを使用しますか? –

+0

コンパイラとオペレーティングシステムに関する詳細を追加できますか? – talonmies

+0

MacOS Snow Leopardのgcc 4.2.1、正確には:686-apple-darwin10-g ++ - 4.2.1(GCC)4.2.1(Apple Inc. build 5666)(ドット3) – Chris

答えて

2

nはどのくらいの大きさですか?

OpenMP parallel forディレクティブのデフォルトスケジューリングは、実装固有のものです。 GOMP(gccで使用されるOpenMP実装)のように見えますが、デフォルトはで、documentation hereに従っています。これは、各スレッドが隣のスレッドによってロードされるメモリ位置に(i-1i+1で)アクセスしていることを意味します。これは、キャッシュ使用率の低下につながります。現代のCPUアーキテクチャでは、このようなステンシル操作は頻繁にメモリに依存し、キャッシュに敏感です。あなたが例えば、大きな塊で、スケジュールを指定してみてください:私はちょうどここでは例として1024を使用してい

#pragma omp parallel for schedule(dynamic,1024) 

。実際には、最適なチャンクファクタを見つけるために実験を行う必要があります(または、パラメータスイープを使用して系統的に検索する、「自動チューニング」と呼ばれるプロセス)。あるいは、CPUのL1またはL2キャッシュサイズから派生させるなど、理論に基づいた値を選択することもできます。

また、forループ内の計算量がスレッド間で均一で、動的スケジューラのオーバーヘッドがボトルネックの原因になる場合があるため、静的スケジューリングを試すこともできます。

#pragma omp parallel for schedule(static) 

をチャンクサイズなしで指定すると、各スレッドにほぼ同じサイズの1つのチャンクが割り当てられます。

最後に、OpenMPスレッドを独自のCPUコアに固定することもできます。これは、環境変数GOMP_CPU_AFFINITYを使用して行うことができます。

編集:

私は、GCC 4.2.1でコンパイルされた次のテストプログラムで遊んでた、と私は、私は上記にリンクされているドキュメントが間違っていると思います。 GOMPのデフォルトはschedule(static)です。

#include <stdio.h> 
#include <omp.h> 

int main(int argc, char** argv) 
{ 
    int i; 
    #pragma omp parallel for 
    for (i=0; i<15; i++) { 
     int id = omp_get_thread_num(); 
     printf("%d assigned to thread %d\n", i, id); 
    } 
} 

そして、二つのスレッドでの出力は次のとおりです。

$ ./test_sched | sort -n 
0 assigned to thread 0 
1 assigned to thread 0 
2 assigned to thread 0 
3 assigned to thread 0 
4 assigned to thread 0 
5 assigned to thread 0 
6 assigned to thread 0 
7 assigned to thread 0 
8 assigned to thread 1 
9 assigned to thread 1 
10 assigned to thread 1 
11 assigned to thread 1 
12 assigned to thread 1 
13 assigned to thread 1 
14 assigned to thread 1 
+0

スケジューリングが定義されていないときのデフォルトは、 AFAIKは通常「静的」です。 '(dynamic、1)'がデフォルトであることを示唆しているGOMPリンクは実際に 'schedule(runtime)'が使われている場合を指しています。 – eran

関連する問題