web-dev-qa-db-ja.com

num_threadsとomp_set_num_threadsとOMP_NUM_THREADSの違い

コードの並列部分のスレッド数を指定する方法について、私はかなり混乱しています。私は使用できることを知っています:

  1. 環境変数OMP_NUM_THREADS
  2. 関数omp_set_num_threads(int)
  3. num_threads(int)in #pragma omp parallel for num_threads(NB_OF_THREADS)

これまでに収集したものは、最初の2つは同等です。しかし、3番目のものはどうですか?誰かが違いのより詳細な説明を提供できますか、1/2と3の違いに関する情報はインターネットで見つかりませんでした。

15
leosenko

_OMP_NUM_THREADS_とomp_set_num_threads()は同等ではありません。環境変数は、チーム内のスレッドの最大数を制御するnthreads-var ICV(内部制御変数)の初期値を設定するためにのみ使用されます。 omp_set_num_threads()を使用すると、nthreads-varの値をいつでも(もちろん、並列領域外で)変更でき、後続のすべての並列領域に影響します。したがって、値を設定します。 n、to _OMP_NUM_THREADS_は、最初の並列領域が検出される前にomp_set_num_threads(n)を呼び出すことと同じです。

並列領域のスレッド数を決定するアルゴリズムは、OpenMP Webサイトで自由に入手できる OpenMP仕様 で非常に明確に説明されています。

if_num_threads_句が存在する場合

then letThreadsRequestedは、_num_threads_句の式の値です。

else letThreadsRequested = nthreads-varの最初の要素の値;

nthreads-varを設定するさまざまな方法の優先順位は、仕様のICVオーバーライド関係の部分にリストされています。

_num_threads_句とomp_set_num_threads()は、_OMP_NUM_THREADS_環境変数の値とnthreads-var ICVの最初の要素の初期値をオーバーライドします。

人間の言語に翻訳される、つまり:

  • _OMP_NUM_THREADS_(存在する場合)は、最初にスレッドの数を指定します。
  • omp_set_num_threads()を呼び出すと、_OMP_NUM_THREADS_の値が上書きされます。
  • _num_threads_句が存在すると、他の両方の値が上書きされます。

使用される実際のスレッド数は、動的チームサイズが有効かどうか(dyn-var ICVが_OMP_DYNAMIC_またはomp_set_dynamic()を介して設定可能)かどうか、またthread-limit-var(_OMP_THREAD_LIMIT_を介して設定可能)、およびネストされた並列処理(_OMP_NESTED_/omp_set_nested())が有効かどうか。

25
Hristo Iliev

スコープのように考えてください。オプション3(num_threads)は、スレッドの現在のチームのみのスレッド数を設定します。その他のオプションは、グローバル/状態設定です。通常はスレッド数を設定せず、デフォルトを使用します。スレッド数を変更する場合、通常は特別な場合に限られるため、次に並列チームを使用するときにグローバル(デフォルト)設定に戻るように、オプション3を使用します。以下のコードを参照してください。オプション3を使用した後、次のスレッドチームが最後のグローバル設定に戻ります。

#include <stdio.h>
#include <omp.h>

int main() {
    #pragma omp parallel
    {
        #pragma omp single
        {
            printf("%d\n", omp_get_num_threads());
        }
    }
    omp_set_num_threads(8);
    #pragma omp parallel
    {
        #pragma omp single
        {
            printf("%d\n", omp_get_num_threads());
        }
    }

    #pragma omp parallel num_threads(2)
    {
        #pragma omp single
        {
            printf("%d\n", omp_get_num_threads());
        }
    }

    #pragma omp parallel
    {
        #pragma omp single
        {
            printf("%d\n", omp_get_num_threads());
        }
    }       
}

4 8 2 8

4
Z boson