web-dev-qa-db-ja.com

OpenMP:実行中のスレッドの総数を取得します

アプリケーションがOpenMPを介して生成したスレッドの総数を知る必要があります。残念ながら、omp_get_num_threads()関数は、現在のチームのスレッド数しか生成しないため、ここでは機能しませんnot

ただし、私のコードは再帰的に実行され(基本的に分割統治)、アイドル状態のプロセッサがまだ存在する限り、新しいスレッドを生成したいのですが、それ以上はありません。

omp_get_num_threadsの制限を回避し、実行中のスレッドのtotal数を取得する方法はありますか?

より詳細な情報が必要な場合は、ワークフローを非常に厳密にモデル化した次の擬似コードを検討してください。

function divide_and_conquer(Job job, int total_num_threads):
  if job.is_leaf(): # Recurrence base case.
    job.process()
    return

  left, right = job.divide()

  current_num_threads = omp_get_num_threads()
  if current_num_threads < total_num_threads: # (1)
    #pragma omp parallel num_threads(2)
      #pragma omp section
        divide_and_conquer(left, total_num_threads)
      #pragma omp section
        divide_and_conquer(right, total_num_threads)

  else:
    divide_and_conquer(left, total_num_threads)
    divide_and_conquer(right, total_num_threads)

  job = merge(left, right)

このコードをtotal_num_threads値4で呼び出すと、(1)で注釈が付けられた条件は常にtrue(各スレッドチームには最大2つのスレッドが含まれるため)、したがって、より高いレベルですでに実行されているスレッドの数に関係なく、コードは常に2つの新しいスレッドを生成します。

アプリケーションで現在実行されているスレッドの総数を決定するプラットフォームに依存しない方法を探しています。

14
Konrad Rudolph

作成されるスレッドの正確な量を知っていることを念頭に置いて、私が思いついた最も簡単な解決策は、独自のスレッドカウンターを維持することです。

私はOpenMPを実際に使用したことがないので、OpenMPについて完全に暗闇にいることに注意してください。

0
jweyrich

少なくともOpenMP3にはそのようなルーチンはないと思います。スレッド数のカウントとフォークの間に明らかに大きな競合状態があるため、それがあったとしても、それが役立つかどうかはわかりません。 1つのスレッドの余地があることを全員が確認し、全員がスレッドを生成した場合、目標のスレッド数をほぼ2倍オーバーシュートする可能性があります。

ただし、これが実際にプログラムの構造であり、スレッドの総数を制限したい場合は、オプションがあります(これらはすべてOpenMP 3.0です)。

  1. _OMP_THREAD_LIMIT_環境変数を使用して、OpenMPスレッドの総数を制限します
  2. _OMP_MAX_ACTIVE_LEVELS_、またはomp_set_max_active_levels()を使用するか、omp_get_level()に対してテストして、スレッドのネストの深さを制限します。 16スレッドのみが必要な場合は、4レベルのネストに制限します
  3. 2の累乗よりも細かい制御が必要な場合は、omp_get_level()を使用してレベルを検索し、さまざまなレベルでomp_get_ancestor_thread_num(int level)を呼び出して、どのスレッドが親、祖父母などであるかを確認できます。それから(この単純な左右のフォークを使用して)グローバルスレッドIDを決定します。 (この場合は∑のようになると思いますl = 0..L-1 al 2L-l ここで、lは0から始まるレベル番号であり、aはそのレベルの祖先スレッド番号です。これにより、(たとえば)スレッド0〜3はフォークできますが、4〜7は許可されないため、16スレッドではなく12スレッドになります。これは、このような通常の状況でのみ機能すると思います。各親スレッドが異なる数の子スレッドをフォークした場合、直接の祖先にしかクエリできないように見えるため、一意のグローバルスレッドIDを決定できるとは思いません。
4
Jonathan Dursi

あなたが示したコードには、「ompセクション」が「ompセクション」の字句スコープ内になければならないという問題があります。 「ompparallel」は「ompparallelsections」という意味だと思います。これを行うもう1つの方法は、「omp task」を使用することです。そうすれば、スレッドの数を数える必要がなくなります。スレッドを並列領域に割り当て、OpenMP実装がタスクをスレッドに割り当てることを許可するだけです。

2
ejd