マルチスレッドは、各スレッドに割り当てられる複数のプロセッサがあり、各スレッドを同時に実行できるマルチプロセッサシステムでのみ実装できるという概念に常に従ってきました。この場合、各スレッドにはすべて専用の個別のリソースがあるため、スケジューリングはありません。しかし、最近、シングル プロセッサ システムでもマルチスレッドを実行できるという記事をどこかで読みました。それが正しいか?はいの場合、シングル プロセッサ システムとマルチ プロセッサ システムの違いは何ですか?
6 に答える
もちろん、シングル プロセッサ システムでも実行できます。実際、その方がはるかに簡単です。これは、複数のプロセスを実行するのと同じように機能します。カーネルは、タイマー割り込みまたは他の同様のメカニズムを介してプロセスを一時停止し、そのマシンの状態を保存して、以前に保存された別の状態に置き換えます。唯一の違いは、その 2 つです。同じプロセスのスレッドは同じ仮想メモリ空間を共有するため、タスク切り替えがより効率的になります。
マルチプロセッサ システムでのマルチスレッド化は、実際にははるかに困難です。複数の CPU/コアからメモリへの同時アクセスの問題と、そこから発生するすべての厄介なメモリ同期の問題があるためです。
最近、シングル プロセッサ システムでもマルチスレッドを実行できるという記事をどこかで読みました。それが正しいか?はいの場合、シングル プロセッサ システムとマルチ プロセッサ システムの違いは何ですか?
はい、シングル プロセッサ システムでマルチスレッドを実行できます。
マルチプロセッサ システムでは、複数のスレッドが異なるコアで同時に実行されます。例- 2 つのスレッドと 2 つのコアがある場合、各スレッドは個々のコアで実行されます。
単一プロセッサ システムでは、スレッドの優先度と OS ポリシーに応じて、複数のスレッドが次々に実行されるか、1 つのスレッドが終了するか OS によってプリエンプトされるまで待機します。しかし、実行中のスレッドは、それらが同時に実行されているように見えます。 、ユーザー空間アプリケーションの必要なアプリケーション応答時間に関連しています。
時間比較(例):
2 つのスレッドの実行にそれぞれ 10us かかる場合、2 プロセッサ システムでは、正味の所要時間は 10us です。
2 つのスレッドの実行にそれぞれ 10us かかる場合、1 プロセッサ システムでは、正味の所要時間は 20us です。
クアッド コア システムでは、アクティブなスレッドを 4 つ以上持つことができます。プロセスがプロセッサよりも多くのスレッドを作成しようとしないことを保証できない限り、スケジューリングがあります。
はい、シングルコア コンピューターで複数のスレッドを使用できます。
シングル プロセッサ システムとマルチプロセッサ システムの違いは、マルチプロセッサ システムでは実際に一度に複数の処理を実行できることです。一度に N 個の処理を実行できます。ここで、N はプロセッサ コアの数です。シングル プロセッサ コアは、一度に 1 つのことしか実行できません。WhozCraig がコメントで述べたように、それは実際の同時実行と認識された同時実行の違いです。
はい、できます。何年も前 (Win 95?) は、協調マルチタスキングからマルチスレッドに移行しました。コンピュータ上のすべてのプログラムには、少なくとも 1 つのスレッドがあります。おそらくもっと。そして、CPU は 1 秒あたり数百万回も狂ったように、これらすべてのスレッドを切り替え続けます。何もすることがない場合は、しばらくアイドル状態になることさえあります。
マルチコア システムとは、これらのスレッドの 2 つ以上が並列で実行される可能性があることを意味するだけです。
ただし、そうすることで得られるものははるかに少なくなります。シングル コア マシンでマルチスレッドを使用してできることは、マルチタスクをシミュレートすることだけです。
マルチタスキングは、実行時間の長い操作が原因で GUI スレッドがロックされるのを防ぐのに十分です。ただし、コンパイラまたは言語 (C# async...await など) の助けがない限り、実装は一般的に複雑です。その結果、多くの GUI プログラマーはマルチスレッドと呼び出しを使用して、マルチタスクを偽装していました。そのコードが単一または複数のコアで実行される場合、これは重要ではありません。
最も重要なことは、マルチタスキングは CPU バウンドの操作には適していないということです。しかし、すべての非同期の問題の 95% は CPU バウンドではありません。それらはネットワークまたはディスクにバインドされています。シングルコア コンピューターでは、マルチスレッドも CPU バウンドには役立ちません。両方とも 100% の CPU 時間を必要とする 2 つのスレッド (同じプログラムまたは別のプログラム) があり、それらを実行するのに 1 つのコアしか必要としない場合、CPU は両方を 49% で実行するように切り替え、残りの 2% をそれらすべてに使用する必要があります。少ししかしない他のスレッド。
最後に、実際にマルチスレッド化できる問題はごくわずかです。フィボナッチ数列を遅くしたり、メモリを必要としたり、複雑にしたりすることなく、マルチスレッド化 (ペアごとに 1 つのスレッド) を試みてください。
tl;dr; CPU バウンドの問題には、マルチスレッドとマルチコア コンピューターが必要です。非同期の問題のほとんどは、CPU バウンドではありません。マルチタスクで十分です。また、シングル コア マシンでも、スレッドを使用して完全にマルチタスクを実行できます。
これは非常に単純化された例です。実際には、私が構築しているプログラムのプロトタイプです。これは、シングル スレッドでの協調マルチタスクの実装です。
main
quit
フラグを false に設定し、関数ポインタ (タスク) の配列を設定してから、 を呼び出しますloop
。
loop
を使用setjmp
して、非ローカル ジャンプ (関数から実行中の前の場所に戻るジャンプ) の戻り点を設定し、最初のタスク (関数) の呼び出しに進みます。
各タスクは で終了しyield()
ます。つまり、どのタスクも実際には機能しませんreturn
。return;
それらにはステートメントが含まれていないだけでなく(関数、つまりプロシージャであるため問題ありません)、呼び出しにジャンプして戻るため、そこにあったとしてもvoid
に到達しません。今回はステートメントに1が返されます。で。ステートメントによって制御されるステートメントは、ループに再び入る前に別のタスクを選択します。return
yield
setjmp
if
loop
if
while
したがって、各タスク関数は複数回実行され、実行する新しいタスクを選択するディスパッチャー(if(setjmp...
ステートメント) に渡されます。
#include <stdio.h>
#include <setjmp.h>
jmp_buf dispatch;
int ntasks;
void (*task[10])(void);
int quit;
void yield(void) {
longjmp(dispatch, 1);
}
void loop() {
static int i = 0;
if(setjmp(dispatch))
i = (i+1) % ntasks;
while(!quit)
task[i]();
}
int acc = 0;
void a(void) {
if (acc > 10) quit = 1;
printf("A\n");
yield();
}
void b(void) {
acc *= 2;
printf("B\n");
yield();
}
void c(void) {
acc += 1;
printf("C\n");
yield();
}
int main() {
quit = 0;
ntasks = 3;
task[0] = a;
task[1] = b;
task[2] = c;
loop();
return 0;
}
この例とシングル プロセッサのマルチタスク コンピューター システムの違いは、実際のプロセッサが実行途中でタスクを中断し、後で同じ場所からタスクを再開することをサポートしていることです。これは、タスクを単一の関数として持つ C シミュレーションでは実際には不可能です。ただし、タスクは、それぞれがディスパッチャー (関数ポインターの配列、またはリンクされたリスト) に渡される一連の C 関数で構成されている可能性があります。