HT:
HT(Hyper-Threading)是英特尔研发的一种技术,在一个物理核上提供2个逻辑核;阿里云ECS的超线程的实现基于英特尔 ® HT技术,允许在一个物理核上并发的运行两个线程(Thread),一个线程可以视为一个vCPU。
背景:
在公有云HPC 场景,大部分客户都是需要关闭HT 的,而HT 在公有云不管是裸金属还是VM规格,大部分默认都是打开的(少部分裸金属默认是关闭HT的,具体需要看规格);线下环境关闭方式都是通过bios 来将HT 关闭;在公有云上普通vm 场景,目前也有对应的api 可以实现bios 上关闭HT的 能力,具体可以参考:
https://help.aliyun.com/document_detail/145895.html?spm=5176.11065259.1996646101.searchclickresult.1ed34106uLy83j。但是在裸金属场景,HT的开关需要实际主板BIOS 上关闭HT,链路会比较长,涉及道硬件的重启,会比较慢,SLA很难保证;下面提供两种Guestos 内部的workround,可以实现类似HT 关闭的效果,这两种方法只在裸金属规格适应;
GuestOS 内部要关闭HT,实际上就是要模拟一个物理核上对应一个逻辑核,所以将每个物理核上的对应一个逻辑核关闭,保留一个物理核对应一个逻辑核就能达到HT关闭效果,实际理解可以认为offline 一半vcpu,并且这些vcpu都一一分布在对应的物理核上:
方法一、nr_cpus 指定最大cpu 使用数量:
nr_cpus 是一个内核参数,作用是限定内核最大支持的cpu 数量,上线是255,下线是2;如果要实现关闭HT的效果,我们可以设置nr_cpus=实例规格vCPU/2,这样内核支持的最大cpu数量就只有实际规格的一半,实际只使用一半cpu,达到offline一半cpu的要求,而且nr_cpus offline的一半的cpu 都是lscpu看到的后一半cpu;这里可能大家会有疑问,会不会offline掉的一半cpu 会有一个物理核上的2个线程都被offline掉的可能呢,下面我们来看下裸金属场景下内部vcpu和物理cpu mapping关系;
假设我们有4个物理核(0,1)(2,3)(4,5)(6,7),每个核有2个线程,在裸金属实例规格内的cpu mapping 关系如图一,按这个顺序如果我们实例内部设置nr_cpus=4的情况下,实例内部后一半4-7vcpu offline,实际对应offline的就是每个物理核上的一个逻辑核;
图一
目前线上的裸金属规格都是能保证这个cpu mapping 方式,所以这种方式在裸金属规格是可行的;
以
ecs.scch5s.16xlarge规格为例,该规格有64vCPU,操作系统是centos 7,具体disable 方法如下:
- lscpu 实例内部查看cpu情况,查看对应实例的HT是否开启,如果vcpu数和实例规格一致,并且Thread per core是2,表面该实例开启了HT
[root@izbp1ifjw9uxwwhw8pnly0z ~]# lscpu
Architecture: x86_64
CPU op-mode(s): 32-bit, 64-bit
Byte Order: Little Endian
CPU(s): 64 ---------和实例规格描述一致
On-line CPU(s) list: 0-63
Thread(s) per core: 2 ---------每个core有2个线程
Core(s) per socket: 16
Socket(s): 2
NUMA node(s): 1
Vendor ID: GenuineIntel
CPU family: 6
Model: 85
Model name: Intel(R) Xeon(R) Gold 6149 CPU @ 3.10GHz
Stepping: 4
CPU MHz: 1200.000
CPU max MHz: 3101.0000
CPU min MHz: 1200.0000
BogoMIPS: 6200.00
Virtualization: VT-x
L1d cache: 32K
L1i cache: 32K
L2 cache: 1024K
L3 cache: 22528K
NUMA node0 CPU(s): 0-63
[root@izbp1ifjw9uxwwhw8pnly0z ~]# vim /boot/grub2/grub.cfg
......
......
linux16 /boot/vmlinuz-3.10.0-693.5.2.el7.ecs.2.x86_64 root=UUID=59d9ca7b-4f39-4c0c-9334-c56c182076b5 ro crashkernel=auto net.ifnames=0 intel_idle.max_cstate=1 intel_pstate=enable processor.max_cstate=1 rd.driver.pre=virtio serial=tty0 console=ttyS0,115200n8 biosdevname=0 console=tty0 pci=realloc=on LANG=en_US.UTF-8 idle=halt nomodeset nr_cpus=32
......
......
- 设置nr_cpus=32之后,我们可以看到只能看到32核,并且都是分布在32个物理核上,达到了关闭HT的效果:
[root@izbp1ifjw9uxwwhw8pnly0z ~]# lscpu
Architecture: x86_64
CPU op-mode(s): 32-bit, 64-bit
Byte Order: Little Endian
CPU(s): 32 --------实际只使用了32个,是实例规格的1/2
On-line CPU(s) list: 0-31
Thread(s) per core: 1 --------每个core 只有1个thread
Core(s) per socket: 16
Socket(s): 2
NUMA node(s): 1
Vendor ID: GenuineIntel
CPU family: 6
Model: 85
Model name: Intel(R) Xeon(R) Gold 6149 CPU @ 3.10GHz
Stepping: 4
CPU MHz: 1200.000
CPU max MHz: 3101.0000
CPU min MHz: 1200.0000
BogoMIPS: 6200.00
Virtualization: VT-x
L1d cache: 32K
L1i cache: 32K
L2 cache: 1024K
L3 cache: 22528K
NUMA node0 CPU(s): 0-31
[root@izbp1ifjw9uxwwhw8pnly0z ~]# lscpu --extend
CPU NODE SOCKET CORE L1d:L1i:L2:L3 ONLINE MAXMHZ MINMHZ
0 0 0 0 0:0:0:0 yes 3101.0000 1200.0000
1 0 0 1 1:1:1:0 yes 3101.0000 1200.0000
2 0 0 2 2:2:2:0 yes 3101.0000 1200.0000
3 0 0 3 3:3:3:0 yes 3101.0000 1200.0000
4 0 0 4 4:4:4:0 yes 3101.0000 1200.0000
5 0 0 5 5:5:5:0 yes 3101.0000 1200.0000
6 0 0 6 6:6:6:0 yes 3101.0000 1200.0000
7 0 0 7 7:7:7:0 yes 3101.0000 1200.0000
8 0 0 8 8:8:8:0 yes 3101.0000 1200.0000
9 0 0 9 9:9:9:0 yes 3101.0000 1200.0000
10 0 0 10 10:10:10:0 yes 3101.0000 1200.0000
11 0 0 11 11:11:11:0 yes 3101.0000 1200.0000
12 0 0 12 12:12:12:0 yes 3101.0000 1200.0000
13 0 0 13 13:13:13:0 yes 3101.0000 1200.0000
14 0 0 14 14:14:14:0 yes 3101.0000 1200.0000
15 0 0 15 15:15:15:0 yes 3101.0000 1200.0000
16 0 1 16 16:16:16:1 yes 3101.0000 1200.0000
17 0 1 17 17:17:17:1 yes 3101.0000 1200.0000
18 0 1 18 18:18:18:1 yes 3101.0000 1200.0000
19 0 1 19 19:19:19:1 yes 3101.0000 1200.0000
20 0 1 20 20:20:20:1 yes 3101.0000 1200.0000
21 0 1 21 21:21:21:1 yes 3101.0000 1200.0000
22 0 1 22 22:22:22:1 yes 3101.0000 1200.0000
23 0 1 23 23:23:23:1 yes 3101.0000 1200.0000
24 0 1 24 24:24:24:1 yes 3101.0000 1200.0000
25 0 1 25 25:25:25:1 yes 3101.0000 1200.0000
26 0 1 26 26:26:26:1 yes 3101.0000 1200.0000
27 0 1 27 27:27:27:1 yes 3101.0000 1200.0000
28 0 1 28 28:28:28:1 yes 3101.0000 1200.0000
29 0 1 29 29:29:29:1 yes 3101.0000 1200.0000
30 0 1 30 30:30:30:1 yes 3101.0000 1200.0000
31 0 1 31 31:31:31:1 yes 3101.0000 1200.0000
使用nr_cpus的好处是:
- lscpu和cpuid等命令看到的内部实际使用的cpu数就是物理cpu数,不会看到offline的cpu,基本达到HT关闭效果和cpu核数显示;
但是也有对应的缺点:
- 就是一旦设置了nr_cpus=实例规格vcpu/2之后,offline掉的一半cpu 在线的情况下是无法在使用了,必须删除nr_cpus参数,然后重启才能恢复所有cpu;
- 打自定义镜像的时候需要特别注意,删除该参数,因为自定义镜像可能您会在不同规格上使用,不同规格下nr_cpus=实例规格vcpu/2的值是不一样的,假设在64vcpu上设置之后,该值就是nr_cpus=32,不删除的情况下打完自定义镜像,如果购买104vcpu场景下,就只能识别到32物理核,需要调整nr_cpus=52才能识别到52个物理核,达到关闭HT需求;
方法二:改变cpu状态,在线offline 一半cpu的方式:
原理和上面介绍的方法一一样,是每个物理核的一个逻辑核offline,在线修改的方式是使用命令,是对应一个物理核的一个逻辑核offline:
#!/bin/bash
for cpunum in $(cat /sys/devices/system/cpu/cpu*/topology/thread_siblings_list | cut -s -d, -f2- | tr ',' '\n' | sort -un)
do
echo 0 > /sys/devices/system/cpu/cpu$cpunum/online
done
还是以
规格为例,实例默认是64vcpu,在线offline 之前:
[root@izbp1ifjw9uxwwhw8pnly0z ~]# lscpu
Architecture: x86_64
CPU op-mode(s): 32-bit, 64-bit
Byte Order: Little Endian
CPU(s): 64 ---------和实例规格一致64vcpu
On-line CPU(s) list: 0-63
Thread(s) per core: 2 ---------每个core有2个thread
Core(s) per socket: 16
Socket(s): 2
NUMA node(s): 1
Vendor ID: GenuineIntel
CPU family: 6
Model: 85
Model name: Intel(R) Xeon(R) Gold 6149 CPU @ 3.10GHz
Stepping: 4
CPU MHz: 1200.000
CPU max MHz: 3101.0000
CPU min MHz: 1200.0000
BogoMIPS: 6200.00
Virtualization: VT-x
L1d cache: 32K
L1i cache: 32K
L2 cache: 1024K
L3 cache: 22528K
NUMA node0 CPU(s): 0-63
在offline 一半cpu 之后:
[root@izbp1ifjw9uxwwhw8pnly0z ~]# lscpu
Architecture: x86_64
CPU op-mode(s): 32-bit, 64-bit
Byte Order: Little Endian
CPU(s): 64
On-line CPU(s) list: 0-31 ------online的是32个vcpu
Off-line CPU(s) list: 32-63 ------offline 32个vcpu
Thread(s) per core: 1 每个core一个thread;
Core(s) per socket: 16
Socket(s): 2
NUMA node(s): 1
Vendor ID: GenuineIntel
CPU family: 6
Model: 85
Model name: Intel(R) Xeon(R) Gold 6149 CPU @ 3.10GHz
Stepping: 4
CPU MHz: 1200.000
CPU max MHz: 3101.0000
CPU min MHz: 1200.0000
BogoMIPS: 6200.00
Virtualization: VT-x
L1d cache: 32K
L1i cache: 32K
L2 cache: 1024K
L3 cache: 22528K
NUMA node0 CPU(s): 0-31
从lscpu --extend 可以看到,offline的最后一半cpu都是在每个物理core上的一个逻辑core;
[root@izbp1ifjw9uxwwhw8pnly0z ~]# lscpu --extend
CPU NODE SOCKET CORE L1d:L1i:L2:L3 ONLINE MAXMHZ MINMHZ
0 0 0 0 0:0:0:0 yes 3101.0000 1200.0000
1 0 0 1 1:1:1:0 yes 3101.0000 1200.0000
2 0 0 2 2:2:2:0 yes 3101.0000 1200.0000
3 0 0 3 3:3:3:0 yes 3101.0000 1200.0000
4 0 0 4 4:4:4:0 yes 3101.0000 1200.0000
5 0 0 5 5:5:5:0 yes 3101.0000 1200.0000
6 0 0 6 6:6:6:0 yes 3101.0000 1200.0000
7 0 0 7 7:7:7:0 yes 3101.0000 1200.0000
8 0 0 8 8:8:8:0 yes 3101.0000 1200.0000
9 0 0 9 9:9:9:0 yes 3101.0000 1200.0000
10 0 0 10 10:10:10:0 yes 3101.0000 1200.0000
11 0 0 11 11:11:11:0 yes 3101.0000 1200.0000
12 0 0 12 12:12:12:0 yes 3101.0000 1200.0000
13 0 0 13 13:13:13:0 yes 3101.0000 1200.0000
14 0 0 14 14:14:14:0 yes 3101.0000 1200.0000
15 0 0 15 15:15:15:0 yes 3101.0000 1200.0000
16 0 1 16 16:16:16:1 yes 3101.0000 1200.0000
17 0 1 17 17:17:17:1 yes 3101.0000 1200.0000
18 0 1 18 18:18:18:1 yes 3101.0000 1200.0000
19 0 1 19 19:19:19:1 yes 3101.0000 1200.0000
20 0 1 20 20:20:20:1 yes 3101.0000 1200.0000
21 0 1 21 21:21:21:1 yes 3101.0000 1200.0000
22 0 1 22 22:22:22:1 yes 3101.0000 1200.0000
23 0 1 23 23:23:23:1 yes 3101.0000 1200.0000
24 0 1 24 24:24:24:1 yes 3101.0000 1200.0000
25 0 1 25 25:25:25:1 yes 3101.0000 1200.0000
26 0 1 26 26:26:26:1 yes 3101.0000 1200.0000
27 0 1 27 27:27:27:1 yes 3101.0000 1200.0000
28 0 1 28 28:28:28:1 yes 3101.0000 1200.0000
29 0 1 29 29:29:29:1 yes 3101.0000 1200.0000
30 0 1 30 30:30:30:1 yes 3101.0000 1200.0000
31 0 1 31 31:31:31:1 yes 3101.0000 1200.0000
32 - - - ::: no - -
33 - - - ::: no - -
34 - - - ::: no - -
35 - - - ::: no - -
36 - - - ::: no - -
37 - - - ::: no - -
38 - - - ::: no - -
39 - - - ::: no - -
40 - - - ::: no - -
41 - - - ::: no - -
42 - - - ::: no - -
43 - - - ::: no - -
44 - - - ::: no - -
45 - - - ::: no - -
46 - - - ::: no - -
47 - - - ::: no - -
48 - - - ::: no - -
49 - - - ::: no - -
50 - - - ::: no - -
51 - - - ::: no - -
52 - - - ::: no - -
53 - - - ::: no - -
54 - - - ::: no - -
55 - - - ::: no - -
56 - - - ::: no - -
57 - - - ::: no - -
58 - - - ::: no - -
59 - - - ::: no - -
60 - - - ::: no - -
61 - - - ::: no - -
62 - - - ::: no - -
63 - - - ::: no - -
在线offline的优势:
可以使用 echo 1 > /sys/devices/system/cpu/cpu$cpunum/online 的方式将 offline 的 cpu 在 online 恢复回来,不需要重启;
在线offline的缺点:
在lscpu或者cpuid等命令里还是可以看到对应offline掉的cpu,有些license 检测到的还是全量cpu;
每次实例重启都需要重新设置一次;
总结:
两种HT 的work round方法,都能达到关HT的效果,并且使用hpl工具多轮 测试cpu性能,和物理上关闭HT效果实际差不多,同时主流的centos、rhel、debian、ubuntu高版本系统都能支持。但由于实际生产业务各种各样,无法真实模拟上述2种方式是否会对业务产生影响。在实际生产环境使用上述两种HT关闭方法下,请您做好详细的测试,是否对您的业务有影响;