
並列コンピューティングは、多数の計算や処理を同時に実行するタイプの計算です。 [ 1 ]大きな問題は多くの場合、より小さな問題に分割でき、それらを同時に解決できます。並列コンピューティングには、ビットレベル、命令レベル、データ、タスク並列など、いくつかの異なる形式があります。並列処理は、高性能コンピューティングで長年使用されてきましたが、周波数スケーリングを妨げる物理的な制約により、より幅広い関心を集めています。[ 2 ]近年、コンピュータの消費電力(およびそれに伴う発熱)が懸念事項となっているため、[ 3 ]並列コンピューティングは、主にマルチコアプロセッサの形で、コンピュータアーキテクチャの支配的なパラダイムとなっています。[ 4 ]

コンピュータサイエンスでは、並列処理と並行処理は異なるものです。並列プログラムは複数のCPUコアを使用し、各コアは独立してタスクを実行します。一方、並行処理は、単一のCPUコア上でも複数のタスクを処理できるようにするもので、コアは必ずしもすべてのタスクを完了することなく、タスク(つまりスレッド)間を切り替えます。プログラムは、並列処理と並行処理の両方の特性を持つ場合もあれば、どちらも持たない場合、あるいは両方を組み合わせた場合もあります。[ 5 ]
並列コンピュータは、ハードウェアが並列処理をサポートするレベルに応じて大まかに分類できます。マルチコアコンピュータやマルチプロセッサコンピュータは、1台のマシン内に複数の処理要素を持ち、クラスタ、MPP、グリッドは、複数のコンピュータを使用して同じタスクを実行します。特定のタスクを高速化するために、従来のプロセッサと併用して、特殊な並列コンピュータアーキテクチャが使用されることもあります。
ビットレベル並列処理や命令レベル並列処理のように、場合によっては並列処理はプログラマーにとって透過的ですが、明示的に並列化されたアルゴリズム、特に並行処理を使用するアルゴリズムは、逐次処理のアルゴリズムよりも記述が困難です。 [ 6 ]なぜなら、並行処理によって潜在的なソフトウェアバグの新たな種類がいくつか発生し、その中でも競合状態が最も一般的だからです。異なるサブタスク間の通信と同期は、通常、並列プログラムのパフォーマンスを最適化する上で最大の障害となります。
並列化によって単一プログラムの高速化がどの程度可能になるかについての理論的な上限は、アムダールの法則によって示されており、それは並列化を利用できる時間の割合によって制限されるというものである。
従来、コンピュータソフトウェアは逐次計算用に作成されてきました。問題を解決するために、アルゴリズムが構築され、命令の逐次ストリームとして実装されます。これらの命令は、1台のコンピュータの中央処理装置で実行されます。一度に実行できる命令は1つだけで、その命令が完了すると次の命令が実行されます。[ 7 ]
一方、並列コンピューティングは、複数の処理要素を同時に使用して問題を解決します。これは、問題を独立した部分に分割し、各処理要素がアルゴリズムのそれぞれの部分を他の部分と同時に実行できるようにすることで実現されます。処理要素は多様であり、複数のプロセッサを備えた単一のコンピュータ、ネットワーク接続された複数のコンピュータ、専用ハードウェア、または上記の任意の組み合わせなどのリソースが含まれます。[ 7 ]歴史的に、並列コンピューティングは、特に気象学などの自然科学や工学分野における科学計算や科学的問題のシミュレーションに使用されていました。これにより、並列ハードウェアとソフトウェアの設計、および高性能コンピューティングが実現しました。[ 8 ]
周波数スケーリングは、1980 年代半ばから 2004 年までコンピュータのパフォーマンスが向上した主な理由でした。プログラムの実行時間は、命令数に命令あたりの平均時間を掛けたものに等しくなります。他のすべてを一定に保つと、クロック周波数を上げると、命令を実行するのにかかる平均時間が短くなります。したがって、周波数を上げると、すべての計算バウンドプログラムの実行時間が短くなります。[ 9 ]ただし、チップの消費電力Pは、 P = C × V 2 × Fという式で与えられます。ここで、Cはクロック サイクルごとに切り替えられる容量(入力が変化するトランジスタの数に比例)、Vは電圧、Fはプロセッサ周波数 (1 秒あたりのサイクル数) です。[ 10 ]周波数を上げると、プロセッサで使用される電力が増加します。プロセッサの消費電力の増加は、最終的にIntelが 2004 年 5 月 8 日にTejas および Jayhawkプロセッサをキャンセルすることにつながり、これは一般的に、周波数スケーリングが支配的なコンピュータ アーキテクチャ パラダイムとしての終焉として挙げられています。[ 11 ]
消費電力と過熱の問題に対処するため、主要な中央処理装置(CPU またはプロセッサ) のメーカーは、マルチコアを備えた電力効率の高いプロセッサの製造を開始しました。コアはプロセッサの計算ユニットであり、マルチコアプロセッサでは各コアが独立しており、同じメモリに同時にアクセスできます。マルチコアプロセッサは、並列コンピューティングをデスクトップコンピュータにもたらしました。そのため、シリアルプログラムの並列化は主流のプログラミングタスクになりました。2012 年、クアッドコアプロセッサがデスクトップコンピュータの標準となり、サーバーには10 個以上のコアプロセッサが搭載されました。ムーアの法則は、プロセッサあたりのコア数が 18 ~ 24 か月ごとに倍増すると予測しました。[ 12 ] 2023 年までに、一部のプロセッサは 100 個以上のコアを搭載しました。熱と設計上の制約により、パフォーマンスと効率のコアが混在する設計 ( ARM の big.LITTLE設計など) もあります。
オペレーティングシステムは、利用可能なコア上でさまざまなタスクやユーザープログラムを並列実行することを保証できます。しかし、シリアルソフトウェアプログラムがマルチコアアーキテクチャを最大限に活用するには、プログラマはコードを再構築して並列化する必要があります。アプリケーションソフトウェアの実行速度の向上は、周波数スケーリングではもはや実現できず、代わりにプログラマはマルチコアアーキテクチャの増大する計算能力を活用するためにソフトウェアコードを並列化する必要があります。[ 13 ]


