2016-10-25 12 views
2

私のコードでは、さまざまな配列を変更するさまざまな関数があり、関数の呼び出し順序が重要です。すべての関数が大きな回数呼び出されると、スレッドを作成して破壊することが大きなオーバーヘッドになっています。 自分の現在の問題を単純化しすぎている可能性があるため、私の質問に編集してください。 funcA、funcBのとFUNC Cはスレッド作成時のオーバーヘッドを避けるopenMP

void funcA (int* a, point b, int* c){ 
#pragma omp parallel for shared(a,b,c) 
    for (int ii = 0; ii < b.y; ii++){ 
     for (int jj = 0; jj < b.x; jj++){ 
      \\ alter values of a and c 
     } 
    } 
} 

void funcB (int* a, point b, int* c){ 
#pragma omp parallel for shared(a,b,c) 
    for (int ii = 0; ii < b.y; ii++){ 
     for (int jj = 0; jj < b.x; jj++){ 
      \\ alter values of a and c 
     } 
    } 
} 

double funcC (int* a, pointb, int* c){ 
    double k = 0; 
#pragma omp parallel for shared(a,b,c) reduction(+:k) 
    for (int ii = 0; ii < b.y; ii++){ 
     for (int jj = 0; jj < b.x; jj++){ 
      \\ alter values of a and c 
      k += sqrt(a[ii*jj] + c[ii**jj]); 
     } 
    } 
    return k; 
} 

ある 例

double ans = 0; 
for (int i = 0; i < 4000; i++){ 
    funcA(a,b,c); 
    funcB(a,b,c); 
    ans = funcC(a,b,c): 
} 
prinft(ans); 

すべての機能で使用され、常にではありませんされているループの最初の前に、スレッドのチームを作成するためにどのような方法があります破壊され、再び作成され、関数呼び出しで正しい順序を維持しますか?

EDIT 2:

私が探しています何がその順序でてfuncA funB、funcCを実行する方法です。しかし、関数には複数のスレッドを使用するいくつかのコードがあります。私は最初にスレッドを作成する方法が欲しいし、それらのパラレルセクションでのみ使用されるので、最後の答えが正しい。フォークを避け、40000回参加する方法はありますか?

+1

[gcc openmp thread reuse] /stackoverflow.com/questions/9076472/gcc-openmp-thread-reuse) – Zulan

+0

ここで 'k'は何をしていますか?それを合理的に賢明な使用なしで、それを扱う方法を説明することは難しいです... – Gilles

+0

@ギル私は私の質問をよりよく説明するために編集しました – Carlos

答えて

1

あなたのコードの残りの部分が正しいか、次はちょうどにあなたがそれを望むように動作するはずと仮定すると、次のようになりまし定義された異なる機能を持つ

#pragma omp parallel shared(a, b, c) 
for (int i = 0; i < 4000; i++){ 
    funcA(a,b,c); 
    funcB(a,b,c); 
    funcC(a,b,c): 
} 

void funcA(int* a, point b, int* c) { 
    #pragma omp for schedule(static) 
    for (int ii = 0; ii < b.y; ii++) { 
     for (int jj = 0; jj < b.x; jj++) { 
      \\ alter values of a and c 
     } 
    } 
} 

void funcB(int* a, point b, int* c) { 
    #pragma omp for schedule(static) 
    for (int ii = 0; ii < b.y; ii++) { 
     for (int jj = 0; jj < b.x; jj++) { 
      \\ alter values of a and c 
     } 
    } 
} 

void funcC(int* a, point b, int* c) { 
    #pragma omp for schedule(static) 
    for (int ii = 0; ii < b.y; ii++) { 
     for (int jj = 0; jj < b.x; jj++) { 
      \\ alter values of a and c 
     } 
    } 
} 

これらのOpenMP関数内のディレクティブは、OpenMP並列領域外のコードに現れる孤立ディレクティブと呼ばれます。ただし、実行時には、既存のOpenMPスレッドチームが望む方法でそれらを使用します。

さらに、それぞれのループにschedule(static)句を付けました。これはコードの正確さのために必要ではありませんが、は、各スレッドが常に関数と呼び出しの間で同じインデックスを扱うようにすることでパフォーマンスを向上させます...

+1

私はこれがOpeMPランタイム固有であることを追加したいと思います。ランタイムは自由に使用できます(長い時間使用しないとスレッドを殺すなど)。しかし、多くの「人気のある」ランタイムはスレッドを生かしています。 – Harald

+0

私の質問(私はopenMPの初心者です)にちょっとした拡張をしていますが、並列ループの機能の1つが減少していれば、スレッドの最初の作成に移行する必要がありますか? – Carlos

+0

関数内のすべてのローカル変数は 'parallel'領域内で宣言されています。したがって、それらはすべて' private'です。削減を行う場合は、関数にパラメータとして格納するために変数を渡す必要があります。この変数は 'parallel'のレベルで' reduce(:) 'として宣言されています。もう一つの可能​​性は、関数からのスレッドごとの部分的な削減結果を返し、 'parallel'領域の' reduce(:) '変数にそれらを累積することです。 – Gilles

関連する問題