スレッド数のコントロールについて
スレッド数をコントロールするには、実行時ライブラリと呼ばれるOpenMPで規定されている関数を使用します。
#include <stdio.h>
#include <omp.h>
int main()
{
int threadCount = 4; /*スレッド数*/
//初期状態を表示
printf( "初期状態の動的調節機能は%s\n\n", omp_get_dynamic() == 0 ? "無効" : "有効" );
/*スレッドの動的調節を有効にする*/
omp_set_dynamic( 1 );
printf ( "動的調節機能を有効化しました\n" );
omp_set_num_threads( threadCount );
#pragma omp parallel
{
printf ( "現在のスレッド数は%dです。\n", omp_get_num_threads());
}
printf( "現在動的調節機能は%s\n\n", omp_get_dynamic() == 0 ? "無効" : "有効" );
/*スレッド数を指定して並列実行*/
omp_set_dynamic( 0 );
omp_set_num_threads( threadCount );
printf ( "動的調節機能を無効化しました。指定したスレッド数は%dです。\n", threadCount );
#pragma omp parallel
{
printf ( "現在のスレッド数は%dです。\n", omp_get_num_threads());
}
printf( "現在動的調節機能は%s\n\n", omp_get_dynamic() == 0 ? "無効" : "有効" );
//終了
printf( "\n\n" );
return 0;
}

このサンプルプログラムは、4つの実行時ライブラリomp_get_dynamic()、omp_set_dynamic、omp_get_num_threads、omp_set_num_threadsを使用しています。
omp_get_dynamic()とomp_set_dynamicは、スレッド数の動的調整が有効か無効かを決定するdyn-var内部制御変数の値を取得/設定するための関数です。動的調節が有効な時は、CPUのコア数に応じて処理が並列化されます。
OpenMPでは、サポートするコンパイラが、あたかも変数をもつかのように振る舞うことになっております。これを内部制御変数と呼びます。omp_get_dynamic()とomp_set_dynamicは、この変数を操作してスレッド数が動的に調節できるか否かを制御します。スレッド数の動的調節が有効な場合はdyn-varが0以外、無効な場合は0と定義されております。自動調節が可能なコンパイラのdyn-var内部制御変数の初期値は未定義ですので、このサンプルグラムに示したように確認や明示的に指定した方がよいでしょう。コンパイラによっては、omp_set_dynamic( 1 )を初めに指定しなくても自動調節が有効ですが、この2つの関数を明示的に使用しなければ、特定のコンパイラに依存するプログラムになってしまいます。
omp_get_num_threadsとomp_set_num_threadsは、スレッド数を指定するための関数です。omp_get_num_threadsをparallel構文の中で使用するとスレッド数が取得できます。parallel構文の範囲以外では必ず1を返しますので注意が必要です。そしてomp_set_num_threadsは、指定した数のスレッドをparallel構文内で生成するための関数です。もし指定した数のスレッド数が生成できなければどうなるかは未定義ですので、あまり大きな数は指定しない方がよいでしょう。
この逆に、複数のスレッドで実行したくない処理が含まれている場合は、次のようにします。
#include <stdio.h>
#include <omp.h>
int main()
{
#pragma omp parallel
{
printf ( "複数回表示\n" );
#pragma omp single
{
printf("1回だけ表示\n");
}
printf ( "複数回表示\n" );
}
//終了
printf( "\n\n" );
return 0;
}
このサンプルプログラムの様に、並列処理をしたい範囲内の一部のコードだけ逐次的に処理をしたい場合は、single構文を使用します。以上がスレッド数を変化させる基本的な方法です。
他の方法として環境変数を使用するやり方があります。環境変数としてOMP_DYNAMICと、OMP_NUM_THREADSを設定することにより同様のことを行えます。
環境変数を試すにはコマンドプロンプトを使用するとよいでしょう。まずcdコマンドでサンプルプログラムの実行ファイルがある場所へ移動します。次に2つのコマンドset OMP_NUM_THREADS=4とset OMP_DYNAMIC=FALSEを実行して下さい。そして最後に実行ファイルの名前を指定してEnterキーを押すと、最初のサンプルの場合は4回「Hello, OpenMP!」と表示されます。
以上でスレッドを操作する方法の説明は終わりです。
まとめ
今回は初回ですので、OpenMPのもっとも基本的な知識について丁寧に解説しました。次回はさらに他のOpenMPの要素について丁寧に解説していきます。この記事がきっかけに並列処理について学習する方がおられれば望外の幸せです。
参考資料
- MSDN
- OpenMP公式ホームページ
- 『OpenMP入門』 北山洋幸 著、秀和システム、2009年8月