理想的には、並列化による高速化は線形であるべきです。つまり、処理要素数を2倍にすれば実行時間は半分になり、さらに2倍にすれば再び半分になるはずです。しかし、最適な高速化を実現する並列アルゴリズムはごくわずかです。ほとんどのアルゴリズムは、処理要素数が少ない場合はほぼ線形の高速化を示しますが、処理要素数が多くなると一定値に収束します。
システム全体の最大潜在的高速化は、アムダールの法則によって計算できます。[ 14 ]アムダールの法則は、タスクの並列化可能なコンポーネントと並列化不可能なコンポーネントの両方の強化のバランスを取ることで、最適なパフォーマンスの向上が達成されることを示しています。さらに、プロセッサ数を増やすと収穫逓減が生じ、ある一定の点を超えると高速化の利得は無視できるほど小さくなることを明らかにしました。[ 15 ] [ 16 ]
アムダールの法則には、固定ワークロードの仮定、プロセス間通信と同期オーバーヘッドの無視、主に計算面に焦点を当て、データ永続性、I/O操作、メモリアクセスオーバーヘッドなどの外的要因を無視するなど、限界がある。[ 17 ] [ 18 ] [ 19 ]
グスタフソンの法則とユニバーサルスケーラビリティ法則は、並列性能のより現実的な評価を与える。[ 20 ] [ 21 ]

