OpenMPと並列処理の順序付け
分かりやすいように、サンプルプログラム(C言語を使用)を掲載します。
#include <stdio.h> int main() { int i; //並列的に数字を表示 printf( "これから並列的に数字を表示します・・・\n" ); #pragma omp parallel for num_threads( 10 ) for ( i = 0; i < 100; i++ ) { printf( " %d", i ); } printf( "\n\n" ); //順番に数字を表示 printf( "これから順番に数字を表示します・・・\n" ); #pragma omp parallel for num_threads( 10 ) ordered for ( i = 0; i < 100; i++ ) { #pragma omp ordered { printf( " %d", i ); } } printf( "\n\n" ); return 0; }
サンプルを実行すると、ordered構文を指定したプログラムは、数値が順番に表示されます。これにより、指定された部分のコードが、逐次的に実行されている事が確認できます。
ordered構文を使用するには、ループ構文で必ずordered指示句を指定します。そして、順番に指定したいコードを ordered構文で指定します。ordered構文で指定されていないコードは、並列に処理されます。
これで、ordered構文内のコードが、順番に処理されるのがなんとなく分かったと思います。ですが、具体的に、どのように実行されるのかが気になると思いましたので、もうひとつサンプルを用意しました。
#include <stdio.h> #include <omp.h> int main() { int i, count; count = 4; #pragma omp parallel for num_threads( count ) ordered for ( i = 0; i < count; i++ ) { printf( "スレッド%dがorderedよりも前の処理をしました。\n", omp_get_thread_num() ); #pragma omp ordered { printf( "スレッド%dがordered内の処理をしました。\n", omp_get_thread_num() ); } printf( "スレッド%dがorderedよりも後の処理をしました。\n", omp_get_thread_num() ); } printf( "\n\n" ); return 0; }
このサンプルを何度か実行し、どの部分のコードがいつ実行されるのかを確認すると、ordered構文の働きが良く分かると思います。
ordered構文で指定された範囲のコードは、必ずスレッドのID昇順で実行されています。一方、ordered構文よりも前のコードは、順番に関係なく実行されています。ordered構文よりも後のコードについても、短いサンプルなので確認し難いですが、ordered構文で指定された範囲のコードが順番に実行された後、並列的に実行されています。
以上の様に、ordered構文は、指定したコードブロック内のコードを、逐次化する事により順番に実行します。プログラムを逐次化すると、パフォーマンスが低下するので、ordered構文は極力使用せず、使用する際も指定するコードの範囲を絞るのが得策です。
【参考資料】