2009-03-19 21 views
50

複数のプロセスやスレッドを使用するプログラムの作成方法を理解できます。新しいプロセスをfork()してIPCを使用するか、複数のスレッドを作成してこれらの種類の通信メカニズムを使用します。プロセスが実行されているコアを制御する方法は?

コンテキスト切り替えも分かります。つまり、CPUは1回だけで、オペレーティングシステムは各プロセスの時間をスケジューリングします(スケジューリングアルゴリズムがたくさんあります)。これにより複数のプロセスを同時に実行することができます。

マルチコアプロセッサ(またはマルチプロセッサコンピュータ)が完成したので、2つの別々のコアで同時に2つのプロセスを実行できます。

私の質問は最後のシナリオです:どのコアがプロセスを実行するかをカーネルがどのように制御するのですか?どのシステムコール(LinuxやWindowsでさえ)が特定のコアでプロセスをスケジュールするか?

私が求めている理由:私は、コンピューティングの最近の話題を探究しようとしている学校のプロジェクトに取り組んでいます。私はマルチコアアーキテクチャを選択しました。そのような環境(デッドロックや競合状態を監視する方法)でプログラムする方法には多くの資料があるようですが、個々のコア自体を制御することはあまりありません。私はいくつかのデモンストレーションプログラムを書いて、「第2のコアで無限ループを実行しています。具体的なコアがあるのCPU使用率のスパイクを見ています。 "。

コード例はありますか?またはチュートリアル?

編集:明確にするために、多くの人がこれがOSの目的であり、OSがこれを世話するべきだと述べています。同意します!しかし、私が求めているのは、オペレーティングシステムがこれを行うために実際にやっていることです。スケジューリングアルゴリズムではなく、「コアを選択したら、そのコアで命令をフェッチするためにはどの命令を実行する必要がありますか」

+1

ここに可能な答え:http://stackoverflow.com/questions/980999 CPUコアからチップセットAPICに送信されているスタートアッププロセッサ間割り込みを記述し、別のCPUを初期化してそのコードを実行するために使用できる答えの1つは、マルチコアアセンブリ言語のようなものです特定のアドレスにあるCPU –

+0

私たち自身のOSでSMPを起動する最小の例:http://stackoverflow.com/a/33651438/895245その+同期メモリを使って遊ぶことが必要です。 –

答えて

31

他にも言及したように、プロセッサの親和性はオペレーティングシステム固有のです。あなたがオペレーティングシステムの範囲外でこれをしたいのであれば、あなたは多くの楽しみの中にいます。それは痛みを意味します。

つまり、他の人はWin32用にSetProcessAffinityMaskを挙げています。誰もLinuxカーネルのプロセッサアフィニティを設定する方法については言及していません。 sched_set_affinity機能を使用する必要があります。方法についてはa nice tutorialです

+1

私はこのトピックについて記事を書きましたが、それはスロバキア語で書かれていますので、それは人に尋ねるのを助けません:)とにかく、あなたの答えは正しい方向に進むので、私はあなたに投票を与えています上に戻る:-) –

+0

このチュートリアルでは、親和性マスクを「created_thread」に設定しています。AFAICTは、スレッドが現在実行されているCPUを厳密に指していません。これはビットマスクにインデックスを付けるためにインクリメントされて使用される単なる整数ですが、この例のように、現在使用されているプロセッサが実際に決定されていないようです。 cpu#子プロセスが作成される順序に対応します。 – Jotorious

1

OSはこれを行う方法を知っているので、必要はありません。実行するコアを指定した場合、あらゆる種類の問題に遭遇する可能性があります。その中には実際にプロセスを遅くするものがあります。 OSが把握できるように、新しいスレッドを開始するだけです。

たとえば、プロセスにコアxを開始するように指示しても、コアxはすでに負荷が重かっていた場合、OSに処理させた場合よりも悪化します。

+0

はい、私はupvoted、しかしおそらくあなたはプロセスAを実行していると、あなたはAを実行しているものを除いて、どのコアでもプロセスB、C、Dを起動したいと思うのはまったく合理的です。 –

30

