In this tutorial, we’ll talk about hyperthreading – what it is and how to manage it.
2. What Is Hyper-Threading?
Hyper-Threading is a proprietary implementation of Simultaneous MultiThreading (SMT) from Intel. The chip-maker originally called it Hyper-Threading Technology, so we’ll shorten it as HTT. It’s present in modern processors from the manufacturer from 2002 onwards.
The aim of HTT, or in general any SMT technology, is to improve the parallelization of tasks. It achieves this by allowing multiple and independent tasks (threads of execution) to share some of the resources of the processors.
In Linux, this is represented as virtual cores, also known as logical CPUs, that are coupled with physical CPUs. In the remainder of the article, we’ll refer to HTT, but everything applies to SMT as well.
2.1. How to Know if We Have Hyper-Threading Enabled?
There are two techniques we can use to check if our system’s using HTT. We can call lscpu and just search (with grep) on its output the number of threads that each core has:
$ lscpu | grep "Thread(s) per core" Thread(s) per core: 2
From this output, we know that HTT is enabled because there’s more than one thread per core (two in this case). In case we had only one thread per core, we would know that HTT is disabled.
We can also inspect the file that contains the flag with the activation mode of SMT:
$ cat /sys/devices/system/cpu/smt/active 1
A value of 1 indicates that we have HTT enabled, while a 0 indicates that we have it disabled.
Moreover, we also need to know the thread siblings list, i.e., which physical CPUs are using HTT and which logical CPUs they refer to. We can use grep (with the -H option to display the filename):
$ grep -H . /sys/devices/system/cpu/cpu*/topology/thread_siblings_list /sys/devices/system/cpu/cpu0/topology/thread_siblings_list:0-1 /sys/devices/system/cpu/cpu1/topology/thread_siblings_list:0-1 /sys/devices/system/cpu/cpu2/topology/thread_siblings_list:2-3 /sys/devices/system/cpu/cpu3/topology/thread_siblings_list:2-3
We see two pairs of CPUs linked: cpu0 with cpu1 and cpu2 with cpu3. The first one is the physical CPU (cpu0 and cpu2), while the subsequent ones are the virtual CPUs where HTT occurs (cpu1 and cpu3). The separator between the items may be a dash (0-1, like in the snippet output) or a comma (0,1).
2.2. Reasons to Disable Hyper-Threading
There are several reasons to disable HTT, although the main two are security and stability.
Regarding security, there’ve been multiple vulnerabilities that exploit the feature of SMT. More specifically, in the case of Intel, the vulnerability Foreshadow (known by the manufacturer as L1 Terminal Fault) exploits HTT to gain access to sensitive data.
Regarding stability, the system may become more responsive when we disable HTT. This, somewhat counterintuitive result may be caused by reasons ranging from the scheduler to the caches or memory allocation per CPU.
3. Disabling Hyper-Threading
There are several ways to disable HTT. While our focus will be on those that we can do on a running system, we’ll first briefly discuss more persistent and better ways to deal with disabling HTT. Then, we’ll look at methods we can use on a running system.
3.1. Disable Hyper-Threading After a Reboot
The best way to disable HTT is by changing the hardware settings in the BIOS or system firmware. This is vendor specific, so we won’t cover it in more detail, but the OS will work with whatever the BIOS allows.
Another option is to set a directive to control the HTT in the kernel during booting. Depending on the kernel version, there are two directives that we can use in the kernel boot command line. For Linux 2.6.9. or older, the noht option controls HTT. For newer versions, the nosmt directive has the same behavior.
3.2. Disable Hyper-Threading at Runtime
It’s commonly discouraged to change the HTT settings at runtime because it can lead to unpredictable behaviors or runtime errors. However, we might need to disable HTT in a system that we can’t reboot. Moreover, it’s not advised to enable HTT after having disabled it. The best way to enable it again is to reboot.
We can disable HTT in only some sibling threads. For example, let’s imagine that in the previous example with cpu0-cpu1, we want to disable HTT in cpu1. With the help of tee, we can set the CPU to be offline:
$ echo 0 | sudo tee /sys/devices/system/cpu/cpu1/online
We might not need to run the previous command as root, depending on our user settings. To enable it again, we should replace the 0 with a 1.
However, if we want to disable HTT globally for all logical CPUs, there’s a better solution than disabling every logical CPU one by one:
$ echo off | sudo tee /sys/devices/system/cpu/smt/control
The three options that are available are on, off, and forceoff. The last one has the same behavior as off but rejects future attempts to modify the content of the file.
The methods applied at runtime are certainly not the same as disabling HTT from the BIOS. These methods disable HTT by disabling the logical CPUs and telling the task scheduler to use only the ones that we have left as active. Nevertheless, the results should be almost the same.
In this article, we’ve talked about hyper-threading. We learned how to find out if we have it enabled and how to disable it. We also understood the motivations we might have for doing that.