20

I am running ubuntu 16.04 server. I can see that hype threading is enabled when I use the lscpu command.

I want to disable it . I went through ubuntu forums and here and here.

These are good discussions why hyper threading may may- not be good. But no definitive solution on how to turn it off.

Can any give the steps for disabling hyperthreading ? Thanks .

3
  • 3
    Have you tried disabling it in the BIOS?
    – edwinksl
    Aug 3, 2017 at 17:16
  • yes, could not find an option for HT
    – john
    Aug 3, 2017 at 17:43
  • @MobTactics: It is much more easy! Just add ht=off except your things to disable hyperthreading.
    – france1
    Jun 6, 2021 at 9:40

8 Answers 8

12

Introduction

This is an interesting question. Probably one of the most interesting in months for me personally. Like the OP there is no option for disabling Hyper Threading in my old BIOS (invented 2012, updated 2016 or so).

Hyper-Threading bugs in Intel Skylake and Kaby Lake:

Anyone using Intel Skylake or Kaby Lake processors must read the bug reports about Hyper Threading that surfaced a couple months ago. This UK Register story spells out how Debian Developers spotted how Hyper Threading can crash and corrupt the machine.

There are numerous problems with Skylake reported in Ask Ubuntu over the last year and one wonders how to discern which problems may have been caused by Hyper Threading bugs.

This answer is divided into three parts:

  • Display of CPUs when Hyper-Threading is turned off/on
  • Bash script to automate turning hyper-threading off/on
  • Conky Crashes if Hyper Threading is turned off before it starts

Display of CPUs when Hyper-Threading is turned off/on

Below you can see the CPU utilization when hyper-threading is turned off and a CPU stress test is performed. About 10 seconds later the same script is repeated with hyper threading turned on. Finally 10 seconds after that the script is run with hyper-threading turned off again:

Set Hyper Threading noht

The display is divided into two sections:

  • On the left half the terminal window invoking the script set-hyper-threading with the parameter 0 (off) and then 1 (on).
  • On the right half conky displays the CPU percentage utilization of CPUS 1 to 8.

First script run Hyper Threading off

The first time the script is run CPU Numbers 2, 4, 6 & 8 (according to Conky) are frozen at 3%, 2%, 2% and 2%. CPU Numbers 1, 3, 5 and 7 spike to 100% while stress test is run.

The CPU topology is displayed with hyper-threading turned off and only the four cores reported:

/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

Second script run Hyper Threading on

The second time the script is run Hyper-Threading is turned on and all CPU Numbers 1-8 spike to 100% while stress test is run.

The CPU topology is displayed with hyper-threading turned on and only the four cores plus and four virtual cores reported:

/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

Third script run Hyper Threading off

Note how after the second script ends CPUs 2, 4, 6 and 8 are idling at 4%, 2%, 3%, 4%. This is important because in the third test turning Hyper-Threading off shows those CPU percentages frozen at 4%, 2%, 3%, 4% rather than 3%, 2%, 2% and 2% from the first test.

Therefore turning off hyper-threading seems to just freeze the virtual CPUs at the current state.

Also note no matter if you turn Hyper-Threading on or off the script still displays "Hyper Threading Supported".


Bash script to automate turning hyper-threading off/on

When viewing the script below keep in mind that Conky numbers the CPUs from 1 to 8 but Linux numbers the CPUs from 0 to 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

NOTE: The program stress is built into all Debian systems which Ubuntu is a derivative of. Therefore you don't have to download and install any packages to run this script in Ubuntu.