通常、アプリケーションがどのコアを実行するかは、システムによって決定されます。ただし、特定のコアに対してアプリケーションの「親和性」を設定して、そのコアでのみアプリケーションを実行するようにOSに指示することができます。通常これは良い考えではありませんが、それが意味を成すかもしれないまれなケースがいくつかあります。

これを行うには、タスクマネージャを使用して、プロセスを右クリックして、「アフィニティを設定」を選択します。 SetThreadAffinityMask、SetProcessAffinityMask、SetThreadIdealProcessorなどの関数を使用して、Windowsでプログラムで行うことができます。

ETA:

あなたはOSが実際にスケジューリングを行う方法に興味があるなら、あなたはこれらのリンクをチェックアウトする場合があります:

Wikipedia article on context switching

Wikipedia article on scheduling

Scheduling in the linux kernel

最近のOSのほとんどでは、OSはコアのために実行するスレッドをスケジューリングします。短い時間スライス。タイムスライスが期限切れになるか、またはスレッドが自発的にコアを生成させるIO操作を実行すると、OSは別のスレッドをコアで実行するようにスケジューリングします(実行可能なスレッドがあれば)。正確にどのスレッドがスケジューリングされるかは、OSのスケジューリングアルゴリズムに依存します。

コンテキスト切り替えの正確な実装の詳細は、CPU & OSに依存します。一般に、カーネルモードへの切り替え、OSは以前のスレッドの状態の保存、新しいスレッドの状態のロード、ユーザーモードへの切り替え、そして新しくロードされたスレッドの再開を伴います。上記にリンクされたコンテキスト切り替えの記事には、これに関するもう少し詳細があります。

+0

+1は簡単な方法で提供しています。 –

+0

親和性マスクは子プロセスによって継承されるため、エクスプローラで設定すると、起動されたすべてのアプリケーションも使用可能なプロセッサのサブセットを使用します。 – Richard

1

私はアセンブリの指示は分かりません。 しかし、Windows API関数はSetProcessAffinityMaskです。 an exampleは、一度に1つのコアでPicasaを実行するために少し前に結んだものです。

2

他にも触れられているように、オペレーティングシステムによって制御されています。 OSによっては、特定のプロセスが実行するコアに影響を与えるシステムコールが提供される場合と提供されない場合があります。しかし、通常はOSにデフォルトの動作をさせるべきです。プロセスが37個実行されている4コアシステムがあり、そのうち34個がスリープしている場合は、残りの3個のアクティブプロセスを別々のコアにスケジュールする予定です。

非常に特殊化されたマルチスレッドアプリケーションでは、コアアフィニティでの再生でスピードが向上する可能性があります。たとえば、2つのデュアルコアプロセッサを搭載したシステムがあるとします。 3つのスレッドを持つアプリケーションがあり、2つのスレッドが同じデータセットで大きく動作し、3つ目のスレッドが異なるデータセットを使用するとします。この場合、同じプロセッサ上で相互作用する2つのスレッドと、もう1つのプロセッサ上の3つ目のスレッドを持つことで、キャッシュを共有できるので、最も効果的です。 OSは各スレッドがどのメモリにアクセスする必要があるか分からないため、スレッドを適切にコアに割り当てることができません。

に興味がある場合は、オペレーティングシステムschedulingをお読みください。 x86でのマルチプロセッシングの詳細は、Intel 64 and IA-32 Architectures Software Developer's Manualsにあります。第3A巻、第7章および第8章には関連情報が含まれていますが、これらのマニュアルは非常に技術的なものです。

3

OpenMPIプロジェクトは、のLinuxに移植可能な形でlibrary to set the processor affinityを持っています。

私はこれをプロジェクトで使用していましたが、うまくいきました。

警告:オペレーティングシステムがコアにどのように番号を付けるかを調べる際にいくつかの問題があることを覚えています。私はこれを4コアの2 Xeon CPUシステムでそれぞれ使用しました。

cat /proc/cpuinfoをご覧ください。私が使った箱には、それはかなり奇妙です。沸騰した出力は終わりです。

明らかに、偶数番号のコアは最初のCPU上にあり、奇数番号のコアは2番目のCPU上にあります。しかし、正しく覚えていれば、キャッシュに問題がありました。これらのIntel Xeonプロセッサでは、各CPUの2つのコアがL2キャッシュを共有しています(プロセッサにL3キャッシュがあるかどうかはわかりません)。私は仮想プロセッサー0と2が1つのL2キャッシュを共有していると思います.1と3は1つを共有し、4と6は1を共有し、5と7は1を共有しました。

