65

たとえば、WAV ファイルのリストを MP3 にエンコードするなど、計算コストの高い処理を行う C# のプログラムがあるとします。通常はファイルを 1 つずつエンコードしますが、たとえば、プログラムに CPU コアの数を割り出し、各コアでエンコード スレッドを起動させたいとしましょう。そのため、クアッド コア CPU でプログラムを実行すると、プログラムはそれがクアッド コア CPU であることを認識し、動作するコアが 4 つあることを認識し、エンコーディング用に 4 つのスレッドを生成し、それぞれが個別に実行されます。 CPU。どうすればいいですか?

また、コアが複数の物理 CPU に分散されている場合、これは何か違うでしょうか? たとえば、2 つのクアッド コア CPU を搭載したマシンを使用している場合、特別な考慮事項はありますか、または 2 つのダイの 8 つのコアは Windows で等しいと見なされますか?

4

10 に答える 10

62

気にしないでください。

代わりにThread Poolを使用してください。スレッド プールは、新しいスレッドを照会できるフレームワークのメカニズム (実際にはクラス) です。

新しいスレッドを要求すると、新しいスレッドが提供されるか、スレッドが解放されるまで作業がキューに入れられます。このように、フレームワークは、現在の CPU の数に応じて、より多くのスレッドを作成する必要があるかどうかを決定します。

編集: さらに、既に述べたように、OS は異なる CPU 間でスレッドを分散する役割を担っています。

于 2008-08-28T14:13:41.920 に答える
18

必ずしもスレッド プールを使用するほど単純ではありません。

デフォルトでは、スレッド プールは各 CPU に複数のスレッドを割り当てます。実行中の作業に関与するすべてのスレッドにはコストがかかるため (タスク切り替えのオーバーヘッド、CPU の非常に限られた L1、L2、場合によっては L3 キャッシュの使用など)、使用する最適なスレッド数は <= です。利用可能な CPU の数 - 各スレッドが他のマシンからサービスを要求している場合を除きます - 非常にスケーラブルな Web サービスなど。場合によっては、特に CPU アクティビティよりも多くのハードディスクの読み取りと書き込みを伴う場合、実際には複数のスレッドよりも 1 つのスレッドの方が適している場合があります。

ほとんどのアプリケーション、特に WAV および MP3 エンコーディングでは、ワーカー スレッドの数を使用可能な CPU の数に制限する必要があります。CPU の数を確認するための C# コードを次に示します。

int processors = 1;
string processorsStr = System.Environment.GetEnvironmentVariable("NUMBER_OF_PROCESSORS");
if (processorsStr != null)
    processors = int.Parse(processorsStr);

残念ながら、CPU の数を制限するほど単純ではありません。また、ハードディスク コントローラとディスクのパフォーマンスも考慮する必要があります。

最適なスレッド数を実際に見つける唯一の方法は、試行錯誤することです。これは、ハードディスクや Web サービスなどを使用している場合に特に当てはまります。ハードディスクの場合、クアッド プロセッサ CPU で 4 つのプロセッサすべてを使用しない方がよい場合があります。一方、一部の Web サービスでは、CPU ごとに 10 個または 100 個の要求を行う方がよい場合があります。

于 2009-02-20T01:54:23.680 に答える
9

マネージ スレッドの場合、これを行うことの複雑さは、ネイティブ スレッドの場合よりも大きくなります。これは、CLR スレッドがネイティブ OS スレッドに直接関連付けられていないためです。つまり、CLR はマネージドスレッドをネイティブ スレッドからネイティブ スレッドに必要に応じて切り替えることができます。関数Thread.BeginThreadAffinityは、マネージド スレッドをネイティブ OS スレッドとロックステップに配置するために提供されています。その時点で、ネイティブ API を使用して、基礎となるネイティブ スレッド プロセッサ アフィニティを与えることを試すことができます。誰もがここで示唆しているように、これはあまり良い考えではありません。実際、スレッドが単一のプロセッサまたはコアに制限されている場合、スレッドが受け取る処理時間が短くなる可能性があることを示唆するドキュメントがあります。

