Linux」カテゴリーアーカイブ

[Linux] process と CPU割り当て

CPU migration

Linux では SMP 構成をとる場合,できるだけ CPU を公平に使うようにスケジューリングされます.そのため,各プロセスの CPU 使用率を元に再スケジューリングのタイミングでプロセスの CPU migration (CPU 間の移動)が発生します.

migration で CPU 間をプロセスが移動するためには,一度動作を止めてコンテキスト(レジスタや状態情報など)を移動させて再開,という処理が行われますが,キャッシュ共有する「CPUコア間」に比べて共有しない「CPUクラスタ間」は移動にかかる時間が掛かるため,移動に重みづけしてスケジューラが次の CPU を判断します.

migration 動作を見る

ではプロセッサの migration でどうやって動いてるんだろう,と*手っ取り早く*調べたいと思ってたところ,
busybox の ps では CPU 割り付けが扱われないため,procps パッケージの ps を使うと確認できました.

$ ps -eo pid,psr,comm

ということで,下記のような shell script で回しておけば,出力ログを加工してグラフ化することで遷移の可視化もできます(かなり古典的手法ですが).

#!/bin/sh
(
    while :; do
        ps -eo pid,psr,comm | grep $PROG;
    done
) | awk '{print $1,",",$2}'

CPUやスケジューリングポリシーを指定

プログラムで直接 sched_setaffinity() や sched_setscheduler() を呼び出せばいいのですが,常にプログラムを書き換えられるわけではないので,できれば shell で指定できる方が都合がいいです.util-linux パッケージを使うと可能になります.

taskset で起動プロセスの CPU を固定することができます.例えば CPU1 でプロセスを起動したい場合は
以下のように指定します.

$ taskset -c 1 PROG

chrt で起動プロセスのポリシーを指定することができます.例えば SCHED_FIFO の priority=50 で
起動したいなら次のようにします.

$ chrt -f 50 PROG

また,kernel の起動オプションで ‘isolcpus’ を付けてCPUを指定すると,そのCPUはプロセスのCPU割り付け対象から外されます.全ての CPU を指定すると全て CPU0 でプロセスを起動するようになります.SMP 構成ながら Asymmetric に CPU を使うこともできそうです.

isolcpus=0-3

余談ですが…

SMP 構成の組込みシステムの場合,応答速度や処理量で破綻する可能性があるのであまり CPU を移動するのはうれしくないですが,特定の CPU に処理が集中するのも不利になるため適度に分散させたいため,スケジュールポリシーの選択は重要になってきます.

SCHED_FIFO,RR や CPU 割り付けを固定で行うこれまでのリアルタイム設計は複雑なシステムになるほど不都合になるため,SCHED_DEADLINE (EDF) や新たに提案されている Energy-Aware などの heuristic スケジューリングにも期待したいところです.

VMware Player 環境の再構築

システムの置き換え

これまで HDD 2台でそれぞれ Windows, Ubuntu を置いて、Windows から VMware で Ubuntu を起動していました。システムドライブを SSD に置き換えるにあたり、Windows も Ubuntu も SSD に置くことにしたのですが、ここでハマってしまったので記録しておきます。

Windows7 のインストールの際に SSD(250GB) を NTFS と ext4 に分けることを想定してパーティションを設定し、Windows7 のインストール、Windows10への upgrade、VMware Player のインストールまでは特にハマるところはなく進みました。

仮想環境の構築に失敗

VMware Player で仮想マシンを作成し、以前と同じように設定した後、HDD は IDE 物理ディスクの「PhysicalDrive0 のパーティション3(ext4想定の空き)」を指定して Ubuntu Desktop のインストールを開始。

後半で Grub のインストール先を指定しますが、上記インストールパーティションを指定すると失敗します。Grub は MBR にインストールするものですが、VMware は物理ディスクの場合もブート時に MBR を見に行くためそのままでは失敗します。

Grub は基本パーティションの Linux FileSystem にある /boot/grub/ を見に行くため、最初に Linux をインストールしてから Windows をインストールすれば解決しそうですが、Grub から Windows を起動すると、VMware Player の Grub からホスト OS のWindows が選択できてしまうためこれは惨事になるのが予想できます。

もう一つのシステムディスク登場

結局、SSD の MBR に Grub をインストールせずに VMware Player から論理パーティション上の Ubuntu が起動するには、もう一つディスクを用意して MBR を Grub にすればよいわけですが、仮想環境なので仮想ディスクを使えばよいわけです。

VMware Player で「仮想マシンの設定の編集」→「(ハードウェアタブ)追加」→「ハード ディスク」で通常のディスクを作成し、Grub が起動できればいいので “とりあえず” Ubuntu Server をインストールしました。Grub はこの仮想ディスクである /dev/sdb の MBR にインストールします。

物理パーティションOSの起動

この時点で VMware Player から Grub 経由で Ubuntu Server が起動しますし、物理パーティションの Ubuntu Desktop も認識しているので、メニューから選択すれば起動できます。しかしこちらがメインなので timeout してすぐに起動するように設定します。Grub の設定を行う Ubuntu Server 側で以下の設定値を変更します。

$ sudo vi /etc/default/grub
-GRUB_DEFAULT=0
+GRUB_DEFAULT=4
-GRUB_TIMEOUT=10
+GRUB_TIMEOUT=3
$ sudo update-grub

GRUB_DEFAULT はメニューのデフォルトの選択値です。私の環境では4つ目に Ubuntu Desktop があったので “4” を指定しています。また、GRUB_TIMEOUT は自動選択までの待ち時間で 3秒に設定し直しています。最後に update-grub で /boot/grub/grub.cfg を更新します。

これでめでたく SSD の Ubuntu Desktop が起動できました。これまで使っていた HDD も「IDE 物理ディスク」として設定してマウントすることでそのまま使うことができます。