マルチコアプロセッサでスレッド割り当てをプログラムする方法は?


13

たとえば、2つの異なるプロセッサコアで実行される2つの異なるスレッドを使用するプログラムを作成するなど、マルチコアプロセッサ上のスレッドを試してみたいと思います。

ただし、スレッドがどのレベルで異なるコアに割り当てられるかは明確ではありません。次のシナリオを想像できます(オペレーティングシステムとプログラミング言語の実装に依存)。

  1. スレッドの割り当ては、オペレーティングシステムによって管理されます。スレッドはOSシステムコールを使用して作成され、プロセスがマルチコアプロセッサで実行されると、OSは異なるコアに異なるスレッドを自動的に割り当て/スケジュールしようとします。
  2. スレッドの割り当ては、プログラミング言語の実装によって管理されます。スレッドを異なるコアに割り当てるには特別なシステムコールが必要ですが、プログラミング言語の標準スレッドライブラリは、その言語の標準スレッド実装を使用するときにこれを自動的に処理します。
  3. スレッドの割り当ては明示的にプログラムする必要があります。私のプログラムでは、使用可能なコアの数を検出し、ライブラリ関数などを使用して異なるスレッドを異なるコアに割り当てるために、明示的なコードを記述する必要があります。

質問をより具体的にするために、WindowsまたはLinux上のJavaまたはC ++でマルチスレッドアプリケーションを作成したと想像してください。マルチコアプロセッサで実行すると、アプリケーションが魔法のように複数のコアを認識して使用しますか(すべてがオペレーティングシステムまたは標準のスレッドライブラリによって管理されるため)、または複数のコアを認識するためにコードを変更する必要がありますか?

回答:


11

マルチコアプロセッサで実行すると、アプリケーションが魔法のように複数のコアを認識して使用しますか(すべてがオペレーティングシステムまたは標準のスレッドライブラリによって管理されるため)、または複数のコアを認識するためにコードを変更する必要がありますか?

簡単な答え:はい、通常はオペレーティングシステムまたはスレッドライブラリによって管理されます。

オペレーティングシステムのスレッドサブシステムは、優先順位に基づいてプロセッサにスレッドを割り当てます(オプション1)。つまり、スレッドがその時間割り当てまたはブロックのために実行を終了すると、スケジューラは次に優先順位の高いスレッドを探し、それをCPUに割り当てます。詳細は、オペレーティングシステムによって異なります。

ただし、オプション2(プログラミング言語で管理)と3(明示的に)が存在します。たとえば、最近のバージョンの.NetのTasksライブラリとasync / awaitは、開発者が並列化可能な(つまり、それ自体で同時に実行できる)コードを作成するはるかに簡単な方法を提供します。関数型プログラミング言語は本質的に並列化可能であり、一部のランタイムは、可能であればプログラムのさまざまな部分を並列に実行します。

オプション3(明示的に)に関して、Windowsでは、スレッドアフィニティを設定できます(スレッドを実行できるプロセッサを指定します)。ただし、これは通常、最速の応答時間クリティカルシステムを除くすべてのシステムでは不要です。効果的なスレッドからプロセッサへの割り当ては、ハードウェアに大きく依存しており、同時に実行される他のアプリケーションに非常に敏感です。

実験する場合は、素数のリストの生成やマンデルブロ集合の作成など、CPUを集中的に使用する長時間実行タスクを作成します。次に、お気に入りのライブラリに2つのスレッドを作成し、マルチプロセッサマシンで両方のスレッドを実行します(つまり、ここ数年でリリースされたほぼすべてのもの)。両方のタスクは並行して実行されるため、ほぼ同時に完了する必要があります。


説明をありがとう(+1)。私のテストプログラムはマージソートの実装です。分割フェーズでは、使用可能なコアがある限り、異なるスレッドを作成します。たとえば、2つのコアがある場合、配列の各半分は異なるスレッド/コアによってソートされます。マージ中に、余分なスレッドが結合/終了されます。
ジョルジオ

データがランダムに分散されている場合、この方法で並べ替えを行うのは困難です。はい、分割して別のスレッドで各部分をソートできますが、いずれにしてもすべての部分をマージする必要があります。スレッドがデータ構造を共有している場合、競合またはロックの問題も発生する可能性があります。私はソートがスレッド化の恩恵を受けることはできないと言っているわけではありませんが、直線的なパフォーマンスの改善にはなりません。
アクトン

データが共有されないため、配列の2つの半分を個別にソートできます。データを含む配列またはリスト全体を操作する1つのスレッドで、最初の分割と最後のマージのみを実行する必要があります。これは、データの1回の完全なスキャンを並行して実行できないことを意味します。残りのスキャンはすべて可能です。
ジョルジオ

もちろん、あなたの例も良い候補だと思います。現時点では、マージソートに精通しているだけであり(また、非並列バージョンを実装しています)、最初の試みとして(おそらく)マージソートが私にとってより適切なものになるでしょう。
ジョルジオ

2
この答えに加えて、優れたオペレーティングシステムは、タスクに異なるCPUまたはコア上のタイムスライスを与えるコストと短期的な飢starのバランスをとるのに十分なほどスマートであると付け加えます。重要なアーキテクチャでは、結果は自動マジックアフィニティに似ている傾向があります。OSは、すべてのジョブを可能な限り迅速に実行することを前提に構築されています。スレッドをコアに結び付け、その決定を下す能力を低下させることで、自分自身を撃ち殺すことができます。
Blrfl

-1

かつては巨大なSGI IRIX環境がありました。そのために、小さなマルチスレッドJavaプログラム(CPUサイクルを消費するだけでした)を作成し、12個のスレッドを作成しました。NUMAアーキテクチャの12個のCPUにまたがるジョブ。プログラムを検索し、Dell R910で実行して確認する場合があります。


3
この答えは、実際には既存の答えにあまり追加されません。あなたは、JVMは、SGIのシステム上で...コアにスレッドを割り当てた理由について詳述おそらく場合
ジェイ・エルストン
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.