1

iOSで使用するためにいくつかのOpenMP並列化ループをGCDに移植しています。モデリングするのに最適な方法がわからない構造に遭遇しました。

OpenMPループは、共有状態ブロックに対していくつかの重要な操作を実行します。この操作では、可能なOpenMPスレッドごとに1つを割り当て、ループ後に結果を結合(事実上削減)します。このように(簡略化):

const int max_threads = omp_get_max_threads();
state_block state[max_threads];

#pragma omp parallel for shared(state) 
for(unsigned int i = 0; i < some_count; i++) {
    // do some stuff
    update_state(state[omp_get_thread_num()]);
}

merge_state_data(state, max_threads);

GCDは、可能なスレッドの最大数(そうですか?)または現在使用しているスレッドを知る方法を提供しないため、このパターンは機能しません。状態ブロックのサイズは重要であり、反復回数が多いため、ループの反復ごとに1つを割り当てることも、純粋な最悪のケースとして妥当ではありません。

カスタムディスパッチソースを使用DISPATCH_SOURCE_TYPE_DATA_ADDして状態の更新を行うことも考えられますが、そのようにアトマイズすると、何千ものソースが必要になり、それは間違っているようです。

GCDで、または一般的にここのデザインで、私が見逃しているものはありますか?

ありがとう。

4

1 に答える 1

1

POSIX スレッド API 関数pthread_setspecific()pthread_getspecific()iOS を使用して、一時的なものを指すスレッド固有のキーを設定し、state_block後で現在実行中のブロックでそれを取得できます。Apple のConcurrency Programming Guideは、異なるブロック実行で異なる値を返す可能性があるため、使用をお勧めしませんpthread_getspecific()が、あなたの場合、これは完全に受け入れられます (結局のところ、それがあなたが求めている機能です)。

プールへの事前アクセスがないため、オンデマンドで状態ブロックを割り当てる必要があります。

  • 現在のスレッドでポインターpthread_getspecific()を取得するために使用します。state_block
  • 特定の値が設定されていない場合は、新しいstate_block値を割り当て、 を使用してキーの値に割り当てますpthread_setspecific()
  • それを使って計算しstate_blockます。

これにより、クリーンアップで問題が発生する可能性があります。たとえば、すべてのタスクが実行されたら状態ブロックを破棄する方法を考えてください。ポインターの共有テーブルを使用し、スレッド固有の値などとしてテーブルに一意のインデックスを設定することができます。ロックを使用して、インデックス値へのアクセスをシリアル化することができます。これは、プール内の各スレッドごとに 1 回だけ実行されるため、許容されます。

もちろん、このアプローチは、固定スレッド プールを使用して同時キューを実装する GCD に依存しています。

于 2012-12-11T09:37:20.700 に答える