Disable hyperthreading from within Linux (no access to BIOS)

Solution 1:

You can do this at runtime if you want to. I found a nice solution described here: http://www.absolutelytech.com/2011/08/01/how-to-disable-cpu-cores-in-linux/

Step 1: Identify the linux CPUs you want to switch off:

cat /proc/cpuinfo

Look for the CPUs that have the same "core id", you want to switch off one of each pair.

Step 2: Switch off the hyperthreading CPUs (in my case the last four of the total 8 "CPUs" seen by Linux)

echo 0 > /sys/devices/system/cpu/cpu4/online
echo 0 > /sys/devices/system/cpu/cpu5/online
echo 0 > /sys/devices/system/cpu/cpu6/online
echo 0 > /sys/devices/system/cpu/cpu7/online

You could setup yourself a script that you run just after system start.

Solution 2:

Newer Kernels provide a Simultaneous Multithreading (SMT) control.

You can check the state of SMT with;

cat /sys/devices/system/cpu/smt/active

Change the state with

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

Options are;

  • on
  • off
  • forceoff

We have tested this with Linux Kernel 4.4.0


Solution 3:

A script to disable hyperthreading in the machine startup...

To disable hyperthreading I include a script on machine /etc/rc.local. It is not exaclty clean, but is easy to install, independent of cpu architecture and should work on any modern linux distribution.

nano /etc/rc.local

    # place this near the end before the "exit 0"

    for CPU in /sys/devices/system/cpu/cpu[0-9]*; do
        CPUID=$(basename $CPU)
        echo "CPU: $CPUID";
        if test -e $CPU/online; then
                echo "1" > $CPU/online; 
        fi;
        COREID="$(cat $CPU/topology/core_id)";
        eval "COREENABLE=\"\${core${COREID}enable}\"";
        if ${COREENABLE:-true}; then        
                echo "${CPU} core=${CORE} -> enable"
                eval "core${COREID}enable='false'";
        else
                echo "$CPU core=${CORE} -> disable"; 
                echo "0" > "$CPU/online"; 
        fi; 
    done;    

How this works?

Linux kernel information and controls can be accessed as files in /sys directory on modern linux distributions. For example:

/sys/devices/system/cpu/cpu3 contains the kernel information and controls for logical cpu 3.

cat /sys/devices/system/cpu/cpu3/topology/core_id will show the core number this logical cpu belongs to.

echo "0" > /sys/devices/system/cpu/cpu3/online allows to disable logical cpu 3.

Why it works?

I do not know exactly why... but the system become more responsive with hyperthreading off (on my i5 notebook and massive Xeon servers with 60+ cores). I guess that has to do with per-cpu caches, per-cpu memory allocation, cpu scheduler allocation and process priorities complex iterations. I think the benefits of hyperthreading is outweight by the complexity of making cpu schedulers that know how to use it.

For me, the problem with hyperthreading is: If I start as many cpu-intensive threads as I have logical cores, I will have fast context switches for the cpu intensive tasks, but expensive ones for the background tasks since the hyperthreading totally consumed by the cpu intensive tasks. On the other hand, if I start as many cpu-intensive threads as I have physical cores I will have no context switches to those tasks and fast context switches for the background tasks. Seems good, but the background tasks will found free logical processors and will run almost imediatedly. It is like they are realtime performace (nice -20).

In the first scenario the hyperthreading is uselles, the background tasks will use expensive context switches because I maxed out hyperthreading with the normal processing. The second is unaceptable because up to 50% of my cpu power gets prioritized to the background tasks.

The "cpu-intensive" tasks I am talking about are artificial intelligence data mining and authorization servers (my work). Blender rendering in cheap computers and clusters (to sketch my future house).

Also, this is guesswork.

I have the impression that is better, but it may not.


Solution 4:

For really old kernels (Linux 2.6.9 or so), append the noht parameter to the kernel on boot.

This kernel command-line option has been removed since at least Linux 2.6.18.


From http://www.faqs.org/docs/Linux-HOWTO/BootPrompt-HOWTO.html :

The `noht' Argument

This will disable hyper-threading on intel processors that have this feature. 

If using lilo edit you /etc/lilo.conf (and run lilo afterwards) or if using grub then edit your /boot/grub/menu.lst .


Solution 5:

You can use the "thread_siblings_list" for each core to turn off the second core in the HT pair.

The following command pipeline is hacky, not optimised, and done this way hopefully to make it easier to understand.

cat /sys/devices/system/cpu/cpu*/topology/thread_siblings_list | \
awk -F, '{print $2}' | \
sort -n | \
uniq | \
( while read X ; do echo $X ; echo 0 > /sys/devices/system/cpu/cpu$X/online ; done )

so, take all the thread siblings lists, extract the second CPU for each pair, get a unique list, and then turn them off.

does this make sense?

if I do "cat /proc/cpuinfo" after running the above, the number of cores halves.