如何确保正在运行的进程的独占 CPU 可用性?

Jea*_*ido 36 performance process debian process-management

起初,这个问题似乎有点愚蠢/令人困惑,因为操作系统负责管理进程执行。

但是,我想测量一些进程受 CPU/IO 限制的程度,并且我觉得我的操作系统正在干扰我的实验,例如,预定的操作系统进程。

以以下情况为例:我运行了进程 A 两次,并从工具“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   |
+---+-------+---------+-----------+---------+
Run Code Online (Sandbox Code Playgroud)

正如我们所看到的,虽然用户时间和系统时间相似,但两者的经过时间发生了巨大变化(相差约 5 分钟)。感觉我的环境中的某些东西引起了某种争用。

我想停止所有可能的后台进程/服务,以避免在我的实验过程中出现任何类型的噪音,但我认为自己是一个新手/中级 unix 用户,我不知道如何保证这一点。

我使用的Linux 4.4.0-45泛型与Ubuntu的LTS 14.04的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
Run Code Online (Sandbox Code Playgroud)

Rui*_*iro 41

您有一个内核选项配置,其中操作系统不会使用 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 上分离了前端守护进程。

由于您有 8 个 CPU,因此您可以通过以下命令的输出进行检查:

$ grep -c proc /proc/cpuinfo
8
Run Code Online (Sandbox Code Playgroud)

或者

$ lscpu | grep '^CPU.s'
CPU(s):                8
Run Code Online (Sandbox Code Playgroud)

将文件中的 Debian/Ubuntu 添加/etc/default/grub到选项中GRUB_CMDLINE_LINUX:

GRUB_CMDLINE_LINUX="isolcpus=7"
Run Code Online (Sandbox Code Playgroud)

(它是 7,因为它从 0 开始,并且您有 8 个内核)

然后跑,

sudo update-grub
Run Code Online (Sandbox Code Playgroud)

这是告诉内核不要使用您的内核之一。

重新启动系统。

然后开始你的过程。

启动它后,您可以立即更改第 8 个 CPU(7 因为 0 是第一个),并且非常确定您是唯一一个使用该 CPU 的人。

为此,请使用以下命令:

taskset -cp 7 PID_number
Run Code Online (Sandbox Code Playgroud)

任务集 - 检索或设置进程的 CPU 亲和性

概要

   taskset [options] [mask | list ] [pid | command [arg]...]
Run Code Online (Sandbox Code Playgroud)

描述

taskset 用于设置或检索给定 PID 的正在运行的进程的 CPU 亲和性,或使用给定的 CPU 亲和性启动新的 COMMAND。CPU 亲和性是一个调度程序属性,它将进程“绑定”到系统上的一组给定 CPU。Linux 调度程序将遵守给定的 CPU 关联性,并且该进程不会在任何其他 CPU 上运行。请注意,Linux 调度程序还支持自然 CPU 亲和性:出于性能原因,调度程序尽可能将进程保持在同一 CPU 上。因此,强制特定的 CPU 关联仅在某些应用程序中有用。

有关更多信息,请参阅:isolcpus、numactl 和 taskset

同样使用ps -eF您应该在 PSR 列中看到正在使用的处理器。

我有一个 CPU 2 和 3 隔离的服务器,实际上,可以看到用户空间中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
Run Code Online (Sandbox Code Playgroud)

如果将它与非隔离 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
Run Code Online (Sandbox Code Playgroud)


小智 5

正如 @Aaron D. Marasco 所提到的,使用csetfromcpuset包也是可能的。(isolcpus并未真正弃用。)其优点之一cset是配置之间无需重新启动,并且如果使用多个核心,调度程序负载平衡器将保持活动状态。

为我们的任务保留处理器 5 和 11

cset shield --cpu 5,11 --kthread on # cpu 5 and 11, move kernel processes if possible
Run Code Online (Sandbox Code Playgroud)

检查我们的 cpuset 上正在运行什么

cset shield -s -v
Run Code Online (Sandbox Code Playgroud)

在 cpuset 上执行任务

cset shield -e bash
Run Code Online (Sandbox Code Playgroud)

附加一个进程

cset shield --shield --pid 22010
Run Code Online (Sandbox Code Playgroud)

分离一个进程

cset shield --unshield --pid 22010
Run Code Online (Sandbox Code Playgroud)

恢复一切

cset shield --reset
Run Code Online (Sandbox Code Playgroud)