LinuxのマルチコアCPUの仕組みを徹底解説|物理コア・論理CPU・SMT・Hyper-Threadingの違い

はじめに

現在のCPUでは、1つのCPUパッケージに複数のCPUコアを搭載するマルチコアが一般的です。複数のコアを利用することで、異なるタスクやスレッドを並列に実行し、CPU全体の処理能力を高めることができます。

また、SMT(Simultaneous Multithreading)に対応したCPUでは、1つの物理コアを複数の論理CPUとしてLinuxから利用できます。そのため、LinuxでCPUの構成や性能を理解するには、Socket、物理コア、論理CPUの違いを区別することが重要です。

ただし、CPUコアや論理CPUの数を増やせば、その数に比例して性能が向上するわけではありません。並列化できない処理やCPU Cache、メモリ帯域、ロック競合、SMTによる実行リソースの共有などが性能に影響します。

本記事では、Linuxから見たマルチコアCPUの構成、Socket・Core・Logical CPUの違い、SMTの仕組み、そしてマルチコアCPUでも性能が単純にコア数倍にならない理由について解説します。

マルチコアCPUとは

マルチコアCPUとは、1つのCPUパッケージ内に複数のCPUコアを搭載したCPUです。各CPUコアは、命令を読み込み、解釈し、演算するための実行機構を持っています。複数のコアがそれぞれ別の命令列を処理することで、複数のタスクを並列に実行できます。

CPU・Core・Threadの違い

CPUは文脈によって意味が変わる言葉です。ハードウェア製品としてのCPUを指す場合もあれば、Linuxが認識する論理CPUを指す場合もあります。物理的な製品を明確に示すときは、物理CPUやSocketという表現が使われます。

Coreは、CPUパッケージ内で命令を実行する物理的な処理単位です。4コアCPUであれば、通常は4つの物理コアを持ちます。

Threadは、ここではCPUが同時に扱えるハードウェアスレッドを意味します。SMTに対応したCPUでは、1つの物理コアを2つ以上の論理CPUとしてOSへ見せることがあります。なお、アプリケーションが作成するソフトウェアスレッドと、CPUのハードウェアスレッドは別の概念です。

1コアCPUとマルチコアCPUの違い

1コアCPUにTask A、Task B、Task Cという3つの実行可能なタスクがある場合、1つのコアがタスクを順番に切り替えながら実行します。

一方で、4コアCPUで4つのタスクを実行する場合は、各コアへ1つずつタスクを割り当てられます。各タスクがほかのタスクの完了を待たずに処理できれば、同じ時間帯に並列実行できます。

ただし、タスクが4つあれば必ず4コアを使うとは限りません。タスクの状態、CPU Affinity、スケジューリングポリシー、ほかのタスクの負荷などによって、実際の割り当ては変化します。また、待ち状態のタスクはCPU上で命令を実行しないため、タスク数とCPU使用率は単純には一致しません。

物理CPU・CPUコア・論理CPUの違い

LinuxでCPU構成を確認するときに特に重要なのが、Socket、Core、Logical CPUの違いです。この3つを区別して理解することで、Linuxから見えるCPU構成を正しく把握しやすくなります。

Socket

Socketは、マザーボード上に物理CPUを装着する単位です。一般に、Socket数は搭載されている物理CPUパッケージの数に対応します。1ソケットサーバーには通常1個、2ソケットサーバーには通常2個の物理CPUが搭載されます。

Core

Coreは、物理CPUの内部にある命令実行単位です。1つのSocketに複数のCoreを搭載できます。CoreごとにL1 CacheやL2 Cacheを持ち、L3 Cacheなどの一部リソースを複数のCoreで共有する構成が一般的です。ただし、具体的な構成はCPUによって異なります。

Logical CPU

Logical CPUは、OSがタスクの実行先として認識するCPUの単位です。SMTが無効な場合は、通常1つのCoreが1つのLogical CPUに対応します。1コア当たり2スレッドのSMTが有効な場合は、通常1つのCoreが2つのLogical CPUとして認識されます。

LinuxではLogical CPUごとにCPU番号が割り当てられます。CPU0からCPU7までが存在する場合、Linuxからは8つのLogical CPUがオンラインになっているように見えます。ただし、CPU0からCPU7までが8つの独立した物理コアであるとは限りません。