System.Diagnostics.Processクラスを調べることもできます。そこには、プロセスのスレッドをProcessThreadオブジェクトのコレクションとして列挙する関数があります。このクラスには、ProcessorAffinity を設定するメソッド、または優先プロセッサを設定するメソッドがあります。それが何であるかはわかりません。

免責事項: CPU の使用率が低いと思われる同様の問題が発生し、この問題について多くのことを調査しました。ただし、ここに投稿されたコメントからも明らかなように、私が読んだすべてに基づいて、それはあまり良い考えではないように見えました. ただし、それでも興味深いものであり、実験するための学習体験です。

于 2008-08-28T14:49:52.443 に答える
6

プログラム内にルーチンを記述することで、これを確実に行うことができます。

ただし、オペレーティングシステムはこれらのものを管理するための最良の候補であるため、それを行うべきではありません. つまり、ユーザーモードプログラムはそれをやろうとすべきではありません。

ただし、場合によっては、負荷分散を達成し、真のマルチスレッド マルチコアの問題 (データ レーシング/キャッシュ コヒーレンス...) を見つけるために (実際に上級ユーザー向けに) 行うことができます。これは、異なるスレッドが異なるプロセッサで実際に実行されるためです。 .

そうは言っても、それでも達成したい場合は、次の方法でそれを行うことができます。(Windows OS) の疑似コードを提供していますが、Linux でも簡単に実行できます。

#define MAX_CORE 256
processor_mask[MAX_CORE] = {0};
core_number = 0;

Call GetLogicalProcessorInformation();
// From Here we calculate the core_number and also we populate the process_mask[] array
// which would be used later on to set to run different threads on different CORES.


for(j = 0; j < THREAD_POOL_SIZE; j++)
Call SetThreadAffinityMask(hThread[j],processor_mask[j]);
//hThread is the array of handles of thread.
//Now if your number of threads are higher than the actual number of cores,
// you can use reset the counters(j) once you reach to the "core_number".

上記のルーチンが呼び出された後、スレッドは常に次のように実行されます。

Thread1-> Core1
Thread2-> Core2
Thread3-> Core3
Thread4-> Core4
Thread5-> Core5
Thread6-> Core6
Thread7-> Core7
Thread8-> Core8

Thread9-> Core1
Thread10-> Core2
...............

これらの概念の詳細については、マニュアル/MSDN を参照してください。

于 2013-08-28T23:28:49.530 に答える
3

これを自分で行うことについて心配する必要はありません。デュアル クワッド マシンでマルチスレッド化された .NET アプリを実行しています。ThreadPool を使用するか手動でスレッドを開始するかに関係なく、すべてのコアで作業が均等に分散されます。

于 2008-08-28T14:16:11.337 に答える
2

各スレッドの行き先は通常、OS 自体によって処理されます。したがって、4 コア システムで 4 つのスレッドを生成すると、OS がそれぞれを実行するコアを決定します。通常、各コアで 1 つのスレッドになります。

于 2008-08-28T14:13:01.877 に答える
2

スレッドを異なるコアに分割するのはオペレーティング システムの仕事であり、スレッドが多くの CPU 時間を使用しているときに自動的に分割されます。心配しないでください。ユーザーが持っているコアの数を調べるには、Environment.ProcessorCountC# で試してください。

于 2008-08-28T14:13:57.367 に答える
1

(言われているように)この種のものを自分で割り当てようとしてはいけない理由の1つは、特にNUMAなどで将来的に、適切に割り当てるための十分な情報がないためです。

実行するスレッドがあり、コアがアイドル状態の場合、カーネルスレッドを実行します。心配する必要はありません。

于 2008-08-28T14:29:39.730 に答える