並列アルゴリズムを実装する上で、データの依存関係を理解することは不可欠です。依存関係のある計算の最も長い連鎖(クリティカルパスと呼ばれる)よりも速く実行できるプログラムはありません。なぜなら、連鎖内の先行する計算に依存する計算は、順番に実行されなければならないからです。しかし、ほとんどのアルゴリズムは、単に長い依存関係のある計算の連鎖だけで構成されているわけではありません。通常、独立した計算を並列実行できる機会が存在します。
P iとP j を2 つのプログラムセグメントとする。バーンスタインの条件[ 22 ]は、この 2 つのセグメントが独立しており、並列実行できる場合を記述する。P i については、すべての入力変数をI i 、出力変数をO iとし、 P jについても同様とする。P iとP j は、以下の条件を満たす場合に独立している。
最初の条件に違反すると、フロー依存性が生じ、最初のセグメントが2番目のセグメントで使用される結果を生成します。2番目の条件は、2番目のセグメントが最初のセグメントに必要な変数を生成する場合、反依存性を表します。3番目で最後の条件は出力依存性を表します。2つのセグメントが同じ場所に書き込む場合、結果は論理的に最後に実行されたセグメントから得られます。[ 23 ]
以下の関数は、いくつかの種類の依存関係を示しています。
1: 関数 Dep(a, b) 2: c := a * b 3: d := 3 * c 4: 関数終了
この例では、命令3は命令2の結果を使用するため、命令3は命令2より前に(あるいは並行して)実行することはできません。これは条件1に違反し、フロー依存性を引き起こします。
1: 関数 NoDep(a, b) 2: c := a * b 3: d := 3 * b 4: e := a + b 5: 関数終了
この例では、命令間に依存関係がないため、すべて並列実行できます。
バーンスタインの条件では、異なるプロセス間でメモリを共有することは認められていません。そのため、セマフォ、バリア、またはその他の同期方法など、アクセス間の順序を強制する何らかの手段が必要となります。
並列プログラムのサブタスクは、しばしばスレッドと呼ばれます。一部の並列コンピュータアーキテクチャでは、ファイバーと呼ばれるより小さく軽量なバージョンのスレッドを使用し、他のアーキテクチャでは、プロセスと呼ばれるより大きなバージョンを使用します。ただし、「スレッド」は一般的にサブタスクの総称として受け入れられています。[ 24 ]スレッドは、オブジェクトやその他のリソースへの同期アクセスを必要とすることがよくあります。たとえば、スレッド間で共有されている変数を更新する必要がある場合などです。同期がない場合、2 つのスレッド間の命令は任意の順序でインターリーブされる可能性があります。たとえば、次のプログラムを考えてみましょう。
命令1Bが1Aと3Aの間で実行される場合、または命令1Aが1Bと3Bの間で実行される場合、プログラムは誤ったデータを生成します。これは競合状態として知られています。プログラマは相互排他を実現するためにロックを使用する必要があります。ロックとは、あるスレッドが変数を制御し、その変数がロック解除されるまで他のスレッドがその変数を読み書きできないようにするプログラミング言語の構成要素です。ロックを保持しているスレッドは、クリティカルセクション(特定の変数への排他的アクセスを必要とするプログラムのセクション)を自由に実行でき、実行が完了したらデータをロック解除できます。したがって、プログラムの正しい実行を保証するために、上記のプログラムはロックを使用するように書き換えることができます。
一方のスレッドは変数 V を正常にロックしますが、もう一方のスレッドはロックアウトされ、 V が再びロック解除されるまで処理を進めることができません。これにより、プログラムの正しい実行が保証されます。スレッドがリソースへのアクセスを直列化する必要がある場合、プログラムの正しい実行を保証するためにロックが必要になることがありますが、ロックを使用するとプログラムの実行速度が大幅に低下し、信頼性に影響を与える可能性があります。[ 25 ]
非アトミックロックを使用して複数の変数をロックすると、プログラムのデッドロックが発生する可能性があります。アトミックロックは、複数の変数を一度にロックします。すべてをロックできない場合は、どの変数もロックしません。2 つのスレッドがそれぞれ同じ 2 つの変数を非アトミックロックを使用してロックする必要がある場合、一方のスレッドが一方の変数をロックし、もう一方のスレッドがもう一方の変数をロックする可能性があります。このような場合、どちらのスレッドも完了できず、デッドロックが発生します。[ 26 ]
多くの並列プログラムでは、サブタスクが同期して動作する必要があります。そのためにはバリアの使用が必要です。バリアは通常、ロックまたはセマフォを使用して実装されます。[ 27 ]ロックフリーおよび待機フリーアルゴリズムとして知られるアルゴリズムのクラスでは、ロックとバリアの使用を完全に回避します。ただし、このアプローチは一般的に実装が難しく、適切に設計されたデータ構造が必要です。[ 28 ]
すべての並列化が高速化につながるわけではありません。一般的に、タスクがより多くのスレッドに分割されるにつれて、それらのスレッドは、互いに通信したり、リソースへのアクセスを互いに待ったりすることに費やす時間の割合がますます大きくなります。[ 29 ] [ 30 ]リソースの競合や通信によるオーバーヘッドが他の計算に費やす時間の大部分を占めるようになると、さらなる並列化(つまり、ワークロードをさらに多くのスレッドに分割すること)は、完了に必要な時間を減少させるのではなく増加させます。この問題は、並列スローダウンとして知られており、[ 31 ]ソフトウェアの分析と再設計によって改善できる場合があります。[ 32 ]
アプリケーションは、サブタスク間の同期や通信の頻度に基づいて分類されることが多い。サブタスクが1秒間に何度も通信する必要がある場合、そのアプリケーションはきめ細かい並列性を示す。1秒間に何度も通信しない場合は粗い並列性を示し、通信がほとんど、あるいは全く必要ない場合は、並列性が低すぎる(シャッフルパラレル)ことを示す。並列性が低すぎるアプリケーションは、並列化が最も容易であると考えられている。
マイケル・J・フリンは、並列(および逐次)コンピュータとプログラムのための初期の分類システムの一つを考案しました。これは現在、フリンの分類法として知られています。フリンは、プログラムとコンピュータが単一の命令セットを使用しているか、複数の命令セットを使用しているか、また、それらの命令が単一のデータセットを使用しているか、複数のデータセットを使用しているかによって分類しました。
単一命令単一データ (SISD) 分類は、完全に逐次的なプログラムに相当します。単一命令複数データ (SIMD) 分類は、大規模なデータセットに対して同じ操作を繰り返し実行することに類似しています。これは、信号処理アプリケーションでよく行われます。複数命令単一データ (MISD) は、あまり使用されない分類です。これに対処するためのコンピュータアーキテクチャ (シストリックアレイなど) が考案されましたが、このクラスに該当するアプリケーションはほとんど実現しませんでした。複数命令複数データ (MIMD) プログラムは、並列プログラムの中で最も一般的なタイプです。
デイビッド・A・パターソンとジョン・L・ヘネシーによれば、「もちろん、これらのカテゴリのハイブリッドである機械もあるが、この古典的なモデルは、シンプルで理解しやすく、良い第一近似を与えるため生き残ってきた。また、おそらく理解しやすさのため、最も広く使用されている方式でもある。」[ 34 ]
並列コンピューティングは、実際には、複数のプロセスからのデータをマージすることに伴うコストが原因で、かなりのオーバーヘッドが発生する可能性があります。具体的には、プロセス間の通信と同期により、同じデータを単一のスレッドで処理する場合と比較して、オーバーヘッドが大幅に高くなる場合があり、多くの場合、2桁以上高くなります。[ 35 ] [ 36 ] [ 37 ]したがって、全体的な改善は慎重に評価する必要があります。

