次の方法で共有


OpenMP からコンカレンシー ランタイムへの移行

コンカレンシー ランタイムでは、さまざまなプログラミング モデルを使用できます。 これらのモデルは、他のライブラリのモデルと重複する場合や、他のライブラリのモデルを補完する場合があります。 このセクションでは、OpenMP とコンカレンシー ランタイムの違いについて説明し、既存の OpenMP コードからコンカレンシー ランタイムの使用に移行する方法の例を示します。

OpenMP プログラミング モデルは、オープン標準により定義されており、Fortran および C/C++ プログラミング言語へのバインドが適切に定義されています。 Microsoft C++ コンパイラでサポートされている OpenMP バージョン 2.0 および 2.5 は、反復処理の並列アルゴリズムに適しています。つまり、これらは、データの配列を並列に反復処理します。 OpenMP 3.0 では、反復的なタスクに加えて、非反復なタスクがサポートされています。

OpenMP は、並列化の度合いが事前に決定され、システムで使用可能なリソースと対応する場合に最も効果的です。 OpenMP モデルは、非常に大きい計算の問題が 1 台のコンピューターの処理リソース全体に分散される高パフォーマンスのコンピューティングに特に適しています。 このシナリオでは、ハードウェア環境が全体的に固定されており、開発者は、このアルゴリズムが実行されるときに、すべてのコンピューティング リソースへの排他アクセスがあることを合理的に期待できます。

ただし、制約が少ないコンピューティング環境は、OpenMP に適していない場合があります。 たとえば、再帰の問題 (クイックソート アルゴリズム、データ ツリーの検索など) を、OpenMP 2.0 および 2.5 を使用して実装することはより難しくなります。 コンカレンシー ランタイムは、非同期エージェント ライブラリ並列パターン ライブラリ (PPL) を提供することで、OpenMP の機能を補完します。 非同期エージェント ライブラリでは、粒度の粗いタスクの並列処理がサポートされています。一方、PPL では、より詳細な並列タスクがサポートされています。 コンカレンシー ランタイムには、操作を並列で実行するために必要なインフラストラクチャが備わっているため、アプリケーションのロジックに集中できます。 ただし、コンカレンシー ランタイムによってさまざまなプログラミング モデルが有効になるため、そのスケジューリング オーバーヘッドは、OpenMP などの他のコンカレンシー ライブラリよりも大きい可能性があります。 そのため、既存の OpenMP コードを変換して、コンカレンシー ランタイムを使用する場合は、パフォーマンスを段階的にテストすることをお勧めします。

OpenMP からコンカレンシー ランタイムに移行するケース

既存の OpenMP コードを移行して、コンカレンシー ランタイム使用すると便利な場合を以下に示します。

ケース コンカレンシー ランタイムの利点
拡張可能な同時実行プログラミング フレームワークが必要である。 コンカレンシー ランタイムの機能の多くは拡張できます。 既存の機能を組み合わせて新しい機能を作成することもできます。 OpenMP はコンパイラ ディレクティブに依存しているため、簡単には拡張できません。
アプリケーションが協調ブロッキングからメリットを得る可能性がある。 まだ使用できないリソースが必要であるためにタスクがブロックされた場合、コンカレンシー ランタイムは、最初のタスクがリソースを待機している間に他のタスクを実行できます。
アプリケーションが、動的負荷分散からメリットを得られる可能性がある。 コンカレンシー ランタイムは、ワークロードの変化に応じてコンピューティング リソースの割り当てを調整するスケジューリング アルゴリズムを使用します。 OpenMP では、スケジューラがコンピューティング リソースを並列リージョンに割り当てると、それらのリソース割り当ては計算全体で固定されます。
例外処理のサポートが必要である。 PPL を使用すると、並列領域またはループの内部と外側の両方で例外をキャッチできます。 OpenMP では、並列領域またはループ内で例外を処理する必要があります。
キャンセル メカニズムが必要である。 PPL を使用すると、アプリケーションは個々のタスクと並列作業ツリーの両方を取り消しできます。 OpenMP では、アプリケーションが独自のキャンセル メカニズムを実装する必要があります。
開始時とはことなるコンテキストで終了するための並列コードが必要である。 コンカレンシー ランタイムを使用して、特定のコンテキストでタスクを開始し、それとは別のコンテキストでタスクの待機または取り消しを行えます。 OpenMP では、並列処理はすべて、開始時のコンテキストで完了する必要があります。
デバッグのサポートを強化する必要がある。 Visual Studio には、[並列スタック] ウィンドウと [並列タスク] ウィンドウが備わっており、マルチスレッド化されたアプリケーションをより簡単にデバッグできます。

コンカレンシー ランタイムのデバッグ サポートの詳細については、「[タスク] ウィンドウの使用」、「[並列スタック] ウィンドウの使用」、および「チュートリアル: 並列アプリケーションのデバッグ」を参照してください。

OpenMP からコンカレンシー ランタイムに移行しないケース

既存の OpenMP コードを移行してコンカレンシー ランタイムを使用するのが適切ではない可能性のあるケースを次に示します。

ケース 説明
アプリケーションが既に要件を満たしている。 アプリケーションのパフォーマンスと現在のデバッグ サポートに満足している場合、移行は適切ではない可能性があります。
並列ループの本体が、ほとんど作業を実行しない。 特にループ本体が比較的小さい場合、コンカレンシー ランタイム タスク スケジューラーのオーバーヘッドが、ループ本体を並列で実行するメリットを上回らない可能性があります。
アプリケーションは C で記述されている。 コンカレンシー ランタイムでは多数の C++ 機能が使用されるため、C アプリケーションで完全に使用できるコードを記述できない場合、適していない可能性があります。

方法: OpenMP の parallel for ループを変換し、コンカレンシー ランタイムを使用する

OpenMP の parallel ディレクティブと for ディレクティブを使用する基本的なループを変換して、コンカレンシー ランタイムの concurrency::parallel_for アルゴリズムを使用する方法を示します。

方法: キャンセル処理を使用する OpenMP ループを変換し、コンカレンシー ランタイムを使用する
必ずしもすべての反復を実行する必要のない OpenMP parallelfor ループを変換して、コンカレンシー ランタイムの取り消しメカニズムを使用する方法を示します。

方法: 例外処理を使用する OpenMP ループを変換し、コンカレンシー ランタイムを使用する
例外処理を実行する OpenMP parallelfor ループを変換して、コンカレンシー ランタイムの例外処理メカニズムが使用されるようにする方法を示します。

方法: 減少変数を使用する OpenMP ループを変換し、コンカレンシー ランタイムを使用する
reduction 句を使用する OpenMP parallelfor ループを変換して、コンカレンシー ランタイムを使用する方法を示します。

関連項目

コンカレンシー ランタイム
OpenMP
並列パターン ライブラリ (PPL)
非同期エージェント ライブラリ