我有一台服务器,它是 12 核超线程系统,这意味着我有 24 个虚拟核心。
我在服务器上运行 24 个进程,每个进程都在自己的端口上监听并执行相同的操作,尽管来自不同的客户端和不同的请求。该进程是一个 Python 脚本,它是使用 gevent 构建的,用于在等待网络操作完成时实现并发。top 和 htop 显示每个进程使用的 CPU 和内存大致相同。由于我运行的进程数与核心数相同,因此我预计所有核心的负载都大致相同。但是,我看到只有一半的核心有实际负载(其余的核心显示负载最小)。
对我来说更奇怪的是,它总是相同的核心,6-11 和 18-23。更重要的是,我有三台相同的服务器,它们在相同的负载下执行相同的操作,并且所有 3 台服务器都在相同的负载下使用相同的核心。有人知道为什么会这样吗?
以下是其中一个服务器的 sar 输出:
04:34:01 PM CPU %user %nice %system %iowait %steal %idle
04:35:01 PM all 18.67 0.00 3.65 0.01 0.00 77.68
04:35:01 PM 0 9.24 0.00 0.76 0.00 0.00 89.99
04:35:01 PM 1 3.16 0.00 0.55 0.00 0.00 96.30
04:35:01 PM 2 1.40 0.00 0.66 0.00 0.00 97.94
04:35:01 PM 3 0.46 0.00 0.12 0.00 0.00 99.42
04:35:01 PM 4 0.15 0.00 0.12 0.00 0.00 99.73
04:35:01 PM 5 0.35 0.00 0.81 0.00 0.00 98.84
04:35:01 PM 6 44.19 0.00 10.05 0.02 0.00 45.74
04:35:01 PM 7 43.99 0.00 10.84 0.02 0.00 45.15
04:35:01 PM 8 27.00 0.00 2.57 0.09 0.00 70.33
04:35:01 PM 9 40.91 0.00 9.02 0.02 0.00 50.06
04:35:01 PM 10 41.97 0.00 10.27 0.00 0.00 47.77
04:35:01 PM 11 33.52 0.00 5.26 0.02 0.00 61.21
04:35:01 PM 12 0.53 0.00 0.10 0.00 0.00 99.37
04:35:01 PM 13 0.32 0.00 0.08 0.00 0.00 99.60
04:35:01 PM 14 0.22 0.00 0.10 0.00 0.00 99.68
04:35:01 PM 15 0.13 0.00 0.10 0.00 0.00 99.77
04:35:01 PM 16 0.12 0.00 0.05 0.00 0.00 99.83
04:35:01 PM 17 0.13 0.00 0.30 0.00 0.00 99.57
04:35:01 PM 18 16.54 0.00 1.49 0.00 0.00 81.97
04:35:01 PM 19 36.16 0.00 5.85 0.02 0.00 57.98
04:35:01 PM 20 29.22 0.00 4.97 0.10 0.00 65.71
04:35:01 PM 21 32.86 0.00 5.25 0.02 0.00 61.87
04:35:01 PM 22 43.01 0.00 9.19 0.00 0.00 47.80
04:35:01 PM 23 39.63 0.00 8.61 0.02 0.00 51.74
以下是 /proc/cpuinfo 中某个核心的输出:
processor : 23
vendor_id : GenuineIntel
cpu family : 6
model : 44
model name : Intel(R) Xeon(R) CPU X5675 @ 3.07GHz
stepping : 2
cpu MHz : 1600.000
cache size : 12288 KB
physical id : 1
siblings : 12
core id : 10
cpu cores : 6
apicid : 53
initial apicid : 53
fpu : yes
fpu_exception : yes
cpuid level : 11
wp : yes
flags : fpu vme de pse tsc msr pae mce cx8 apic mtrr pge mca cmov pat pse36 clflush dts acpi mmx fxsr sse sse2 ss ht tm pbe syscall nx pdpe1gb rdtscp lm constant_tsc arch_perfmon pebs bts rep_good xtopology nonstop_tsc aperfmperf pni dtes64 monitor ds_cpl vmx smx est tm2 ssse3 cx16 xtpr pdcm dca sse4_1 sse4_2 popcnt lahf_lm ida arat tpr_shadow vnmi flexpriority ept vpid
bogomips : 6133.17
clflush size : 64
cache_alignment : 64
address sizes : 40 bits physical, 48 bits virtual
power management:
这些系统还拥有约 24GB 的 RAM,其中使用量不到 4GB,并且没有显示任何交换活动。磁盘活动也很少,这些服务器所做的几乎所有工作都是网络绑定的,每个大约 60-80MB/s,进出双千兆以太网卡,绑定到单个接口。
答案1
这是因为它是超线程服务器。一半的 CPU 只是“虚拟”的。因此 Linux 会尽量避免使用这些虚拟 CPU,而将精力集中在真实的 CPU 上。
由于您的系统没有负载,因此您无法看到其他程序将在更高负载下使用。尝试增加负载。您会看到差异。
答案2
超线程核心不应被视为功能齐全的核心。请记住,它们是虚拟核心,因此它们共享物理核心的一些资源。超线程的好处体现在高度线程化和并行化的进程中,但不在您描述的用例中。根据我的经验,超线程核心的性能相当于真实核心的 30-40%,所以我倾向于不让重要的东西在它们上运行。如果您期望一对一的进程到核心映射,您最好将 12 个进程绑定到真实核心,或者通过禁用超线程或 CPU 屏蔽来完全避免使用虚拟核心。
您是否在使用某种形式的 CPU 亲和性映射 (taskset、cset),还是只让 Linux 处理分配?如果是这样,您看到的是调度程序对您的情况的最佳利用,即优先使用真实核心而不是虚拟核心。