コンピューティングにおいて、並列プログラミングモデルは並列コンピュータアーキテクチャの抽象化であり、プログラム内でアルゴリズムとその構成を表現するのに便利です。プログラミングモデルの価値は、その汎用性(さまざまなアーキテクチャに対してさまざまな問題をどれだけうまく表現できるか)とパフォーマンス(コンパイルされたプログラムがどれだけ効率的に実行できるか)によって判断できます。[ 1 ]並列プログラミングモデルの実装は、既存の言語の拡張として、プログラミング言語から呼び出されるライブラリの形をとることができます。
特定のプログラミングモデルに関する合意は、そのモデルをサポートするさまざまな並列コンピュータの構築につながり、ソフトウェアの移植性を促進するため重要である。この意味で、プログラミングモデルはハードウェアとソフトウェアの間の橋渡し役と呼ばれる。[ 2 ]
並列プログラミングモデルの分類は、大きく分けてプロセス間の相互作用と問題分解の2つの領域に分類できます。[ 3 ] [ 4 ] [ 5 ]
プロセス間相互作用とは、並列プロセス同士が通信するためのメカニズムのことである。最も一般的な相互作用の形態は共有メモリとメッセージパッシングであるが、相互作用は暗黙的(プログラマには見えない)な場合もある。
共有メモリは、プロセス間でデータを効率的に受け渡す手段です。共有メモリモデルでは、並列プロセスはグローバルアドレス空間を共有し、非同期的に読み書きを行います。非同期の同時アクセスは競合状態を引き起こす可能性があり、ロック、セマフォ、モニタなどのメカニズムを使用してこれを回避できます。従来のマルチコアプロセッサは共有メモリを直接サポートしており、 Cilk、OpenMP、Threading Building Blocksなどの多くの並列プログラミング言語やライブラリは、この機能を活用するように設計されています。
メッセージパッシングモデルでは、並列プロセスはメッセージを相互に渡すことでデータを交換します。これらの通信は、受信者が準備できる前にメッセージを送信できる非同期通信と、受信者が準備できている必要がある同期通信に分けられます。メッセージパッシングの形式化であるCommunicating sequential processes (CSP) は、同期通信チャネルを使用してプロセスを接続しており、 Occam、Limbo、Goなどの重要な言語につながりました。一方、アクターモデルは非同期メッセージパッシングを使用しており、 D、Scala 、SALSAなどの言語の設計に採用されています。
分割グローバルアドレス空間(PGAS)モデルは、共有メモリとメッセージパッシングの中間的なアプローチを提供します。PGASは、論理的に分割されたグローバルメモリアドレス空間の抽象化を提供し、各プロセスにローカルな部分が割り当てられます。並列プロセスは、共有メモリモデルと同様に、グローバルアドレス空間に対して非同期的に操作(読み取りや書き込みなど)を実行することで通信します。しかし、グローバルアドレス空間を特定のプロセスに親和性のある部分に意味的に分割することで、プログラマは参照の局所性を活用し、分散メモリ並列コンピュータ上での効率的な実装が可能になります。PGASは、 Fortran 2008、Chapel、UPC++、SHMEMなど、多くの並列プログラミング言語やライブラリで提供されています。
暗黙的モデルでは、プログラマーにはプロセス間の相互作用が見えず、代わりにコンパイラやランタイムがそれを実行します。暗黙的並列処理の2つの例として、高レベル操作内の並行処理が規定されているドメイン固有言語と、副作用がないため非依存関数を並列実行できる関数型プログラミング言語があります。 [ 6 ]しかし、この種の並列処理は管理が難しく[ 7 ] 、 Concurrent HaskellやConcurrent MLなどの関数型言語は、並列処理を明示的かつ正しく管理する機能を提供します。
並列プログラムは、同時に実行されるプロセスで構成されます。問題の分解は、構成要素となるプロセスがどのように定式化されるかに関係します。[ 8 ] [ 5 ]
タスク並列モデルは、プロセス、つまり実行スレッドに焦点を当てます。これらのプロセスは多くの場合、動作が異なり、そのため通信の必要性が強調されます。タスク並列処理は、メッセージパッシング通信を表現する自然な方法です。フリンの分類法では、タスク並列処理は通常、 MIMD / MPMDまたはMISDに分類されます。
データ並列モデルは、データセット(通常は規則的な構造を持つ配列)に対する演算の実行に重点を置いています。一連のタスクがこのデータに対して演算を行いますが、それぞれが互いに素なパーティションに対して独立して実行されます。フリンの分類法では、データ並列処理は通常、 MIMD / SPMDまたはSIMDに分類されます。
ストリーム並列処理(パイプライン並列処理とも呼ばれる)は、計算を複数のステージに分割し、各ステージで入力データの一部を処理することに重点を置いています。各ステージは独立して並行して動作し、あるステージの出力が次のステージへの入力となります。ストリーム並列処理は、連続的なデータストリームやパイプライン処理を伴うアプリケーションに特に適しています。
暗黙的なプロセス間相互作用と同様に、並列処理の暗黙的なモデルは、コンパイラ、ランタイム、またはハードウェアが処理を担当するため、プログラマには何も明らかにされません。例えば、コンパイラでは、自動並列化は逐次コードを並列コードに変換するプロセスであり、コンピュータアーキテクチャでは、スーパースカラ実行は命令レベルの並列性を利用して演算を並列実行するメカニズムです。
並列プログラミングモデルは、計算モデルと密接に関連しています。並列計算モデルは、計算プロセスのコストを分析するために使用される抽象化ですが、ハードウェアやソフトウェアで効率的に実装できるという意味で、必ずしも実用的である必要はありません。対照的に、プログラミングモデルは、ハードウェアとソフトウェアの実装に関する実際的な考慮事項を具体的に含意します。[ 9 ]
並列プログラミング言語は、1つまたは複数のプログラミングモデルに基づいて構築される場合がある。例えば、高性能Fortranは共有メモリ相互作用とデータ並列問題分解に基づいており、Goは共有メモリとメッセージパッシングによる相互作用のためのメカニズムを提供している。