6

私は OpenMP を初めて使用し、個々のスレッドを開始して 2D 配列内の各アイテムを処理しようとしています。

本質的に、これは:

for (i = 0; i < dimension; i++) {
    for (int j = 0; j < dimension; j++) {
        a[i][j] = b[i][j] + c[i][j];

私がやっていることはこれです:

#pragma omp parallel for shared(a,b,c) private(i,j) reduction(+:diff) schedule(dynamic)
    for (i = 0; i < dimension; i++) {
        for (int j = 0; j < dimension; j++) {
            a[i][j] = b[i][j] + c[i][j];

これは実際に各 2D アイテムのスレッドを開始しますか? どうやってそれをテストしますか?それが間違っている場合、それを行う正しい方法は何ですか? ありがとう!

注: コードは大幅に簡略化されています

4

2 に答える 2

7

コード サンプルでは、​​外側のループのみが並列です。内側のループで印刷omp_get_thread_num()してテストすると、特定の に対して、スレッド番号が同じであることがわかりますi(もちろん、このテストは、実行が異なれば結果が異なるため、決定的なものではなく実証的なものです)。たとえば、次のようにします。

#include <stdio.h>
#include <omp.h>
#define dimension 4

int main() {
    #pragma omp parallel for
    for (int i = 0; i < dimension; i++)
        for (int j = 0; j < dimension; j++)
            printf("i=%d, j=%d, thread = %d\n", i, j, omp_get_thread_num());
    }

私は得る:

i=1, j=0, thread = 1
i=3, j=0, thread = 3
i=2, j=0, thread = 2
i=0, j=0, thread = 0
i=1, j=1, thread = 1
i=3, j=1, thread = 3
i=2, j=1, thread = 2
i=0, j=1, thread = 0
i=1, j=2, thread = 1
i=3, j=2, thread = 3
i=2, j=2, thread = 2
i=0, j=2, thread = 0
i=1, j=3, thread = 1
i=3, j=3, thread = 3
i=2, j=3, thread = 2
i=0, j=3, thread = 0

コードの残りの部分については、新しい質問に詳細を記載することをお勧めします (小さなサンプルからは判断が難しい場合がありますprivate(j)) j。上記の例では、自動的にプライベートになります。diffサンプルには見られない変数だと思います。また、ループ変数iは自動的にプライベートになります (バージョン 2.5 仕様から- 3.0 仕様と同じ)。

for または parallel for コンストラクトの for ループ内のループ反復変数は、そのコンストラクト内でプライベートです。

編集:上記のすべては、あなたと私が示したコードに対して正しいですが、次のことに興味があるかもしれません. OpenMP バージョン 3.0 (たとえば、 gcc バージョン 4.4で使用できますが、バージョン 4.3 では使用できません) の場合collapse、コードをそのまま記述できる節がありますが、 #pragma omp parallel for collapse (2)両方の for ループを並列化します (仕様を参照)。

編集: OK、gcc 4.5.0 をダウンロードして上記のコードを実行しcollapse (2)ましたが、次の出力を取得するために使用し、内部ループが並列化されたことを示しています。

i=0, j=0, thread = 0
i=0, j=2, thread = 1
i=1, j=0, thread = 2
i=2, j=0, thread = 4
i=0, j=1, thread = 0
i=1, j=2, thread = 3
i=3, j=0, thread = 6
i=2, j=2, thread = 5
i=3, j=2, thread = 7
i=0, j=3, thread = 1
i=1, j=1, thread = 2
i=2, j=1, thread = 4
i=1, j=3, thread = 3
i=3, j=1, thread = 6
i=2, j=3, thread = 5
i=3, j=3, thread = 7

ここのコメント(「回避策」を検索) は、両方のループを並列化したい場合のバージョン 2.5 の回避策にも関連していますが、上記のバージョン 2.5 の仕様は非常に明示的です (セクションA.35の非準拠の例を参照してください) 。 .

于 2010-02-07T04:00:41.077 に答える
0

ネストされたomp並列forsを(omp_set_nested(1)呼び出し後に)使用してみることができますが、すべてのopenmp実装でサポートされているわけではありません。

だから私はいくつかの2Dグリッドを作成し、グリッド上のすべてのスレッドを単一から開始することを推測します(固定4x4スレッドグリッドの例):

#pragma omp parallel for
for(k = 0; k < 16; k++)
{
    int i,j,i_min,j_min,i_max,j_max;
    i_min=(k/4) * (dimension/4);
    i_max=(k/4 + 1) * (dimension/4);
    j_min=(k%4) * (dimension/4);
    j_max=(k%4 + 1) * (dimension/4);

    for(i=i_min;i<i_max;i++)
      for(j=j_min;j<j_max;j++)
       f(i,j);

}
于 2010-02-07T05:01:47.577 に答える