答案1
介绍
这个问题很有趣。对我个人来说,这可能是几个月来最有趣的问题之一。和楼主一样,我的旧 BIOS(2012 年发明,2016 年左右更新)中没有禁用超线程的选项。
Intel Skylake 和 Kaby Lake 中的超线程错误:
任何使用英特尔 Skylake或者卡比湖处理器必须阅读几个月前出现的有关超线程的错误报告。这英国注册故事详细说明了 Debian 开发人员如何发现超线程如何导致机器崩溃和损坏。
去年,Ask Ubuntu 上报告了许多有关 Skylake 的问题,人们想知道如何辨别哪些问题可能是由超线程错误引起的。
本回答分为三部分:
- 关闭/打开超线程时显示 CPU
- 自动打开/关闭超线程的 Bash 脚本
- 如果在启动前关闭超线程,Conky 会崩溃
关闭/打开超线程时显示 CPU
下面您可以看到关闭超线程并执行 CPU 压力测试时的 CPU 利用率。大约 10 秒后,在打开超线程的情况下重复相同的脚本。最后 10 秒后,再次关闭超线程运行脚本:
显示屏分为两部分:
- 在终端窗口的左半部分,
set-hyper-threading
使用参数 0(关闭)和 1(打开)调用脚本。 - 右半部分
conky
显示 CPU 1 至 8 的 CPU 利用率百分比。
第一个脚本关闭超线程
第一次运行脚本时,CPU 编号 2、4、6 和 8(根据 Conky)分别冻结在 3%、2%、2% 和 2%。运行压力测试时,CPU 编号 1、3、5 和 7 会飙升至 100%。
显示 CPU 拓扑,超线程已关闭且仅报告四个核心:
/sys/devices/system/cpu/cpu0/topology/core_id:0
/sys/devices/system/cpu/cpu2/topology/core_id:1
/sys/devices/system/cpu/cpu4/topology/core_id:2
/sys/devices/system/cpu/cpu6/topology/core_id:3
第二个脚本运行超线程
脚本第二次运行时,超线程打开,并且在压力测试运行时所有 CPU 编号 1-8 都飙升至 100%。
显示 CPU 拓扑,超线程已打开,并且仅报告四个核心加四个虚拟核心:
/sys/devices/system/cpu/cpu0/topology/core_id:0
/sys/devices/system/cpu/cpu1/topology/core_id:0
/sys/devices/system/cpu/cpu2/topology/core_id:1
/sys/devices/system/cpu/cpu3/topology/core_id:1
/sys/devices/system/cpu/cpu4/topology/core_id:2
/sys/devices/system/cpu/cpu5/topology/core_id:2
/sys/devices/system/cpu/cpu6/topology/core_id:3
/sys/devices/system/cpu/cpu7/topology/core_id:3
第三个脚本关闭超线程
请注意,第二个脚本结束后,CPU 2、4、6 和 8 的空闲率分别为 4%、2%、3%、4%。这一点很重要,因为在第三个测试中,关闭超线程后,这些 CPU 的百分比将冻结在 4%、2%、3%、4%,而不是第一个测试中的 3%、2%、2% 和 2%。
因此,关闭超线程似乎只是将虚拟 CPU 冻结在当前状态。
另请注意,无论您打开还是关闭超线程,脚本仍然显示“支持超线程”。
自动打开/关闭超线程的 Bash 脚本
查看下面的脚本时请记住 Conky 将 CPU 编号从 1 到 8,但 Linux 将 CPU 编号从 0 到 7。
#!/bin/bash
# NAME: set-hyper-threading
# PATH: /usr/local/bin
# DESC: Turn Hyper threading off or on.
# DATE: Aug. 5, 2017.
# NOTE: Written Part of testing for Ubuntu answer:
# https://askubuntu.com/questions/942728/disable-hyper-threading-in-ubuntu/942843#942843
# PARM: 1="0" turn off hyper threading, "1" turn it on.
if [[ $# -ne 1 ]]; then
echo 'One argument required. 0 to turn off hyper-threading or'
echo '1 to turn hyper-threading back on'
exit 1
fi
echo $1 > /sys/devices/system/cpu/cpu1/online
echo $1 > /sys/devices/system/cpu/cpu3/online
echo $1 > /sys/devices/system/cpu/cpu5/online
echo $1 > /sys/devices/system/cpu/cpu7/online
grep "" /sys/devices/system/cpu/cpu*/topology/core_id
grep -q '^flags.*[[:space:]]ht[[:space:]]' /proc/cpuinfo && \
echo "Hyper-threading is supported"
grep -E 'model|stepping' /proc/cpuinfo | sort -u
stress --cpu 8 --io 1 --vm 1 --vm-bytes 128M --timeout 10s
笔记:该程序stress
内置于所有 Debian 系统(Ubuntu 是其衍生产品)。因此,您无需下载和安装任何软件包即可在 Ubuntu 中运行此脚本。
如果您有双核 CPU,则需要删除(或注释掉#
)控制 CPU 编号 5 和 7 的行。
归功于嗨天使用于显示 CPU 拓扑的 bash 行grep "" /sys/devices/system/cpu/cpu*/topology/core_id
。
如果在启动前关闭超线程,Conky 会崩溃
为了使 CPU 2、4、6、8 的利用率达到最低水平,我尝试在启动时关闭超线程。我使用了这个脚本来做到这一点:
# NAME: /etc/cron.d/turn-off-hyper-threading
# DATE: Auguust 5, 1017
# DESC: This turns off CPU 1, 3, 5 & 7
# NOTE: Part of testing for Ubuntu answer:
# https://askubuntu.com/questions/942728/disable-hyper-threading-in-ubuntu/942843#942843
# BUGS: Conky crashes with Segmentation Fault when CPU 2,4,6 & 8 (as conky calls them)
# are off-line.
#
SHELL=/bin/sh
PATH=/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin
#
# @reboot root echo 0 > /sys/devices/system/cpu/cpu1/online
# @reboot root echo 0 > /sys/devices/system/cpu/cpu3/online
# @reboot root echo 0 > /sys/devices/system/cpu/cpu5/online
# @reboot root echo 0 > /sys/devices/system/cpu/cpu7/online
但是conky
如果在启动时关闭超线程,就会因分段错误而崩溃。因此我不得不注释掉@reboot
脚本中的四行。
Conky 代码显示 CPU 百分比利用率和负载因子
如果您有兴趣在 Conky 中设置类似的显示,以下是相关的代码片段:
${color orange}${voffset 2}${hr 1}
${color2}${voffset 5}Intel® i-7 3630QM 3.4 GHz: ${color1}@ ${color green}${freq} MHz
${color}${goto 13}CPU 1 ${goto 81}${color green}${cpu cpu1}% ${goto 131}${color3}${cpubar cpu1 18}
${color}${goto 13}CPU 2 ${goto 81}${color green}${cpu cpu2}% ${goto 131}${color3}${cpubar cpu2 18}
${color}${goto 13}CPU 3 ${goto 81}${color green}${cpu cpu3}% ${goto 131}${color3}${cpubar cpu3 18}
${color}${goto 13}CPU 4 ${goto 81}${color green}${cpu cpu4}% ${goto 131}${color3}${cpubar cpu4 18}
${color}${goto 13}CPU 5 ${goto 81}${color green}${cpu cpu5}% ${goto 131}${color3}${cpubar cpu5 18}
${color}${goto 13}CPU 6 ${goto 81}${color green}${cpu cpu6}% ${goto 131}${color3}${cpubar cpu6 18}
${color}${goto 13}CPU 7 ${goto 81}${color green}${cpu cpu7}% ${goto 131}${color3}${cpubar cpu7 18}
${color}${goto 13}CPU 8 ${goto 81}${color green}${cpu cpu8}% ${goto 131}${color3}${cpubar cpu8 18}
${color1}All CPU ${color green}${cpu}% ${goto 131}${color1}Temp: ${color green}${hwmon 2 temp 1}°C ${goto 250}${color1}Up: ${color green}$uptime
${color green}$running_processes ${color1}running of ${color green}$processes ${color1}loaded processes.
Load Avg. 1-5-15 minutes: ${alignr}${color green}${execpi .001 (awk '{printf "%s/", $1}' /proc/loadavg; grep -c processor /proc/cpuinfo;) | bc -l | cut -c1-4} ${execpi .001 (awk '{printf "%s/", $2}' /proc/loadavg; grep -c processor /proc/cpuinfo;) | bc -l | cut -c1-4} ${execpi .001 (awk '{printf "%s/", $3}' /proc/loadavg; grep -c processor /proc/cpuinfo;) | bc -l | cut -c1-4}
${color1}NVIDIA ${color}-GPU ${color green}${nvidia gpufreq} Mhz ${color}-Memory ${color green}${nvidia memfreq} Mhz
${color1}GT650M ${color}-Temp ${color green}${nvidia temp}°C ${color}-Threshold ${color green}${nvidia threshold}°C
${color orange}${voffset 2}${hr 1}
笔记:完整的 conky 资源文件可以在以下位置找到:这个答案。
答案2
您可以以 root 身份或超级用户权限禁用 Linux 中的超线程:
# echo off > /sys/devices/system/cpu/smt/control
您可以显示当前超线程状态和:
$ cat /sys/devices/system/cpu/smt/control
此命令打印以下之一:
on|off|forceoff|notsupported|notimplemented
或者,使用最新的内核,您可以通过在内核参数中添加nosmt
或来禁用超线程。nosmt=force
此外,大多数 BIOS 固件都包含禁用超线程的选项。如果在 BIOS 中禁用了超线程,则上面的 cat 可能会返回forceoff
。
答案3
最近的内核支持 maxcpus内核参数。
这允许您将 CPU 数量设置为物理核心数量。这可能有助于缓解由以下因素引起的威胁:MDS 漏洞在英特尔第 6 代 CPU 上。
如何:
使用 sudo(root)权限使用您最喜欢的文本编辑器打开 /etc/default/grub。
找到以以下内容开头的行GRUB_CMDLINE_LINUX_DEFAULT=
并将 maxcpus=n 添加到任何现有的内核参数中,例如常见的安静的飞溅参数(其中 n = 您的 CPU 拥有的物理核心的数量。
例如,在我信赖的 Intel(R) Core(TM) i3-3220 CPU @ 3.30GHz 双核超线程上,我添加了最大 CPU 数=2在启动时关闭超线程。
保存文件然后发出命令sudo update-grub
并重新启动。
您可以通过发出以下命令来确认成功lscpu | grep "per core"
,该命令应提供如下输出:
Thread(s) per core: 1
在内核 4.4.0 上测试
资料来源:
https://github.com/torvalds/linux/blob/master/Documentation/admin-guide/kernel-parameters.txt
https://www.kernel.org/doc/html/latest/admin-guide/hw-vuln/mds.html
https://unix.stackexchange.com/questions/145645/disabling-cpu-cores-on-quad-core-processor-on-linux
答案4
maxcpus=n
中的参数无法GRUB_CMDLINE_LINUX_DEFAULT=
正常工作。它给我留下了 2 个核心和 4 个线程,而不是 4 个核心 4 个线程。
我找到了一个解决方案。
改为添加mitigations=auto,nosmt
到GRUB_CMDLINE_LINUX_DEFAULT=
在搭载 Linux 4.4.0 的 Ubuntu 16.04 LTS 上进行了测试。