実行中のプロセスに対して排他的なCPU可用性を保証する方法は?

実行中のプロセスに対して排他的なCPU可用性を保証する方法は?

最初は、オペレーティングシステムがプロセスの実行を管理しているため、この質問はやや愚かで混乱しているようです。

しかし、CPU / IOバインドされたいくつかのプロセスがどれくらいになるかを測定したいと思い、OSがスケジュールされたOSプロセスと同じ実験を妨げているようです。

たとえば、次の状況を考えてみます。プロセスAを2回実行し、「time」ツールから次の出力を取得しました(時間列は秒単位)。

+---+-------+---------+-----------+---------+
|Run|Process|User Time|System Time|Wall time|
+---+-------+---------+-----------+---------+
|1  |A      |196.3    |5.12       |148.86   |
|2  |A      |190.79   |4.93       |475.46   |
+---+-------+---------+-----------+---------+

ご覧のとおり、ユーザー時間とシステム時間は似ていますが、2つの実行時間は大きく異なります(約5分程度の違い)。私の環境の何かがある種の議論を引き起こすように感じました。

実験中にノイズを避けるために、可能な限りすべてのバックグラウンドプロセス/サービスを停止したいと思います。しかし、私は自分自身を初心者/中級のUnixユーザーだと思い、それをどのように保証できるかわかりません。

私はそれを使用していますLinux 4.4.0-45 - 汎用そしてUbuntu 14.04 LTS 64ビット。

あなたの助けに本当に感謝します。不足している情報が必要な場合は、すぐに投稿を修正いたします。

CPU情報

$ grep proc /proc/cpuinfo | wc -l
8
$ lscpu
Architecture:          x86_64
CPU op-mode(s):        32-bit, 64-bit
Byte Order:            Little Endian
CPU(s):                8
On-line CPU(s) list:   0-7
Thread(s) per core:    2
Core(s) per socket:    4
Socket(s):             1
NUMA node(s):          1
Vendor ID:             GenuineIntel
CPU family:            6
Model:                 60
Stepping:              3
CPU MHz:               4002.609
BogoMIPS:              7183.60
Virtualization:        VT-x
L1d cache:             32K
L1i cache:             32K
L2 cache:              256K
L3 cache:              8192K
NUMA node0 CPU(s):     0-7

答え1

OSがCPUを使用しないカーネルオプション設定がありますisolcpus

isolcpus - カーネルスケジューラからCPUを切り離します。

概要 isolcpus= cpu_number [, cpu_number ,...]

説明共通カーネルSMPバランシングおよびスケジューラアルゴリズムでcpu_number値で定義された指定されたCPUを削除します。 「解放された」CPUの内外にプロセスを移動する唯一の方法は、CPUアフィニティシステムコールを使用することです。 cpu_numberは0から始まるため、最大値はシステムのCPU数より1未満です。

単純なテスト以上に役立つこの構成を設定する方法を説明します。

たとえば、MeruはLinuxベースのAPコントローラでこの技術を使用して、ネットワークトラフィックがI / O操作として知られているオペレーティングシステムの内部操作を妨げないようにします。

私も同じ理由で非常に忙しいWebフロントエンドでそれを使用しています。私は人生の経験を通してサーバーの制御を失い、フロントエンドデーモンを切り離すまで強制的に再起動する必要があることがよくわかりました。独自の専用CPU。

CPUが8つなので、次のコマンド出力で確認できます。

$ grep -c proc /proc/cpuinfo
8

または

$ lscpu | grep '^CPU.s'
CPU(s):                8

ファイルにDebian / Ubuntu/etc/default/grubオプションを追加しますGRUB_CMDLINE_LINUX

GRUB_CMDLINE_LINUX="isolcpus=7"

(0から始まり、コアが8つなので7です。)

次に実行します。

sudo update-grub

これはカーネルがコアの1つを使用しないように指示します。

システムを再起動します。

その後、プロセスを開始します。

起動するとすぐに8番目のCPU(7、0が最初のもの)に変わり、そのCPUを使用している唯一のCPUであることを確認できます。

これを行うには、次のコマンドを使用します。

taskset -cp 7 PID_number

ワークセット - プロセスの CPU アフィニティを取得または設定します。

要約

   taskset [options] [mask | list ] [pid | command [arg]...]

説明する

ワークセットは、指定されたPIDに対して実行中のプロセスのCPUアフィニティを設定または取得するため、または指定されたCPUアフィニティで新しいコマンドを開始するために使用されます。 CPU アフィニティは、プロセスをシステムの特定の CPU セットに「バインド」するスケジューラ属性です。 Linux スケジューラは指定された CPU アフィニティを尊重し、プロセスは他の CPU で実行されません。 Linuxスケジューラは自然なCPUの好みもサポートします。パフォーマンス上の理由から、スケジューラは可能な限りプロセスを同じ CPU に保持しようとします。したがって、特定のCPUの好みを強制することは、特定のアプリケーションでのみ有用です。

