
コンピュータアーキテクチャにおいて、マルチスレッドとは、中央処理装置(CPU)(またはマルチコアプロセッサの単一コア)が複数の実行スレッドを提供できる能力のことである。
1990年代後半以降、命令レベル並列処理のさらなる活用に向けた取り組みが停滞するにつれ、マルチスレッド処理のパラダイムがより普及してきた。これにより、トランザクション処理というより専門的な分野から、スループットコンピューティングの概念が再び注目を集めるようになった。単一のスレッドやプログラムの速度をさらに向上させることは非常に困難だが、ほとんどのコンピュータシステムは実際には複数のスレッドやプログラム間でマルチタスク処理を行っている。したがって、すべてのタスクのスループットを向上させる技術は、全体的なパフォーマンス向上につながる。
スループットコンピューティングにおける主要な2つの技術は、マルチスレッドとマルチプロセッシングである。
あるスレッドでキャッシュミスが頻繁に発生した場合、他のスレッドは未使用の計算リソースを引き続き活用できるため、全体的な実行速度が向上する可能性があります。これは、単一のスレッドのみが実行された場合、これらのリソースがアイドル状態になるのを防ぐためです。また、スレッドがCPUのすべての計算リソースを使用できない場合(命令が互いの結果に依存している場合)、別のスレッドを実行することで、それらのリソースがアイドル状態になるのを防ぐことができます。
複数のスレッドがキャッシュやTLB(トランスレーションルックアサイドバッファ)などのハードウェアリソースを共有している場合、互いに干渉する可能性があります。その結果、スレッド切り替えハードウェアに対応するために必要な周波数の低下やパイプラインステージの増加により、単一スレッドの実行時間は改善されず、場合によっては悪化する可能性があります。
全体的な効率は様々です。インテルはハイパースレッディング技術で最大30%の改善を主張していますが[ 1 ]、最適化されていない依存浮動小数点演算のループを実行するだけの合成プログラムは、並列実行時に実際に100%の速度向上を実現します。一方、MMXまたはAltiVec拡張機能を使用し、データプリフェッチを実行する(優れたビデオエンコーダーのように)手動で調整されたアセンブリ言語プログラムは、キャッシュミスやアイドル状態のコンピューティングリソースの影響を受けません。そのため、このようなプログラムはハードウェアマルチスレッドの恩恵を受けず、共有リソースの競合によりパフォーマンスが低下する可能性があります。
ソフトウェアの観点から見ると、マルチスレッド処理のためのハードウェアサポートはソフトウェアからより分かりやすく、マルチプロセッシングよりもアプリケーションプログラムとオペレーティングシステムの両方に多くの変更を必要とします。マルチスレッド処理をサポートするために使用されるハードウェア技術は、コンピュータのマルチタスク処理に使用されるソフトウェア技術と類似していることがよくあります。スレッドスケジューリングも、マルチスレッド処理における大きな課題です。
2 つのプロセスからのデータをマージすると、プロセス間通信や同期などのオーバーヘッドのために、同じデータを単一のスレッドで処理する場合と比較して、コストが大幅に高くなることがよくあります。場合によっては、2 桁以上高くなることもあります。[ 2 ] [ 3 ] [ 4 ]
最も単純なマルチスレッド処理は、通常であれば長時間の遅延を引き起こすようなイベントによってブロックされるまで、1つのスレッドが実行される場合に発生します。このような遅延とは、オフチップメモリへのアクセスを必要とするキャッシュミスなどが考えられ、データが返ってくるまでに数百CPUサイクルかかる場合があります。スレッドプロセッサは、遅延が解消されるのを待つ代わりに、実行準備が整った別のスレッドに実行を切り替えます。前のスレッドのデータが到着した時点で初めて、前のスレッドは実行準備完了スレッドのリストに戻されます。
例えば:
概念的には、リアルタイムオペレーティングシステムで使用される協調型マルチタスクに似ています。協調型マルチタスクでは、タスクは何らかのイベントを待つ必要がある場合に、自発的に実行時間を放棄します。このタイプのマルチスレッドは、ブロック型、協調型、または粗粒度型マルチスレッドとして知られています。
マルチスレッドハードウェアサポートの目的は、ブロックされたスレッドと実行準備が整った別のスレッドとの間で高速な切り替えを可能にすることです。あるスレッドから別のスレッドへの切り替えは、ハードウェアが使用するレジスタセットを切り替えることを意味します。この目的を達成するために、プログラムから見えるレジスタ、および一部のプロセッサ制御レジスタ(プログラムカウンタなど)のハードウェアが複製されます。たとえば、2つのスレッド間を高速に切り替えるために、プロセッサは2組のレジスタセットを備えて構築されます。
マルチスレッド処理のためのハードウェアサポートが強化されることで、スレッド切り替えを1回のCPUサイクルで実行できるようになり、パフォーマンスが向上します。また、ハードウェアのサポート強化により、各スレッドは他のスレッドとハードウェアリソースを共有することなく、単独で実行されているかのように動作できるため、マルチスレッド処理をサポートするためにアプリケーションやオペレーティングシステムに必要なソフトウェア変更を最小限に抑えることができます。
多くのマイクロコントローラや組み込みプロセッサは、割り込み処理における迅速なコンテキスト切り替えを可能にするために、複数のレジスタバンクを備えています。このような方式は、ユーザープログラムスレッドと割り込みスレッド間のブロックマルチスレッド処理の一種と考えることができます。
きめ細かいマルチスレッド処理の目的は、実行パイプラインからデータ依存性による停止をすべて排除することです。各スレッドは他のスレッドから比較的独立しているため、パイプライン内の特定のステージの命令が、パイプライン内の以前の命令の出力を必要とする可能性が低くなります。概念的には、オペレーティングシステムで使用されるプリエンプティブマルチタスク処理に似ています。例えるなら、各アクティブスレッドに割り当てられるタイムスライスは1CPUサイクルです。
例えば:
この種のマルチスレッド処理は、当初はバレル処理と呼ばれていました。バレルの樽板はパイプラインの各ステージと、そのステージを実行するスレッドを表しています。インターリーブ型、プリエンプティブ型、細粒度型、またはタイムスライス型マルチスレッド処理は、より現代的な用語です。
ブロック型マルチスレッド処理で説明したハードウェアコストに加えて、インターリーブ型マルチスレッド処理では、各パイプラインステージが処理中の命令のスレッドIDを追跡するという追加コストが発生します。また、パイプライン内で同時に実行されるスレッド数が増えるため、異なるスレッド間でのスラッシングを回避するために、キャッシュやTLBなどの共有リソースをより大きくする必要があります。
最も高度なマルチスレッド方式は、スーパースカラプロセッサに適用されます。通常のスーパースカラプロセッサは、CPUサイクルごとに単一のスレッドから複数の命令を発行しますが、同時マルチスレッド(SMT)では、スーパースカラプロセッサはCPUサイクルごとに複数のスレッドから命令を発行できます。単一のスレッドには命令レベルの並列性が限られていることを認識し、このタイプのマルチスレッドは、複数のスレッド間で利用可能な並列性を活用して、未使用の発行スロットに関連する無駄を削減しようとします。
例えば:
SMT以外のマルチスレッド方式を区別するために、「時間的マルチスレッド」という用語は、一度に1つのスレッドからの命令しか発行できない場合を指すために使用されます。
インターリーブ型マルチスレッド処理で説明したハードウェアコストに加えて、SMTでは、各パイプラインステージが処理中の各命令のスレッドIDを追跡するという追加コストが発生します。ここでも、キャッシュやTLBなどの共有リソースは、処理される多数のアクティブスレッドに合わせてサイズを調整する必要があります。
実装例としては、 DEC(後にCompaq)EV8(未完成)、Intel Hyper-Threading Technology、IBM POWER5 / POWER6 / POWER7 / POWER8 / POWER9、IBM z13 / z14 / z15、Sun Microsystems UltraSPARC T2、Cray XMT、AMD BulldozerおよびZenマイクロアーキテクチャなどが挙げられる。
主要な研究分野の一つは、実行準備が整ったスレッドのリストから次に実行するスレッドを迅速に選択し、実行準備が整ったスレッドと停止したスレッドのリストを管理するスレッドスケジューラです。重要な副次的テーマとして、スケジューラが使用できるさまざまなスレッド優先度スキームがあります。スレッドスケジューラは、完全にソフトウェアで実装することも、完全にハードウェアで実装することも、ハードウェアとソフトウェアの組み合わせで実装することも可能です。
もう一つの研究分野は、どのような種類のイベントがスレッド切り替えを引き起こすべきかという点です。例えば、キャッシュミス、スレッド間通信、DMA完了などが挙げられます。
マルチスレッド方式が、特権制御レジスタやTLBを含むソフトウェアから見えるすべての状態を複製する場合、各スレッドごとに仮想マシンを作成することが可能になる。これにより、各スレッドは同じプロセッサ上で独自のオペレーティングシステムを実行できる。一方、ユーザーモードの状態のみを保存する場合は、必要なハードウェアが少なくなり、同じダイ面積またはコストでより多くのスレッドを同時にアクティブにできる。