1970年代の超大規模集積回路(VLSI)コンピュータチップ製造技術の出現から1986年頃まで、コンピュータアーキテクチャの高速化は、プロセッサが1サイクルあたりに処理できる情報量であるコンピュータワードサイズを2倍にすることによって推進されました。 [ 38 ]ワードサイズを大きくすると、ワードの長さよりも大きいサイズの変数に対して演算を実行するためにプロセッサが実行しなければならない命令の数が減少します。たとえば、8ビットプロセッサが2つの16ビット整数を加算する必要がある場合、プロセッサはまず 標準加算命令を使用して各整数の下位8ビットを加算し、次に キャリー付き加算命令と下位加算からのキャリービットを使用して上位8ビットを加算する必要があります。したがって、8ビットプロセッサは1つの演算を完了するために2つの命令を必要としますが、16ビットプロセッサは1つの命令で演算を完了できます。
歴史的に見ると、4ビットマイクロプロセッサは8ビット、16ビット、そして32ビットのマイクロプロセッサへと置き換えられてきました。この流れは、汎用コンピューティングの標準として20年間君臨してきた32ビットプロセッサの登場によって概ね終焉を迎えました。64ビットプロセッサが普及したのは、2000年代初頭にx86-64アーキテクチャが登場してからのことです。

コンピュータプログラムは、本質的にはプロセッサによって実行される命令のストリームです。命令レベルの並列処理がない場合、プロセッサはクロックサイクルごとに 1 未満の命令しか発行できません( IPC < 1 )。このようなプロセッサはサブスカラプロセッサとして知られています。これらの命令は、プログラムの結果を変えることなく、グループに並べ替えたり結合したりして並列に実行できます。これは命令レベルの並列処理として知られています。命令レベルの並列処理の進歩は、1980 年代半ばから 1990 年代半ばまでコンピュータ アーキテクチャを支配しました。[ 39 ]

現代のプロセッサはすべて、マルチステージ命令パイプラインを備えています。パイプラインの各ステージは、そのステージの命令に対してプロセッサが実行する異なるアクションに対応しています。N ステージのパイプラインを持つプロセッサは、完了の異なるステージで最大N 個の異なる命令を持つことができ、クロック サイクルごとに 1 つの命令を発行できます ( IPC = 1 )。これらのプロセッサは、スカラープロセッサとして知られています。パイプライン プロセッサの典型的な例はRISCプロセッサで、命令フェッチ (IF)、命令デコード (ID)、実行 (EX)、メモリ アクセス (MEM)、レジスタ ライトバック (WB) の 5 つのステージがあります。Pentium 4プロセッサは 35 ステージのパイプラインを持っていました。[ 40 ]

最新のプロセッサのほとんどは、複数の実行ユニットを備えています。通常、この機能はパイプライン処理と組み合わされ、クロックサイクルごとに複数の命令を発行できます ( IPC > 1 )。これらのプロセッサはスーパースカラプロセッサとして知られています。スーパースカラプロセッサは、複数の実行ユニットが完全なプロセッサ (つまり処理ユニット) ではないという点で、マルチコアプロセッサとは異なります。命令は、それらの間にデータ依存性がない場合にのみグループ化できます。スコアボードとトマスロアルゴリズム(スコアボードに似ていますが、レジスタリネーミングを使用します) は、アウトオブオーダー実行と命令レベル並列処理を実装するための最も一般的な手法の 2 つです。
タスク並列性とは、並列プログラムの特徴の一つで、「全く異なる計算を同じデータセットまたは異なるデータセットに対して実行できる」という点である。[ 41 ]これは、同じ計算を同じデータセットまたは異なるデータセットに対して実行するデータ並列性とは対照的である。タスク並列性では、タスクをサブタスクに分解し、各サブタスクをプロセッサに割り当てて実行する。プロセッサはこれらのサブタスクを並行して、多くの場合協調して実行する。タスク並列性は通常、問題のサイズに応じてスケーリングしない。[ 42 ]
スーパーワードレベルの並列処理は、ループ展開と基本ブロックベクトル化に基づくベクトル化手法です。ループベクトル化アルゴリズムとは異なり、座標、カラーチャネルの操作、手動で展開されたループなど、インラインコードの並列性を利用できます。[ 43 ]
並列コンピュータのメインメモリは、共有メモリ(単一のアドレス空間内のすべての処理要素間で共有される)か、分散メモリ(各処理要素が独自のローカルアドレス空間を持つ)のいずれかです。[ 44 ]分散メモリとは、メモリが論理的に分散されていることを意味しますが、多くの場合、物理的にも分散されていることを意味します。分散共有メモリとメモリ仮想化は、処理要素が独自のローカルメモリを持ち、非ローカルプロセッサ上のメモリにアクセスできるという、2 つのアプローチを組み合わせたものです。ローカルメモリへのアクセスは、通常、非ローカルメモリへのアクセスよりも高速です。スーパーコンピュータでは、分散共有メモリ空間は、 PGASなどのプログラミングモデルを使用して実装できます。このモデルにより、1 つの計算ノード上のプロセスが、別の計算ノードのリモートメモリに透過的にアクセスできます。すべての計算ノードは、 Infinibandなどの高速インターコネクトを介して外部共有メモリシステムにも接続されています。この外部共有メモリシステムはバーストバッファとして知られており、通常は複数の I/O ノードに物理的に分散された不揮発性メモリのアレイから構築されます。