これについて詳しくは、次をご覧ください。isolcpus、numactl、ワークセット

また、ps -eFPSR列に使用されているプロセッサを表示する必要があります。

CPU 2と3が分離されたサーバーがあり、実際には1つps -eのプロセスしか表示できません。ユーザーエリア予想通りそうですpound

# ps -eo psr,command | tr -s " " | grep "^ [2|3]"
 2 [cpuhp/2]
 2 [watchdog/2]
 2 [migration/2]
 2 [ksoftirqd/2]
 2 [kworker/2:0]
 2 [kworker/2:0H]
 3 [cpuhp/3]
 3 [watchdog/3]
 3 [migration/3]
 3 [ksoftirqd/3]
 3 [kworker/3:0]
 3 [kworker/3:0H]
 2 [kworker/2:1]
 3 [kworker/3:1]
 3 [kworker/3:1H]
 3 /usr/sbin/pound

孤立していないCPUと比較すると、はるかに多くのタスクが実行されます(下のウィンドウ)。スライドショー):

# ps -eo psr,command | tr -s " " | grep "^ [0|1]"
 0 init [2]
 0 [kthreadd]
 0 [ksoftirqd/0]
 0 [kworker/0:0H]
 0 [rcu_sched]
 0 [rcu_bh]
 0 [migration/0]
 0 [lru-add-drain]
 0 [watchdog/0]
 0 [cpuhp/0]
 1 [cpuhp/1]
 1 [watchdog/1]
 1 [migration/1]
 1 [ksoftirqd/1]
 1 [kworker/1:0]
 1 [kworker/1:0H]
 1 [kdevtmpfs]
 0 [netns]
 0 [khungtaskd]
 0 [oom_reaper]
 1 [writeback]
 0 [kcompactd0]
 0 [ksmd]
 1 [khugepaged]
 0 [crypto]
 1 [kintegrityd]
 0 [bioset]
 1 [kblockd]
 1 [devfreq_wq]
 0 [watchdogd]
 0 [kswapd0]
 0 [vmstat]
 1 [kthrotld]
 0 [kworker/0:1]
 0 [deferwq]
 0 [scsi_eh_0]
 0 [scsi_tmf_0]
 1 [vmw_pvscsi_wq_0]
 0 [bioset]
 1 [jbd2/sda1-8]
 1 [ext4-rsv-conver]
 0 [kworker/0:1H]
 1 [kworker/1:1H]
 1 [bioset]
 0 [bioset]
 1 [bioset]
 1 [bioset]
 1 [bioset]
 1 [bioset]
 1 [bioset]
 1 [bioset]
 0 [jbd2/sda3-8]
 1 [ext4-rsv-conver]
 1 /usr/sbin/rsyslogd
 0 /usr/sbin/irqbalance --pid=/var/run/irqbalance.pid
 1 /usr/sbin/cron
 0 /usr/sbin/sshd
 1 /usr/sbin/snmpd -Lf /dev/null -u snmp -g snmp -I -smux -p /var/run/snmpd.pid
 1 /sbin/getty 38400 tty1
 1 /lib/systemd/systemd-udevd --daemon
 0 /usr/sbin/xinetd -pidfile /run/xinetd.pid -stayalive
 1 [kworker/1:2]
 0 [kworker/u128:1]
 0 [kworker/0:2]
 0 [bioset]
 1 [xfsalloc]
 1 [xfs_mru_cache]
 1 [jfsIO]
 1 [jfsCommit]
 0 [jfsCommit]
 0 [jfsCommit]
 0 [jfsCommit]
 0 [jfsSync]
 1 [bioset]
 0 /usr/bin/monit -c /etc/monit/monitrc
 1 /usr/sbin/pound
 0 sshd: rui [priv]
 0 sshd: rui@pts/0,pts/1
 1 -bash
 1 -bash
 1 -bash
 1 [kworker/u128:0]
 1 -bash
 0 sudo su
 1 su
 1 bash
 0 bash
 0 logger -t cmdline root[/home/rui] 
 1 ps -eo psr,command
 0 tr -s 
 0 grep ^ [0|1]
 0 /usr/bin/vmtoolsd

答え2

@Aaron D. Marascoが述べたように、csetfromパッケージを使用するcpusetことも可能です。 (isolcpus実際には廃止されました。)利点の1つcsetは、構成間で再起動する必要はなく、複数のコアを使用している場合はスケジューラロードバランサがアクティブのままであることです。

作業のためにプロセッサ5と11を予約します。

cset shield --cpu 5,11 --kthread on # cpu 5 and 11, move kernel processes if possible

私たちのCPUSetで何が実行されているかを確認してください。

cset shield -s -v

CPUsetでジョブを実行する

cset shield -e bash

プロセス接続

cset shield --shield --pid 22010

プロセスの分離

cset shield --unshield --pid 22010

すべてを復元する

cset shield --reset

関連情報