lscpuで確認する

Linuxではlscpuを実行すると、Socket数、1 Socket当たりのCore数、1 Core当たりのThread数、Logical CPU数を確認できます。

例えば、関連する項目が次のように表示されたとします。

Socket(s):                1
Core(s) per socket:       4
Thread(s) per core:       2
CPU(s):                   8

この環境には1つの物理CPUがあり、その内部に4つの物理コアがあります。各物理コアは2つのハードウェアスレッドに対応するため、Linuxは合計8つのLogical CPUを認識しています。

1 Socket
   ↓
4 Core
   ↓
2 Thread / Core
   ↓
8 Logical CPUs

基本的な関係は、Socket数 × 1 Socket当たりのCore数 × 1 Core当たりのThread数 = Logical CPU数です。上記の例では、1 × 4 × 2 = 8となります。

仮想マシンでは、lscpuに表示される構成が物理ホストの実際の構成と一致するとは限りません。仮想CPUのトポロジーはハイパーバイザーからゲストOSへ提示された情報であり、物理ホスト上のコアやスレッドとの対応関係は環境によって異なります。

SMT(Simultaneous Multithreading)の仕組み

SMTはSimultaneous Multithreadingの略で、1つの物理コアを複数の論理CPUとして利用する仕組みです。Intel CPUで使われるHyper-Threadingは、SMTの代表的な実装として知られています。

SMTでは1つの物理コアを複数の論理CPUとして利用する

例えば、4コア8スレッドのCPUでは、4つの物理コアがあり、各コアが2つの論理CPU(Logical CPU)としてOSから認識されます。

この場合、Linuxからは8つのLogical CPUが存在するように見え、それぞれをタスクの実行先として利用できます。

ただし、8つの物理コアが存在するわけではありません。

なぜ1つの物理コアで複数のスレッドを実行できるのか

CPUコアが命令を実行していても、コア内部の実行リソースが常にすべて使用されているわけではありません。例えば、メモリアクセス待ち、命令間の依存関係、分岐などによって、一部の実行リソースが使用されないことがあります。

SMTでは、1つの物理コアで複数のハードウェアスレッドの状態を保持します。そのため、一方のスレッドだけでは使い切れない実行リソースを、もう一方のスレッドの命令でも利用できます。

単純に「Thread Aが完全に停止したらThread Bへ切り替える」という仕組みではありません。SMTでは、複数のハードウェアスレッドの命令を同じ物理コア上で並行して処理することで、コア内部のリソース利用率を高めます。

SMTを有効にしても物理コアが増えるわけではない

SMTによってLogical CPU数が2倍になっても、物理コア数が2倍になるわけではありません。

同じ物理コアに属するLogical CPUは、コア内部のさまざまなリソースを共有します。どのリソースが共有・分割されるかはCPUのマイクロアーキテクチャによって異なります。

そのため、4 Physical Core / 8 Logical CPU ≠ 8 Physical Core です。

つまり、SMTはCPUコアそのものを増やす仕組みではなく、1つの物理コアが持つ実行リソースを複数のスレッドで効率よく利用するための仕組みです。

SMTによる性能向上の目安

SMTを有効にすると、1つの物理コアで複数のハードウェアスレッドを実行できますが、性能が単純に2倍になるわけではありません。同じ物理コアに属するスレッドは、コア内部の実行リソースの一部を共有するためです。

SMTによる性能向上は、CPUやワークロードによって異なります。例えばIntelは、SMTの実装であるHyper-Threading Technologyによって、最大30%程度の性能向上が得られる場合があると説明しています。

ただし、常に30%向上するわけではありません。一方のスレッドが使用していない実行リソースを、もう一方のスレッドが利用できる場合には高い効果が期待できます。一方、2つのスレッドが同じ実行リソースを強く要求する場合は競合が発生し、性能向上が小さくなることがあります。

そのため、SMTは「物理コアを2倍にする仕組み」ではなく、物理コア内部の実行リソースを複数のスレッドで効率よく利用し、CPU全体のスループットを向上させる仕組みと考えると分かりやすいでしょう。

参考:Intel® Performance Counter Monitor – A Better Way to Measure CPU…

マルチコアでも性能が単純にN倍にならない理由