メインメモリの各要素に等しいレイテンシと帯域幅でアクセスできるコンピュータアーキテクチャは、均一メモリアクセス(UMA)システムと呼ばれます。通常、これはメモリが物理的に分散されていない共有メモリシステムでのみ実現可能です。この特性を持たないシステムは、非均一メモリアクセス(NUMA)アーキテクチャと呼ばれます。分散メモリシステムは、非均一メモリアクセスとなります。
コンピュータシステム( GroqのLPUを除く)はキャッシュを利用します。キャッシュとは、プロセッサの近くに配置された小型で高速なメモリで、メモリ値の一時的なコピーを格納します(物理的にも論理的にも近い)。並列コンピュータシステムでは、同じ値が複数の場所に格納される可能性のあるキャッシュに問題があり、プログラムの実行が誤る可能性があります。これらのコンピュータには、キャッシュされた値を追跡し、戦略的にそれらを消去することで、プログラムの正しい実行を保証するキャッシュコヒーレンシーシステムが必要です。バススヌーピングは、どの値がアクセスされているか(したがって消去する必要があるか)を追跡するための最も一般的な方法の1つです。大規模で高性能なキャッシュコヒーレンシーシステムを設計することは、コンピュータアーキテクチャにおいて非常に難しい問題です。その結果、共有メモリコンピュータアーキテクチャはスケーラブルではなく、分散メモリシステムはスケーラブルになります。[ 44 ]
プロセッサ間およびプロセッサとメモリ間の通信は、共有メモリ(マルチポートまたは多重化)、クロスバースイッチ、共有バス、またはスター、リング、ツリー、ハイパーキューブ、ファットハイパーキューブ(ノードに複数のプロセッサを持つハイパーキューブ)、n次元メッシュなど、無数のトポロジーの相互接続ネットワークを介して、ハードウェアでいくつかの方法で実装できます。
相互接続されたネットワークに基づく並列コンピュータでは、直接接続されていないノード間でメッセージをやり取りできるように、何らかのルーティング機構が必要となる。大規模なマルチプロセッサマシンでは、プロセッサ間の通信に使用される媒体は階層構造になっていることが多い。
並列コンピュータは、ハードウェアが並列処理をサポートするレベルに応じて大まかに分類できる。この分類は、基本的な計算ノード間の距離とほぼ一致する。これらは相互に排他的なものではなく、例えば、対称型マルチプロセッサのクラスタは比較的よく見られる。
マルチコアプロセッサとは、同一チップ上に複数の処理ユニット(「コア」と呼ばれる)を搭載したプロセッサのことです。このプロセッサは、複数の実行ユニットを持ち、1つの命令ストリーム(スレッド)からクロックサイクルごとに複数の命令を発行できるスーパースカラプロセッサとは異なります。一方、マルチコアプロセッサは、複数の命令ストリームからクロックサイクルごとに複数の命令を発行できます。ソニーのPlayStation 3向けに設計されたIBMのCellマイクロプロセッサは、代表的なマルチコアプロセッサです。マルチコアプロセッサの各コアは、潜在的にスーパースカラである可能性があり、つまり、各コアはクロックサイクルごとに1つのスレッドから複数の命令を発行できます。
同時マルチスレッド (インテルのハイパースレッディングが最もよく知られている)は、擬似マルチコアの初期形態である。同時マルチスレッドに対応したプロセッサは、同一処理ユニット内に複数の実行ユニットを備えており(つまり、スーパースカラアーキテクチャを採用している)、複数のスレッドからクロックサイクルごとに複数の命令を発行できる。一方、時間的マルチスレッドは、同一処理ユニット内に単一の実行ユニットを備えており、複数のスレッドから一度に1つの命令を発行できる。
対称型マルチプロセッサ (SMP) は、メモリを共有しバスを介して接続される複数の同一プロセッサを備えたコンピュータ システムです。[ 45 ]バス競合により、バス アーキテクチャのスケーリングが妨げられます。そのため、SMP は通常 32 個を超える プロセッサで構成されません。[ 46 ]プロセッサのサイズが小さく、大容量キャッシュによってバス帯域幅の要件が大幅に削減されるため、十分なメモリ帯域幅が存在する限り、このような対称型マルチプロセッサは非常にコスト効率が高くなります。[ 45 ]
分散コンピュータ(分散メモリマルチプロセッサとも呼ばれる)は、処理要素がネットワークで接続されている分散メモリコンピュータシステムです。分散コンピュータは高いスケーラビリティを備えています。「同時コンピューティング」、「並列コンピューティング」、「分散コンピューティング」という用語は重複が多く、明確な区別はありません。[ 47 ] [ 48 ]同じシステムが「並列」と「分散」の両方として特徴付けられる場合があり、典型的な分散システムのプロセッサは並列に同時実行されます。[ 49 ] [ 50 ]

クラスタとは、密接に連携して動作する疎結合コンピュータのグループであり、ある意味では単一のコンピュータとみなすことができます。[ 51 ]クラスタは、ネットワークで接続された複数のスタンドアロンマシンで構成されています。クラスタ内のマシンは対称である必要はありませんが、対称でない場合は負荷分散が難しくなります。最も一般的なタイプのクラスタはBeowulfクラスタで、これはTCP/IP Ethernetローカルエリアネットワークで接続された複数の同一の市販コンピュータ上に実装されたクラスタです。[ 52 ] Beowulfテクノロジーは、もともとThomas SterlingとDonald Beckerによって開発されました。Top500スーパーコンピュータの87%はクラスタです。[ 53 ]残りは、後述する大規模並列プロセッサです。
グリッドコンピューティングシステム(後述)は、並列処理が容易な問題を容易に処理できるため、現代のクラスタは通常、より困難な問題、つまりノード間で中間結果をより頻繁に共有する必要がある問題を処理するように設計されています。これには、高い帯域幅と、より重要なことに、低遅延の相互接続ネットワークが必要です。多くの歴史的および現在のスーパーコンピュータは、Cray Gemini ネットワークなど、クラスタコンピューティング用に特別に設計されたカスタマイズされた高性能ネットワークハードウェアを使用しています。[ 54 ] 2014 年現在、現在のほとんどのスーパーコンピュータは、 Myrinet、InfiniBand、またはGigabit Ethernetなどの市販の標準ネットワークハードウェアを使用しています。

