4

チームメイトに OpenMP の簡単なプレゼンテーションを行うためのコード サンプルを準備していたときに、奇妙なケースを見つけました。最初に私は古典的なループを書きました:

void sequential(int *a, int size, int *b)
{
    int i;
    for (i = 0; i < size; i++) {
        b[i] = a[i] * i;
    }
}

for ディレクティブの正しい OpenMP の使用法は簡単です。int iスコープを作成するには、宣言をスコープに移動するだけprivateです。

void parallel_for(int *a, int size, int *b)
{
#pragma omp parallel for
    for (int i = 0; i < size; i++) {
        b[i] = a[i] * i;
    }
}

しかし、次の関数を書いたときint j、for ループ スコープ外で宣言した共有のために、他の 2 つの異なる結果が得られると予想していました。しかし、テスト フレームワークを使用すると、予期したエラーが表示されず、その関数の出力に誤った値が表示されます。

void parallel_for_with_an_usage_error(int *a, int size, int *b)
{
    int j;
#pragma omp parallel for
    for (int i = 0; i < size; i++) {
        /*int*/ j = a[i]; //To be correct j should be declared here, in-loop to be private !
        j *= i;
        b[i] = j;
    }
}

私はテスト用の完全なソースコードを持っています.VS'12とgcc(C++ 11を有効にして)でビルドしますhttp://pastebin.com/NJ4L0cbV

コンパイラが何をしているのか知っていますか? 偽の共有を検出しますint jか?最適化ヒューリスティックによりループ内に移動しますか?

感謝

4

1 に答える 1

0

私の意見では、コンパイラーが何らかの最適化を行っている可能性があります。上記の貼り付けられたコード (cout なし) では、変数 j はループ内以外の場所にないため、コンパイラは生成されたアセンブリ コードのループ内に j の宣言を配置できます。

別の可能性としては、コンパイラがループ内の 3 つのステートメントを 1 つのステートメントに変換している可能性があります。

/*int*/ j = a[i]; //To be correct j should be declared here, in-loop to be private !
j *= i;
b[i] = j;

に、

b[i] = a[i] * i;

コンパイラは、OpenMP コードであるかどうかに関係なく、この最適化を行います。

于 2013-08-21T02:51:11.037 に答える