8コアCPUを使用しても、1コアCPUの8倍の性能になるとは限りません。複数コアを利用して性能を高めるには、処理を並列に実行できることに加え、コア間で共有するリソースや同期処理による制約が小さいことが必要です。

並列化できない処理がある

処理の一部には、前の処理結果が得られなければ次へ進めない部分があります。このような部分は複数のコアへ単純に分割できません。また、アプリケーションが単一スレッドで作られている場合、そのスレッドはある瞬間には1つのLogical CPUでしか実行されません。

全体の一部だけを並列化できる場合、コア数を増やすほど並列部分は短縮できますが、並列化できない部分は残ります。そのため、コア数を増やしたときの性能向上には上限があります。この関係はAmdahlの法則として知られています。

CPU Cacheを共有する場合がある

一般的なマルチコアCPUでは、L1 CacheやL2 Cacheをコアごとに持ち、L3 Cacheを複数コアで共有します。多くのコアが大量のデータへ同時にアクセスすると、共有キャッシュの容量や帯域をめぐる競合が発生する可能性があります。

さらに、複数コアが同じCache Line上のデータを頻繁に更新すると、Cache Coherencyを保つための通信が増えます。異なる変数であっても同じCache Lineに配置されているために競合する現象はFalse Sharingと呼ばれ、マルチスレッド処理の性能を大きく低下させることがあります。

メモリ帯域が競合する

CPUコアを増やしても、メインメモリとの間で転送できるデータ量が同じ割合で増えるとは限りません。複数のコアが大量のデータを同時に読み書きすると、メモリ帯域がボトルネックになる可能性があります。

演算量よりメモリアクセス量が多い処理では、コアを追加してもCPUがデータを待つ時間が増え、性能が伸びにくくなります。このような場合は、CPU使用率やコア数だけでなく、Cache Missやメモリ帯域も確認する必要があります。

ロック競合が発生する

複数のスレッドが共有データを安全に更新するため、Mutexなどのロックを利用することがあります。あるスレッドがロックを保持している間、ほかのスレッドが待つ必要があれば、その部分は並列に実行できません。

スレッド数を増やすほど同じロックを取得しようとする頻度が高くなる場合は、コアが増えてもロック待ちが増加し、性能が向上しないことがあります。場合によっては、スレッド数を増やす前より性能が低下します。

CPU Migrationが発生する

CPU間のLoad Balancingには、空いているCPUを利用できる利点があります。一方、タスクが異なるコアへ頻繁に移動すると、移動先のキャッシュへデータを読み込み直す必要が生じ、Cache Missが増える可能性があります。

CPU Affinityを設定すればMigrationを抑えられますが、実行先を限定することで負荷の偏りが大きくなる可能性もあります。Migration回数だけを減らすのではなく、アプリケーションの待ち時間やスループットを含めて効果を確認する必要があります。

SMTでは実行リソースを共有する

SMTによるLogical CPUは、完全に独立した物理コアではありません。同じ物理コアに属するハードウェアスレッドは、コア内部の実行リソースを共有します。そのため、8 Logical CPUが見える4コア8スレッドCPUの性能は、8つの物理コアを持つCPUと同じではありません。

SMTが有効な場合の性能はワークロードによって変わります。物理コア数、Logical CPU数、タスクの特性を区別し、実際の処理時間やスループットを測定することが重要です。

まとめ

マルチコアCPUでは、1つのCPUパッケージに複数の物理コアを搭載し、それぞれのコアで異なるタスクを並列に実行できます。Linuxでは、タスクの実行先としてLogical CPUが使用されるため、Socket・Core・Logical CPUの違いを理解することが重要です。

また、SMTを利用すると1つの物理コアを複数のLogical CPUとして利用できますが、物理コアそのものが増えるわけではありません。同じ物理コアに属するハードウェアスレッドは実行リソースを共有するため、性能向上の程度はワークロードによって異なります。

さらに、CPUコアを増やしても、並列化できない処理、CPU Cache、メモリ帯域、ロック競合、CPU Migrationなどの影響により、性能が単純にコア数倍になるとは限りません。

LinuxのCPU性能を確認するときは、Logical CPU数だけを見るのではなく、物理コア数やSMTの構成、アプリケーションの並列性、共有リソースの競合などを含めて考えることが重要です。

コメント