大規模並列プロセッサ (MPP) は、多数のプロセッサがネットワークで接続された単一のコンピュータです。MPP はクラスタと多くの点で同じ特徴を持っていますが、MPP は専用の相互接続ネットワークを備えています (クラスタはネットワークに汎用ハードウェアを使用します)。また、MPP はクラスタよりも規模が大きく、通常 100 個をはるかに超える プロセッサを備えています。[ 55 ] MPP では、「各 CPU は独自のメモリとオペレーティングシステムおよびアプリケーションのコピーを保持しています。各サブシステムは高速相互接続を介して他のサブシステムと通信します。」[ 56 ]
IBMのBlue Gene/Lは、2009年6月のTOP500ランキングによると世界で5番目に速いスーパーコンピュータであり、MPPである。
グリッドコンピューティングは、並列コンピューティングの中で最も分散型の形態です。インターネットを介して通信するコンピュータ群を利用して、特定の問題に取り組みます。インターネットの帯域幅が狭く、レイテンシが非常に高いため、分散コンピューティングは通常、並列処理が容易な問題のみを扱います。
ほとんどのグリッドコンピューティングアプリケーションはミドルウェア(オペレーティングシステムとアプリケーションの間にあるソフトウェアで、ネットワークリソースを管理し、ソフトウェアインターフェースを標準化する)を使用します。最も一般的なグリッドコンピューティングミドルウェアは、Berkeley Open Infrastructure for Network Computing (BOINC)です。ボランティアコンピューティングソフトウェアは、コンピュータがアイドル状態のときに計算を実行する「余剰サイクル」を利用することがよくあります。 [ 57 ]
インターネットと高帯域幅ネットワークの普及により、クラウドコンピューティングが実現しました。これは、大規模並列処理リソースをサービスとして提供するモデルです。このパラダイムは基盤となるハードウェアを抽象化し、ユーザーは物理インフラストラクチャを管理することなく、拡張可能なワークロードに対応する仮想化クラスタにアクセスできるようになります。
最新の分散型台帳プロトコルは、並列コンピューティングの原理を適用して、従来のブロックチェーンの逐次的なボトルネックを克服します。状態空間をシャーディングすることで、新しいコンセンサスアーキテクチャは「大規模並列トランザクション処理」を可能にします。Cerberusなどのプロトコルで使用されているこのモデルでは、独立したトランザクションは、単一のグローバルブロックで逐次的に処理されるのではなく、異なるノードで同時に実行できる並列タスクとして扱われます。[ 58 ]
並列コンピューティングの分野には、ニッチな関心領域にとどまっている特殊な並列デバイスが存在する。これらは特定の分野に特化しているわけではないが、適用できる並列問題の種類は限られている傾向がある。
再構成可能コンピューティングとは、汎用コンピュータのコプロセッサとしてフィールドプログラマブルゲートアレイ(FPGA)を使用する技術である。FPGAは、本質的には、特定のタスクに合わせて回路構成を再構成できるコンピュータチップである。
FPGAは、 VHDL [ 59 ]やVerilog [ 60 ]などのハードウェア記述言語でプログラムできます。いくつかのベンダーは、ほとんどのプログラマーが慣れ親しんでいるCプログラミング言語の構文と意味をエミュレートしようとするC to HDL言語を作成しました。最もよく知られているC to HDL言語は、Mitrion-C、Impulse C、およびHandel-Cです。C ++に基づくSystemCの特定のサブセットもこの目的で使用できます。
AMDがHyperTransportテクノロジーをサードパーティベンダーに開放するという決定は、高性能再構成可能コンピューティングを実現する技術となった。[ 61 ] DRC Computer Corporationの最高執行責任者であるMichael R. D'Amour氏によると、「私たちが初めてAMDに入社したとき、彼らは私たちのことを『ソケット泥棒』と呼んだ。今では彼らは私たちのことをパートナーと呼んでいる。」[ 61 ]

