Sun Studio 12 Update 1: OpenMP API ユーザーズガイド

4.2 入れ子並列処理の制御

入れ子並列処理は、プログラムの実行前にさまざまな環境変数を設定することでその実行を制御できます。

4.2.1 OMP_NESTED

入れ子並列処理は、OMP_NESTED 環境変数を設定するか omp_set_nested() を呼び出すことで有効または無効に設定できます。

3 つのレベルを持つ、入れ子並列構文の例を次に示します。


例 4–1 入れ子並列処理の例


#include <omp.h>
#include <stdio.h>
void report_num_threads(int level)
{
    #pragma omp single
    {
        printf("Level %d: number of threads in the team - %d\n",
                  level, omp_get_num_threads());
    }
 }
int main()
{
    omp_set_dynamic(0);
    #pragma omp parallel num_threads(2)
    {
        report_num_threads(1);
        #pragma omp parallel num_threads(2)
        {
            report_num_threads(2);
            #pragma omp parallel num_threads(2)
            {
                report_num_threads(3);
            }
        }
    }
    return(0);
}

入れ子並列処理を有効にして、このプログラムをコンパイルおよび実行すると、次のようなソート済みの結果が出力されます。


% setenv OMP_NESTED TRUE
% a.out
Level 1: number of threads in the team - 2
Level 2: number of threads in the team - 2
Level 2: number of threads in the team - 2
Level 3: number of threads in the team - 2
Level 3: number of threads in the team - 2
Level 3: number of threads in the team - 2
Level 3: number of threads in the team - 2

入れ子並列処理を無効にして同じプログラムを実行した場合と比べてみましょう。


% setenv OMP_NESTED FALSE
% a.out
Level 1: number of threads in the team - 2
Level 2: number of threads in the team - 1
Level 3: number of threads in the team - 1
Level 2: number of threads in the team - 1
Level 3: number of threads in the team - 1

4.2.2 SUNW_MP_MAX_POOL_THREADS

OpenMP 実行時ライブラリにはスレッドがプールされていて、並列領域内でのスレーブスレッドとして使用されます。SUNW_MP_MAX_POOL_THREADS 環境変数を設定することで、プールに保存しておけるスレッドの最大数を制限できます。この変数のデフォルト値は 1023 です。

プールにあるのは、実行時ライブラリが作成した非ユーザースレッドだけです。最初のスレッドやユーザーのプログラムが明示的に作成したスレッドは含まれません。この環境変数をゼロに設定すると、スレッドのプールは空になり、すべての並列領域は 1 つのスレッドによって実行されます。

次の例は、プールに十分な数のスレッドがない場合には、並列領域が取得できるスレッドの数が少なくなることを示す例です。コードは、上記の例と同じです。アクティブ化されるすべての並列領域に必要な同時スレッドの数は、8 個です。プールには、少なくとも 7 個のスレッドが含まれている必要があります。ここで SUNW_MP_MAX_POOL_THREADS 変数を 5 に設定すると、もっとも内側の入れ子にある 4 つの並列領域のうち、2 つは必要な数のスレーブスレッドを取得できない場合があります。実行結果はさまざまですが、1 つの例を見てみましょう。


% setenv OMP_NESTED TRUE
% setenv SUNW_MP_MAX_POOL_THREADS 5
% a.out
Level 1: number of threads in the team - 2
Level 2: number of threads in the team - 2
Level 2: number of threads in the team - 2
Level 3: number of threads in the team - 2
Level 3: number of threads in the team - 2
Level 3: number of threads in the team - 1
Level 3: number of threads in the team - 1

4.2.3 SUNW_MP_MAX_NESTED_LEVELS

環境変数 SUNW_MP_MAX_NESTED_LEVELS は、複数のスレッドを必要とする入れ子になった有効な並列領域の最大の深さを制限します。

この環境変数で指定した数を超える有効な入れ子を持つ有効な並列領域は、1 つのスレッドによって実行されます。IF 節がないか、IF 節の評価が true となる場合は、並列領域は有効であると見なされます。有効な入れ子レベルのデフォルトの最大数は 4 です。

次に、4 重の入れ子になった並列領域のコードの例を示します。SUNW_MP_MAX_NESTED_LEVELS が 2 に設定されると、3 番目と 4 番目の深さにある入れ子並列領域は 1 つのスレッドによって実行されます。


#include <omp.h>
#include <stdio.h>
#define DEPTH 5
void report_num_threads(int level)
{
    #pragma omp single
    {
        printf("Level %d: number of threads in the team - %d\n",
               level, omp_get_num_threads());
    }
}
void nested(int depth)
{
    if (depth == DEPTH)
        return;

    #pragma omp parallel num_threads(2)
    {
        report_num_threads(depth);
        nested(depth+1);
    }
}
int main()
{
    omp_set_dynamic(0);
    omp_set_nested(1);
    nested(1);
    return(0);
}

入れ子の深さの最大数を 4 に設定してこのプログラムをコンパイル、実行すると、次のような結果が出力されます。実際の結果は、OS がどのようにスレッドをスケジューリングしているかによって異なります。


% setenv SUNW_MP_MAX_NESTED_LEVELS 4
% a.out |sort 
Level 1: number of threads in the team - 2
Level 2: number of threads in the team - 2
Level 2: number of threads in the team - 2
Level 3: number of threads in the team - 2
Level 3: number of threads in the team - 2
Level 3: number of threads in the team - 2
Level 3: number of threads in the team - 2
Level 4: number of threads in the team - 2
Level 4: number of threads in the team - 2
Level 4: number of threads in the team - 2
Level 4: number of threads in the team - 2
Level 4: number of threads in the team - 2
Level 4: number of threads in the team - 2
Level 4: number of threads in the team - 2
Level 4: number of threads in the team - 2

入れ子の深さを 2 に設定して実行した場合の結果は次のとおりです。


% setenv SUNW_MP_MAX_NESTED_LEVELS 2
% a.out |sort 
Level 1: number of threads in the team - 2
Level 2: number of threads in the team - 2
Level 2: number of threads in the team - 2
Level 3: number of threads in the team - 1
Level 3: number of threads in the team - 1
Level 3: number of threads in the team - 1
Level 3: number of threads in the team - 1
Level 4: number of threads in the team - 1
Level 4: number of threads in the team - 1
Level 4: number of threads in the team - 1
Level 4: number of threads in the team - 1

この例は、可能性のある結果の一部のみを示しています。実際の結果は、OS がどのようにスレッドをスケジューリングしているかによって異なります。