Oracle® Developer Studio 12.5: OpenMP API ユーザーズガイド

印刷ビューの終了

更新: 2016 年 7 月
 
 

3.2 入れ子並列処理の制御

入れ子並列処理を制御するには、プログラムを実行する前にさまざまな環境変数を設定するか、omp_set_nested() 実行時ルーチンを呼び出します。このセクションでは、入れ子並列処理を制御するために使用できるさまざまな環境変数について説明します。

3.2.1 OMP_NESTED

入れ子並列処理は、OMP_NESTED 環境変数を設定することによって、有効または無効にすることができます。デフォルトでは、入れ子並列処理は無効になっています。

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

使用例 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 | 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

入れ子並列処理を無効にしてプログラムを実行すると、次の出力が生成されます。

% setenv OMP_NESTED FALSE
% a.out | sort
Level 1: number of threads in the team = 2
Level 2: 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
Level 3: number of threads in the team = 1

3.2.2 OMP_THREAD_LIMIT

OMP_THREAD_LIMIT 環境変数の設定は、プログラム全体で使用される OpenMP スレッドの最大数を制御します。この数値には、最初の (メイン) スレッド、および OpenMP 実行時ライブラリによって作成された OpenMP ヘルパースレッドが含まれます。デフォルトでは、プログラム全体で使用される OpenMP スレッドの最大数は 1024 です (1 つの最初の (メイン) スレッドおよび 1023 個の OpenMP ヘルパースレッド)。

スレッドプールは、OpenMP 実行時ライブラリによって作成された OpenMP ヘルパースレッドのみで構成されます。プールには、最初の (メイン) スレッドやユーザーのプログラムが明示的に作成したスレッドは含まれません。

OMP_THREAD_LIMIT に 1 を設定すると、ヘルパースレッドプールが空になり、すべての並列領域が 1 つのスレッド (最初の (メイン) スレッド) によって実行されます。

次の例の出力では、プール内のヘルパースレッド数が不十分な場合、並列領域で取得されるヘルパースレッド数も少なくなる可能性があることを示しています。このコードは、環境変数 OMP_THREAD_LIMIT に 6 が設定されていることを除いて、使用例 1のコードと同じです。アクティブ化されるすべての並列領域に必要な同時スレッドの数は、8 個です。つまり、プールには少なくとも 7 個のヘルパースレッドが含まれている必要があります。OMP_THREAD_LIMIT に 6 を設定すると、プールには最大 5 個のヘルパースレッドが含まれることになります。このため、もっとも内側にある 4 つの並列領域のうち 2 つが、必要な数のヘルパースレッドを取得できないことがあります。次の例は、可能性のある結果の 1 つを示しています。

% setenv OMP_NESTED TRUE
% OMP_THREAD_LIMIT 6
% 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 = 1
Level 3: number of threads in the team = 1

3.2.3 OMP_MAX_ACTIVE_LEVELS

環境変数 OMP_MAX_ACTIVE_LEVELS は、アクティブな並列領域をいくつまで入れ子にすることができるかを制御します。並列領域がアクティブであると見なされるのは、複数のスレッドで構成されているチームによって実行される場合です。設定しない場合、デフォルト値は 4 です。

この環境変数を設定しても、入れ子になったアクティブな並列領域の最大数が制御されるだけで、入れ子並列処理は有効になりません。入れ子並列を有効にするには、OMP_NESTEDTRUE に設定するか、true() と評価される引数を指定して omp_set_nested を呼び出す必要があります。

次のコード例では、4 重の入れ子並列領域を作成しています。

#include <omp.h>
#include <stdio.h>
#define DEPTH 4
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);
}

次の出力は、DEPTH に 4 を設定してコード例をコンパイルおよび実行した場合の可能性のある結果を示しています。実際の結果は、オペレーティングシステムがどのようにスレッドをスケジューリングしているかによって異なります。

% setenv OMP_NESTED TRUE
% setenv OMP_MAX_ACTIVE_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

OMP_MAX_ACTIVE_LEVELS を 2 に設定すると、3 番目と 4 番目の深さにある入れ子並列領域は 1 つのスレッドによって実行されます。次の例は、可能性のある結果を示しています。

% setenv OMP_NESTED TRUE
% setenv OMP_MAX_ACTIVE_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