グラフィックス処理ユニット(GPGPU)による汎用コンピューティングは、コンピュータ工学研究における比較的新しいトレンドです。GPUは、コンピュータグラフィックス処理のために高度に最適化されたコプロセッサです。[ 62 ]コンピュータグラフィックス処理は、データ並列処理、特に線形代数行列演算が主流の分野です。
初期の頃、GPGPU プログラムは通常のグラフィックス API を使用してプログラムを実行していました。しかし、GPU 上で汎用計算を行うための新しいプログラミング言語とプラットフォームがいくつか開発され、NvidiaとAMD はそれぞれCUDAとStream SDKを備えたプログラミング環境をリリースしました。その他の GPU プログラミング言語には、BrookGPU、PeakStream、RapidMindなどがあります。Nvidia はTesla シリーズで計算専用の製品もリリースしています。テクノロジー コンソーシアム Khronos Group は、 CPU と GPU で構成されるプラットフォーム間で実行されるプログラムを作成するためのフレームワークであるOpenCL仕様をリリースしました。AMD 、Apple、Intel、NvidiaなどがOpenCLをサポートしています。
並列アプリケーションに対応するために、いくつかの特定用途向け集積回路(ASIC)アプローチが考案されている。[ 63 ] [ 64 ] [ 65 ]
ASICは(定義上)特定のアプリケーションに特化しているため、そのアプリケーションに合わせて完全に最適化できます。その結果、特定のアプリケーションでは、ASICは汎用コンピュータよりも優れた性能を発揮する傾向があります。しかし、ASICはUVフォトリソグラフィによって製造されます。このプロセスにはマスクセットが必要であり、これは非常に高価になる可能性があります。マスクセットの費用は100万米ドルを超える場合があります。[ 66 ](チップに必要なトランジスタが小さいほど、マスクは高価になります。)一方、汎用コンピューティングの性能は時間の経過とともに向上し(ムーアの法則で説明されているように)、わずか1、2世代のチップでこれらの向上分を相殺する傾向があります。[ 61 ]初期費用が高く、ムーアの法則に牽引される汎用コンピューティングに追い抜かれる傾向があるため、ASICはほとんどの並列コンピューティングアプリケーションには実用的ではありません。しかし、いくつかは構築されています。1つの例は、分子動力学シミュレーションにカスタムASICを使用するPFLOPSのRIKEN MDGRAPE-3マシンです。

ベクトルプロセッサは、大量のデータに対して同じ命令を実行できるCPUまたはコンピュータシステムです。ベクトルプロセッサは、数値またはベクトルの線形配列に対して動作する高レベルの演算を備えています。ベクトル演算の例はA = B × Cで、A、B、Cはそれぞれ64ビット浮動小数点数の64要素ベクトルです。[ 67 ]これらはFlynnのSIMD分類と密接に関連しています。[ 67 ]
クレイ社は1970年代から1980年代にかけて、ベクトル処理コンピュータで有名になりました。しかし、CPUとしてもコンピュータシステム全体としても、ベクトルプロセッサは概して姿を消しました。現代のプロセッサの命令セットには、フリースケール・セミコンダクター社のAltiVecやインテル社のStreaming SIMD Extensions (SSE)など、ベクトル処理命令がいくつか含まれています。
並列コンピュータをプログラミングするために、並行プログラミング言語、ライブラリ、API、および並列プログラミングモデル(アルゴリズムスケルトンなど)が作成されてきました。これらは一般的に、基盤となるメモリアーキテクチャ(共有メモリ、分散メモリ、または共有分散メモリ)に関する仮定に基づいてクラスに分類できます。共有メモリプログラミング言語は、共有メモリ変数を操作することによって通信します。分散メモリはメッセージパッシングを使用します。POSIXスレッドとOpenMP は、最も広く使用されている共有メモリ API の 2 つであり、メッセージパッシングインターフェース(MPI) は、最も広く使用されているメッセージパッシングシステム API です。[ 68 ]並列プログラムのプログラミングで使用される概念の 1 つは未来の概念であり、プログラムのある部分が、将来のある時点でプログラムの別の部分に必要なデータを提供すると約束します。
並列プログラミングの標準化に向けた取り組みの一つとして、ハイブリッドマルチコア並列プログラミングのためのオープンスタンダードであるOpenHMPPが挙げられます。OpenHMPPのディレクティブベースのプログラミングモデルは、ハードウェアアクセラレータへの計算処理の効率的なオフロードと、リモートプロシージャコールを用いたハードウェアメモリとの間のデータ転送の最適化を実現する構文を提供します。
コンシューマー向けGPUの普及に伴い、グラフィックスAPI(コンピュートシェーダーと呼ばれる)、専用API( OpenCLなど)、またはその他の言語拡張機能において、コンピュートカーネルのサポートが実現するようになった。
コンパイラによる逐次プログラムの自動並列化は、特に前述のプロセッサ周波数の制限がある中で、並列コンピューティングの「聖杯」である。コンパイラ研究者による数十年にわたる研究にもかかわらず、自動並列化は限られた成功しか収めていない。[ 69 ]
主流の並列プログラミング言語は、明示的に並列化されているか、(せいぜい)部分的に暗黙的であり、プログラマがコンパイラに並列化の指示を与えるかのいずれかである。完全に暗黙的な並列プログラミング言語はいくつか存在し、SISAL、Parallel Haskell、SequenceL、SystemC(FPGA用)、Mitrion-C、VHDL、Verilogなどが挙げられる。
コンピュータシステムが複雑化するにつれて、障害発生間隔の平均時間は通常短くなります。アプリケーションチェックポイントは、コンピュータシステムがアプリケーションの「スナップショット」(現在のすべてのリソース割り当てと変数状態の記録、コアダンプに類似)を取得する技術です。この情報は、コンピュータが故障した場合にプログラムを復元するために使用できます。アプリケーションチェックポイントとは、プログラムが最初からではなく、最後のチェックポイントからのみ再開すればよいことを意味します。チェックポイントはさまざまな状況で利点をもたらしますが、特に高性能コンピューティングで使用される多数のプロセッサを備えた高度に並列化されたシステムで役立ちます。[ 70 ]
並列コンピュータがより大規模かつ高速になるにつれて、以前は実行に時間がかかりすぎた問題を解決できるようになりました。バイオインフォマティクス(タンパク質の折り畳みや配列解析)や経済学など、さまざまな分野で並列コンピューティングが活用されています。並列コンピューティングアプリケーションでよく見られる問題の種類は次のとおりです。[ 71 ]
Parallel computing can also be applied to the design of fault-tolerant computer systems, particularly via lockstep systems performing the same operation in parallel. This provides redundancy in case one component fails, and also allows automatic error detection and error correction if the results differ. These methods can be used to help prevent single-event upsets caused by transient errors.[73] Although additional measures may be required in embedded or specialized systems, this method can provide a cost-effective approach to achieve n-modular redundancy in commercial off-the-shelf systems.

