45

OpenMP で を使用する場合、スレッドはセクションomp sections内のブロックに分散されますか、それともセクションごとに各スレッドが割り当てられますか?

時期nthreads == 3

#pragma omp sections
{
    #pragma omp section
    { 
        printf ("id = %d, \n", omp_get_thread_num());
    }

    #pragma omp section
    { 
        printf ("id = %d, \n", omp_get_thread_num());
    }
}

出力:

id=1
id=1

しかし、次のコードを実行すると:

#pragma omp sections
{
    #pragma omp section
    { 
        printf ("id = %d, \n", omp_get_thread_num());
    }

    #pragma omp section
    { 
        printf ("id = %d, \n", omp_get_thread_num());
    }
}

#pragma omp sections
{
    #pragma omp section
    { 
        printf ("id = %d, \n", omp_get_thread_num());
    }

    #pragma omp section
    { 
        printf ("id = %d, \n", omp_get_thread_num());
    }
}

出力:

id=1
id=1

id=2
id=2

これらの出力から、OpenMP におけるセクションの概念が何であるかを理解できません。

4

9 に答える 9

102

キーワードが表示されないためparallel、OP によって投稿されたコードが並列実行されることはありません。OP が 0 以外の ID を取得したという事実は、おそらく彼のコードが並列ディレクティブに埋め込まれていたことを示しています。ただし、これは彼の投稿からは明らかではなく、初心者を混乱させる可能性があります。

最低限の賢明な例は次のとおりです(OPによって投稿された最初の例の場合):

#pragma omp parallel sections
{
    #pragma omp section
    { 
        printf ("id = %d, \n", omp_get_thread_num());
    }

    #pragma omp section
    { 
        printf ("id = %d, \n", omp_get_thread_num());
    }
}

私のマシンでは、これは印刷されます

id = 0,
id = 1,

2 つのセクションが異なるスレッドによって実行されていることを示しています。

ただし、このコードは 2 つのスレッドよりも多くの並列処理を抽出できないことに注意してください。より多くのスレッドで実行すると、他のスレッドは何もする必要がなく、アイドル状態になります。

于 2013-10-09T20:29:43.160 に答える
28

並列セクションの考え方は、さまざまな (内部の) セクションを並列で実行できるというヒントをコンパイラに与えることです。次に例を示します。

#pragma omp parallel sections
{
   #pragma omp section
   {
      /* Executes in thread 1 */
   } 
   #pragma omp section
   {
      /* Executes in thread 2 */
   } 
   #pragma omp section
   {
      /* Executes in thread 3 */
   } 
   /* ... */
}

これはコンパイラへのヒントであり、発生する保証はありませんが、発生するはずです。あなたの出力は期待通りのものです。スレッド ID 1 とスレッド 2 で #sections が実行されていると表示されます。どのスレッドが最初に実行されるかわからないため、出力順序は非決定論的です。

于 2010-05-05T06:17:01.677 に答える
13

から最初の行を変更します

#pragma omp セクション

の中へ

#pragma omp 並列セクション

"parallel" ディレクティブは、2 つのセクションが 2 つのスレッドに割り当てられることを保証します。次に、次の出力 id = 0、id = 1、

于 2013-11-15T21:05:22.767 に答える
5

OpenMP 標準 3.1によると、セクション 2.5.2 (強調鉱山):

セクション コンストラクトは、チーム内のスレッド間で分散され、スレッドによって実行される一連の構造化ブロックを含む非反復ワークシェアリング コンストラクトです。各構造化ブロックは 、その暗黙的なタスクのコンテキストで、チーム内のスレッドの 1 つによって 1 回実行されます。

...

セクション コンストラクト内の各構造化ブロックの前には、セクション ディレクティブが先行する場合がありますが、最初のブロックは例外であり、先行するセクション ディレクティブはオプションです。チーム内のスレッド間で構造化ブロックをスケジューリングする方法は、実装定義です。nowait 句が指定されていない限り、セクション構造の最後に暗黙のバリアがあります。

したがって、これらのルールをあなたのケースに適用すると、次のように主張できます。

  1. sectionsディレクティブで識別されるさまざまな構造化ブロックは、1 つのスレッドによって 1 回実行されます。つまり、スレッドの数に関係なく、常に 4 つのプリントがあります。
  2. 最初のブロックは、2 番目のブロックのsectionsに (非決定的な順序で) 実行されます (これも非決定的な順序で実行されます)。これは、ワークシェアリング構造の最後に暗黙のバリアがあるためです。sections
  3. スケジューリングは実装定義であるため、特定のセクションがどのスレッドに割り当てられているかを制御することはできません

したがって、出力は、スケジューラがチーム内のスレッドに異なるブロックを割り当てることを決定した方法によるものです。

于 2013-10-10T21:08:14.113 に答える
3

出力行に情報を追加し、セクションを追加すると役立つ場合があります (スレッド数がある場合)。

#pragma omp parallel sections
{
    #pragma omp section
    {
        printf ("section 1 id = %d, \n", omp_get_thread_num()); 
    }
    #pragma omp section
    {
        printf ("section 2 id = %d, \n", omp_get_thread_num());
    }
    #pragma omp section
    {
        printf ("section 3 id = %d, \n", omp_get_thread_num());
    }
}

次に、次のようなより興味深い出力が得られる場合があります。

section 1 id = 4,
section 3 id = 3,
section 2 id = 1,

これは、使用可能な任意のスレッドによって、セクションが任意の順序で実行される方法を示しています。

于 2013-12-29T17:26:25.383 に答える
0

Note that 'nowait' tells the compiler that threads do not need to wait to exit the section. In Fortran 'nowait' goes at the end of the loop or section, which makes this more obvious.

于 2013-09-13T20:06:38.057 に答える
-4

異なるセクションで異なるスレッドを本当に開始したい場合、このnowait句は、スレッドがセクションに入るのを待つ必要がないことをコンパイラに伝えます。

#pragma omp parallel sections nowait
{
   ...
}
于 2012-11-07T20:15:28.763 に答える