天天看点

公有云上裸金属规格HT关闭方案

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的就是每个物理核上的一个逻辑核;

公有云上裸金属规格HT关闭方案

图一

目前线上的裸金属规格都是能保证这个cpu mapping 方式,所以这种方式在裸金属规格是可行的;

ecs.scch5s.16xlarge

规格为例,该规格有64vCPU,操作系统是centos 7,具体disable 方法如下:

  1. 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
      
  1. 我们在grub里配置nr_cpus=实例规格vcpu/2, 我们的 是64vcpu,这里nr_cpus=32参数,然后重启:
[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
......
......      
  1. 设置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的好处是:

  1. lscpu和cpuid等命令看到的内部实际使用的cpu数就是物理cpu数,不会看到offline的cpu,基本达到HT关闭效果和cpu核数显示;

但是也有对应的缺点:

  1. 就是一旦设置了nr_cpus=实例规格vcpu/2之后,offline掉的一半cpu 在线的情况下是无法在使用了,必须删除nr_cpus参数,然后重启才能恢复所有cpu;
  2. 打自定义镜像的时候需要特别注意,删除该参数,因为自定义镜像可能您会在不同规格上使用,不同规格下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关闭方法下,请您做好详细的测试,是否对您的业务有影响;

继续阅读