The origins of true (MIMD) parallelism go back to Luigi Federico Menabrea and his Sketch of the Analytic Engine Invented by Charles Babbage.[75][76][77]
In 1957, Compagnie des Machines Bull announced the first computer architecture specifically designed for parallelism, the Gamma 60.[78] It utilized a fork-join model and a "Program Distributor" to dispatch and collect data to and from independent processing units connected to a central memory.[79][80]
1958 年 4 月、スタンレー・ギル (フェランティ) は並列プログラミングと分岐および待機の必要性について議論した。[ 81 ]また 1958 年、IBM の研究者であるジョン・コックとダニエル・スロットニックは、数値計算における並列処理の使用について初めて議論した。[ 82 ] 1962 年、バローズ社はクロスバー スイッチを介して最大 16 個のメモリ モジュールにアクセスできる 4 プロセッサ コンピュータである D825 を発表した。[ 83 ] 1967 年、アムダールとスロットニックは、米国情報処理学会連合会議で並列処理の実現可能性についての議論を発表した。[ 82 ]この議論の中で、並列処理による高速化の限界を定義するためにアムダールの法則が考案された。
1969年、ハネウェルは最大8つのプロセッサを並列実行できる対称型マルチプロセッサシステムである最初のMulticsシステムを発表しました。 [ 82 ] 1970年代にカーネギーメロン大学で行われたマルチプロセッサプロジェクトであるC.mmpは、数個以上のプロセッサを備えた最初のマルチプロセッサの1つでした。スヌーピングキャッシュを備えた最初のバス接続型マルチプロセッサは、1984年のSynapse N+1でした。[ 76 ]
SIMD並列コンピュータは1970年代に遡ります。初期のSIMDコンピュータの動機は、プロセッサの制御ユニットのゲート遅延を複数の命令に償却することでした。[ 84 ] 1964年、スロットニックはローレンス・リバモア国立研究所向けに大規模並列コンピュータを構築することを提案しました。[ 82 ]彼の設計は米国空軍によって資金提供され、これが初期のSIMD並列コンピューティングの取り組みであるILLIAC IVとなりました。[ 82 ]その設計の鍵は、最大256個のプロセッサによるかなり高い並列性であり、これによりマシンは後にベクトル処理として知られるようになる大規模なデータセットを処理することができました。しかし、ILLIAC IVは、プロジェクトが4分の1しか完了していないにもかかわらず、11年かかり、当初の見積もりのほぼ4倍の費用がかかったため、「最も悪名高いスーパーコンピュータ」と呼ばれました。[ 74 ] 1976年にようやく最初の実際のアプリケーションを実行できるようになったとき、Cray-1などの既存の商用スーパーコンピュータに性能で劣っていた。
1970年代初頭、MITコンピュータ科学・人工知能研究所で、マービン・ミンスキーとシーモア・パパートは、生物の脳を大規模並列コンピュータとみなす「心の社会」理論の開発を始めた。1986年、ミンスキーは『心の社会』を出版し、「心は多くの小さなエージェントから形成され、それぞれはそれ自体では無知である」と主張した。[ 85 ]この理論は、私たちが知能と呼ぶものが、非知能的な部分の相互作用の産物である可能性を説明しようとするものである。ミンスキーは、この理論に関するアイデアの最大の源泉は、ロボットアーム、ビデオカメラ、コンピュータを使って子供のブロックで組み立てる機械を作ろうとした彼の研究から得られたと述べている。[ 86 ]
同様のモデル(生物学的脳を大規模並列コンピュータとみなすモデル、つまり脳は独立または半独立のエージェントの集合体で構成されているモデル)は、以下の研究者によっても提唱されている。
{{cite book}}: CS1 maint: 複数の名前: 著者リスト (リンク)シミュレーションされたすべての回路は、超高速集積回路 (VHSIC) ハードウェア記述言語 (VHDL) で記述されました。ハードウェアモデリングは、Xilinx FPGA Artix 7 xc7a200tfbg484-2 上で実行されました。
こうした研究の究極の目標である逐次プログラムの自動並列化は、いまだ実現していません。特定の種類のアルゴリズムの自動並列化は実証されていますが、その成功は、予測可能なフロー制御(例えば、静的に決定された反復回数を持つネストされたループ構造)と静的に分析可能なメモリアクセスパターン(例えば、浮動小数点データの大きな多次元配列を走査する処理)を持つ科学計算や数値計算アプリケーションにほぼ限定されています。