この奇妙なこと(1.5年前にLinuxでプロセスナンバリングに関するドキュメントが見つかりませんでした)のため、この種の低レベルのチューニングには注意が必要です。しかし、明らかにいくつかの用途があります。あなたのコードがいくつかの種類のマシン上で動作するなら、この種のチューニングをする価値があるかもしれません。別のアプリケーションは、StreamItのような特定のドメイン固有の言語になります。ここで、コンパイラはこの汚い作業を行い、スマートなスケジュールを計算できます。

processor  : 0 
physical id  : 0 
siblings  : 4 
core id   : 0 
cpu cores  : 4 

processor  : 1 
physical id  : 1 
siblings  : 4 
core id   : 0 
cpu cores  : 4 

processor  : 2 
physical id  : 0 
siblings  : 4 
core id   : 1 
cpu cores  : 4 

processor  : 3 
physical id  : 1 
siblings  : 4 
core id   : 1 
cpu cores  : 4 

processor  : 4 
physical id  : 0 
siblings  : 4 
core id   : 2 
cpu cores  : 4 

processor  : 5 
physical id  : 1 
siblings  : 4 
core id   : 2 
cpu cores  : 4 

processor  : 6 
physical id  : 0 
siblings  : 4 
core id   : 3 
cpu cores  : 4 

processor  : 7 
physical id  : 1 
siblings  : 4 
core id   : 3 
cpu cores  : 4 
+0

また、SLERTはこれを試み、プロセッサまたはプロセッサグループを選択するためのかなり洗練されたメカニズムを備えています。 –

5

「このプロセスの実行を開始してください」というメッセージは表示されません。

コアには、実行可能コードと実行可能レベル、実行可能な命令に関するさまざまな制限事項が記載されています。プロセスは認識されません。

コンピュータの起動時には、簡単にするために1つのコア/プロセッサしかアクティブでなく、実際には任意のコードを実行します。 OSがマルチプロセッサ対応の場合、システム固有の命令で他のコアを起動し、他のコアは他のコアと同じ場所からピックアップしてそこから実行する可能性が最も高いです。

スケジューラは、OSの内部構造(タスク/プロセス/スレッドキュー)を調べ、コアを実行中とマークします。その後、他のコアで実行されている他のスケジューラインスタンスは、タスクが再び待機状態になる(特定のコアに固定されているとマークされていない)まで、他のコアで実行されるスケジューラインスタンスには触れません。タスクが実行中であるとマークされた後、スケジューラは以前に中断された時点でタスクを再開しながらユーザランドへの切り替えを実行します。

技術的には、全く同じコードを正確に同じコードで実行することからコアを停止するものは何もありませんが(多くのロックされていない機能があります)、それを期待するコードが書かれていなければ、

シナリオは、コアが必ずしもすべて同じメモリを参照する必要がなく、他のコアのクラッチからコードをフェッチする必要がある場合がある、よりエキゾチックなメモリモデル(上記の「通常の」線形シングルワーキングメモリ空間を想定します)タスクをコアに固定するだけで簡単に処理できます(AFAIK Sony PS3アーキテクチャはSPUを使用しています)。代わりに使用しては/ proc/cpuinfoをのプロセッサの数を調べるに

1

だけで実行します。

nproc 

を特定のプロセッサのグループでプロセスを実行するには:

taskset --cpu-list 1,2 my_command 

は私のことを言うだろうコマンドはCPU 1または2でのみ実行できます。

4つの異なる処理を行う4つのプロセッサでプログラムを実行するには、パラメータ化を使用します。 (へ

for i in `seq 0 1 3`; 
do 
    taskset --cpu-list $i my_command $i; 
done 

この(2mil-1)に0がプロセッサ1に行くように、配列内の800万操作を扱っている2milの良い例:プログラムへの引数は異なる何かをすることを伝えます4mil-1)をプロセッサ2などに送信する。あなたはapt-getを/ YUMを使用して、コマンドラインで実行されているホテルトップインストールすることにより、各プロセスの負荷を見ることができます

htop 
関連する問題