If you have a dual core CPU you need to remove (or comment out with #) the lines controlling CPU numbers 5 and 7.

Credit to Hi-Angel for bash line grep "" /sys/devices/system/cpu/cpu*/topology/core_id displaying CPU topology.


Conky Crashes if Hyper Threading is turned off before it starts

To get CPUs 2, 4, 6, 8 to lowest percent utilization possible I tried turning off Hyper-Threading during boot up. I used this script to do that:

# 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

However conky crashes with a segmentation fault if hyper-threading is turned off when it starts up. As such I had to comment out the four @reboot lines in the script.

Conky Code to display CPU percent utilization and load factor

If you are interested in setting up a similar display in Conky here is the relevant code snippet:

${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}

NOTE: The full conky resource file can be found on this answer.

10
  • 1
    Sorry, but noht doesn't exist. I even grepped for the option through linux-4.13-rc1 sources that I happen to occasionally have. However I certainly understand what could've confused you: dat bugreport complains that the option doesn't work, and then it's closed as nextrelease, like if they fixed something. However if you read the comments, you'll see that the only use of noht is for a hand-crafted script which checks the kernel command line for the option, then disables cores through /sys/ filesystem. IOW noht is useless.
    – Hi-Angel
    Aug 4, 2017 at 7:34
  • @Hi-Angel Thanks for pointing out it's not necessary. I did testing without it and the off-line cores doubled from 2,2,5,5 % (with noht) to 5,5,10,10% (without noht). I'll do more testing tonight. I searched kernel parameter documentation and could not find any reference to noht. Aug 4, 2017 at 10:43
  • On side note, there's no Machine/Human language to indexing :) To resolve confusion with indices starting from 0, 1, or even a particular number (as it is in MiniZinc), it's better to think in terms of index sets, i.e. a surjection from a set of indices to another set. Abstracting it away allows you to note easier when some relevant to a data stuff, that does not represent indices, can actually be used for indexing after getting twiddled a bit. The advantage comes from having in mind a concept unbound from a memory layout and other limitations.
    – Hi-Angel
    Aug 5, 2017 at 14:37
  • @Hi-Angel Similar comparison between "Start Position" and "Offset" I guess. Anyway I'm about to rewrite this answer based on last two days of testing and coding so our comments will soon be obsolete... Aug 5, 2017 at 16:05
  • Rick - what's that cool terminal based calendar you've got running there??
    – Diagon
    Apr 22, 2020 at 8:59
12

You can disable hyperthreading in Linux as root or with superuser privileges with:

# echo off > /sys/devices/system/cpu/smt/control

You can display the current hyperthreading status with:

$ cat /sys/devices/system/cpu/smt/control

This command prints one of:

on|off|forceoff|notsupported|notimplemented

Alternatively, with recent kernels, you can disable hyperthreading by adding nosmt or nosmt=force to your kernel parameters.

Also, most BIOS firmwares include an option for disabling hyperthreading. If it's disabled in the BIOS the above cat likely returns forceoff.

3
  • Have you tried this to disable hyper threading at boot?
    – Elder Geek
    Sep 16, 2019 at 18:24
  • 1
    @ElderGeek no, I haven't tried the maxcpus= kernel parameter for disabling hyperthreading. Mainly because I can't find any official documentation on its interaction with hyperthreading cores. Is it guaranteed to always disable hyperthreading if you specify maxcpus=#real_cores? Or might you end up with half the real-cores with HT still enabled on some systems? Also one maxcpus= setting isn't portable between machines with different core counts. Maintaining variations of this parameter for different machines would be tedious and error-prone. Sep 16, 2019 at 18:37
  • In my experience is has always disabled hyperthreading if you specify maxcpus=#real_cores provided of course that you trust the output of lscpu | grep "per core" You make a vaild point regarding portability however, on the flip side setting the kernel parameter once doesn't seem too onerous a task to me.
    – Elder Geek
    Sep 16, 2019 at 18:51
6

Recent kernels support the maxcpus kernel parameter.

This allows you to set the number of cpus to the number of physical cores. This may be useful to help mitigate threats caused by MDS vulnerabilities on Intel CPUs from family 6.

How:

with sudo (root) privileges open /etc/default/grub with your favorite text editor.

Find the line that begins with GRUB_CMDLINE_LINUX_DEFAULT=

and add maxcpus=n to any existing kernel parameters such as the common quiet splash parameters (where n = the number of physical cores your cpu has.

For example on my trusty Intel(R) Core(TM) i3-3220 CPU @ 3.30GHz dual core with hyperthreading I added maxcpus=2 to turn off hyperthreading at boot time.

Save the file and then issue the command sudo update-grub and reboot.

You can confirm success by issuing the command lscpu | grep "per core" which should provide output like this:

Thread(s) per core: 1

Tested on kernel 4.4.0

Sources:

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

2
3

Here is a script to identify the ht-cores and toggle them online/offline.

#!/bin/bash
typeset -i core_id
typeset -i sibling_id
typeset -i state

for i in /sys/devices/system/cpu/cpu[0-9]*; do
  core_id="${i##*cpu}"
  sibling_id="-1"

  if [ -f ${i}/topology/thread_siblings_list ]; then
    sibling_id="$(cut -d',' -f1 ${i}/topology/thread_siblings_list)"
  fi

  if [ $core_id -ne $sibling_id ]; then
    state="$(<${i}/online)"
    echo -n "$((1-state))" > "${i}/online"
    echo "switched ${i}/online to $((1-state))"
  fi
done

@WinEunuuchs2Unix, maybe you can add this to your excellent answer.

1
  • I had to numerically sort the list to make it work properly: for i in $(find /sys/devices/system/cpu/cpu[0-9]* -maxdepth 0 -type d |sort -V); do
    – neuhaus
    Jun 18, 2019 at 14:47
3

The maxcpus=n parameter in GRUB_CMDLINE_LINUX_DEFAULT= doesn't work properly. It left me with 2 cores and 4 threads instead of 4 cores 4 threads.

I found a solution.

Add mitigations=auto,nosmt to GRUB_CMDLINE_LINUX_DEFAULT= instead

Tested on Ubuntu 16.04 LTS with Linux 4.4.0.

Source: https://wiki.ubuntu.com/SecurityTeam/KnowledgeBase/MDS

1

A slightly more robust way of looking in the kernel for hyperthread pairs is needed for systems where the motherboard hosts multiple CPU sockets because core_id is duplicated. Here's my version on a system with two 8-core Xeon chips (example from Ubuntu 16.04):

$ cat /sys/devices/system/cpu/cpu*/topology/thread_siblings_list \
> | sort --unique --numeric-sort
0,16
1,17
2,18
3,19
4,20
5,21
6,22
7,23
8,24
9,25
10,26
11,27
12,28
13,29
14,30
15,31

For various purposes, you may also want to look in the files

/sys/devices/system/cpu/present
/sys/devices/system/cpu/online
/sys/devices/system/cpu/offline
0

If you've read discussions, then you probably know that usually it's unreasonable to disable, so I'll assume you want it for learning purposes.

The idea of HT is having multiple sets of CPU registers for every physical core (the so called virtual cores). There's no a "better" virtual core, they're identical. Armed with this knowledge you can disable virtual cores except for one for every physical one.

First you want to know which pair of virtual cores belong to which physical core at /sys/ filesystem. You can use core_id file for that:

λ grep "" /sys/devices/system/cpu/cpu*/topology/core_id
/sys/devices/system/cpu/cpu0/topology/core_id:0
/sys/devices/system/cpu/cpu1/topology/core_id:2
/sys/devices/system/cpu/cpu2/topology/core_id:0
/sys/devices/system/cpu/cpu3/topology/core_id:2

From the output you can infer that cpu0+cpu2 are contained in one physical core, and cpu1+cpu3 in the other. Now elevate privileges, and use echo command to disable one in every pair:

λ sudo -s
# echo 0 > /sys/devices/system/cpu/cpu1/online
# echo 0 > /sys/devices/system/cpu/cpu2/online

Note that cpu0 don't have "online" file and can't be disabled, so I disabled cpu2 instead.

0
0

@visit1985's answer doesn't work if the separator in thread_siblings_list is not a comma (which is, for example, the case on my AMD Ryzen system).

Here is a script to turn hyper-threading off that works with any separator:

#!/bin/bash

for cpu in /sys/devices/system/cpu/cpu[1-9]*; do
    if [ -e "$cpu/topology/thread_siblings_list" ]; then
        sibling=$(awk -F '[^0-9]' '{ print $2 }' $cpu/topology/thread_siblings_list)
        if [ ! -z $sibling ]; then
            echo 0 > "/sys/devices/system/cpu/cpu$sibling/online"
        fi
    fi
done

And here is one to turn hyper-threading on:

#!/bin/bash

for cpu in /sys/devices/system/cpu/cpu[1-9]*; do
    echo 1 > "$cpu/online"
done
1

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .