PMPの流儀

PMPの流儀

エンジニアのページ

MENU

プロセスとマルチスレッドの違いについて

WindowsなどのOSが持つプロセスとスレッドの関係について解説します。またCPU用語で最近8core 16thread などのスレッドという単語も出てきていますが、その関係についても触れます。

1. プロセスとは

Windows, Linux, Mac など現在のOSは、マルチタスクが当たり前になりました。
タスクはプロセスとも呼び、プログラムの実行単位の事です。

各プログラムは、物理メモリのある番地に割り付けられ、OSが短い時間で実行するプロセスを切り替えながら実行し、同時に動いているように見せています。タイムシェアリングシステム(Time Sharing System 略して TSS)と呼ばれ、元々はメインフレームと呼ばれる巨大なコンピュータを複数のユーザーが同時利用するために生み出されました。

CPUがマルチコアの場合は、コア数で分担して実行していきます。
コア数の数分だけは本当に同時実行しています。

例えば…料理人が4名いて複数のオーダーが入っている場合
4人で分担して1分毎にオーダーを切り替えながら調理しているような感じです。
料理の場合は、時間で切り替えることは現実的ではなく、切りがいいところまで進めて、煮込みのような合間につぎのオーダーの一部を実施する感じでしょうか。

マルチタスクOS上では、プロセスという単位でプログラムを実行します。
プロセス毎に持つ固有情報は以下です

1.1 メモリ空間

プロセス毎に仮想のメモリ空間が割り付けられます。CPUが持つ仮想メモリという機能を使用することで、プログラム自身が認識しているアドレスと、物理的なアドレスは分離されており、自分のプロセス以外のメモリにアクセスする事はできません。
プログラムに不具合があるとメモリアクセス違反で落ちることがありますが、あくまでもそのプロセスだけが消されるだけでOSや他のプロセスには影響はありません。

この機能が無いと、ポインタの初期化し忘れて書き込みをすることで、他のプログラムやシステムを破壊することになります。リッチなOSを搭載していない小規模な組み込み系開発では、今でもこのリスクはあります。

1.2 CPUレジスタ情報

レジスタは固定の変数のようなイメージです。

汎用レジスタ
プログラムカウンタ
スタックポインタ
ステータスレジスタ

など用途別にいくつかの種類があります。このうちのプログラムカウンタには、実行するアドレスが入ります。
コンピュータを動かすというのは、

(1). プログラムカウンタが指しているアドレスから、命令を読み取る。
(2). その命令を実行し、プログラムカウンタの値を進める
この繰り返しです。

OSは、プロセス毎にCPUレジスタ情報をメモリ上に保持し、タスク切り替え時に、そのタスクのレジスタを復元してプロセスを実行します。

1.3 プロセスの欠点

プロセス間はメモリ空間が分離され安全な環境が与えられました。
1つのプロセス内で完結する分には問題ないのですが、複数のプロセスが強調して動かす場合は大変です。
情報の受け渡し方法が考えられました。共有メモリ、イベント、ミューテックスセマフォ、パイプ等です。これらはOSにより機能提供されています。
プロセスは安心・安全環境を構築したが故に、協調動作をさせるのがやりくくなりました。

それを解決するのがマルチスレッドです。

2. スレッド

スレッドは上記プロセスの、CPUレジスタの部分を指します。
基本は1プロセス内に、1つのCPUレジスタセットを持つので、1プロセス = 1スレッドです。

1プロセス内に、複数のCPUレジスタ情報を持つことが可能です。そうすると、メモリ空間は1つの中で、複数の処理を同時実行する事ができます。
実は、プロセスの所で説明したマルチタスクの切り替えは、プロセス単位ではなく、スレッド単位で管理しています。

マルチタスクを実現するためにマルチプロセスが存在しているのに、スレッドという仕組みが後になって導入されました。
違いはメモリ空間です。

プロセス間はメモリ空間が分離されていますが、マルチスレッドの場合は、メモリ空間が同一で通常の変数を共有できるのがメリットです。
また、スレッドの生成はプロセスの生成よりも軽いというメリットもあります。
しかし、その分スレッド間の動きを厳密にコントロールしておかないと、排他問題、デッドロックなど様々な問題が生じるで、高度なプログラミング力が必要です。

3. CPUのスレッドについて

最近のCPUのスペックで8コア 16スレッドという具合に、スレッドというキーワードが出ています。

基本は、CPUのコア毎に1セット分のCPUレジスタセットを持ちます。
8コアだと、8セット分のCPUレジスタセットを持ち、8個のプロセスを同時実行できるわけです。

CPUのスレッドというのは一般的にはSMTと呼ばれる技術です。Intelではハイパースレッディングと呼んでいます。IntelAMDのCPUでは、1つのコアに対し2個分のCPUレジスタセットを持っています。

CPUはメモリから命令を読み込みその命令を実行します。このメモリから読み込み時間はCPUから見ると途方もなく長い期間待つことになります。メモリだけに限りませんが、そういった隙間の遊んでいる期間を使って、別のレジスタセットを並行して動かすという方式です。

CPU内には以前読み取った命令やデータを記憶しておくキャッシュメモリが搭載されており、ヒットすればメモリからの読み込みを省略して実行する事ができます。1つがメモリのリード待ち中に、もう1つはキャッシュにヒットして実行できるわけです。隙間時間を埋めるだけですので、効果は約1.3倍程度とのことです。
キャッシュのエリアも2本のスレッドで共有するとになるので、逆に遅くなる場合もあり、それを嫌ってSMTを切っている人もいます。

8コア 16スレッドというのは、コアが8個あり、各コアに2個のCPUレジスタを持つことから、計16個のCPUレジスタを持つという意味です。それをスレッドと呼んでいます。
OSが持つスレッドもCPUのレジスタを持ちましたね。これで関係が見えてきます。

OSは、コアとスレッドの両方を識別して、8コア、16スレッドを認識します。
このCPUの16スレッド = 16個のCPUレジスタに対し、OSが持つスレッドを割り当ててプログラムを実行させます。OSのスレッドは1回あたり100msec 程度の実行時間で、別のスレッドに切り替えていくことになります。

16スレッドといっても、同一コア内の2スレッドを同時に使っても1.3倍程度にしかならないため、OSは極力異なるコアに優先してスレッドを割り当てていきます。異なるコアであれば、単純に2倍の能力になりますからね。

全体を俯瞰するとこんな感じになります。

f:id:ruruucky:20211118233208p:plain