How can I check if hyperthreading is enabled on a Linux machine, using a perl script to check for it?
I'm trying the following way:
dmidecode -t processor | grep HTT
Let me know if I'm on right track.
I have always just used the following and looked at 'Thread(s) per core:'.
hostname:~ # lscpu
Architecture: x86_64
CPU(s): 24
Thread(s) per core: 2 <-- here
Core(s) per socket: 6
CPU socket(s): 2
NUMA node(s): 2
Vendor ID: GenuineIntel
CPU family: 6
Model: 44
Stepping: 2
CPU MHz: 1596.000
Virtualization: VT-x
L1d cache: 32K
L1i cache: 32K
L2 cache: 256K
L3 cache: 12288K
Note, however, this technique will fail if any logical processor has been turned off with a simple
echo 0 > /sys/devices/system/cpu/cpuX/online
Notes added on July 8, 2014: As Riccardo Murri pointed out, my answer below only shows whether the processor reports to support hyperthreading. Generally, *nix O/S are configured to enable hyperthreading if supported. However, to actually check this programmatically see for instance Nils' answer!
---- Original answer from March 25, 2012:
You are indeed on the right track :) with
dmidecode -t processor | grep HTT
On Linux, I generally just look for "ht" on the "flags" line of /proc/cpuinfo. See for instance
grep '^flags\b' /proc/cpuinfo | tail -1
or if you want to include the "ht" in the pattern
grep -o '^flags\b.*: .*\bht\b' /proc/cpuinfo | tail -1
(\b matches the word boundaries and helps avoid false positives in cases where "ht" is part of another flag.)
lscpu is the way to check.
dmidecode; the CPUID flag represented by ht means “that the physical package is capable of supporting Intel Hyper-Threading Technology and/or multiple cores”, not that the CPU supports hyper-threading.
If the number of logical processors is twice the number of cores you have HT. Use to following script to decode /proc/cpuinfo:
#!/bin/sh
CPUFILE=/proc/cpuinfo
test -f $CPUFILE || exit 1
NUMPHY=`grep "physical id" $CPUFILE | sort -u | wc -l`
NUMLOG=`grep "processor" $CPUFILE | wc -l`
if [ $NUMPHY -eq 1 ]
then
echo This system has one physical CPU,
else
echo This system has $NUMPHY physical CPUs,
fi
if [ $NUMLOG -gt 1 ]
then
echo and $NUMLOG logical CPUs.
NUMCORE=`grep "core id" $CPUFILE | sort -u | wc -l`
if [ $NUMCORE -gt 1 ]
then
echo For every physical CPU there are $NUMCORE cores.
fi
else
echo and one logical CPU.
fi
echo -n The CPU is a `grep "model name" $CPUFILE | sort -u | cut -d : -f 2-`
echo " with`grep "cache size" $CPUFILE | sort -u | cut -d : -f 2-` cache"
$NUMCORE > $NUMLOG we can say that hyperthreading is enabled, right? It fact it would be 2 * $NUMCORE = $NUMLOG, is this always true or some CPUs might have 4x more cores?
lscpu available, lscpu will provide the same information along with lots of extra meta-data and the output from lscpu is more easily parseable. but this solution does work and only uses /proc/cpuinfo.
processor field starts at zero in my /proc/cpuinfo
The easiest way to check if SMT (generic for HT, which is just Intel branding) is active just do:
cat /sys/devices/system/cpu/smt/active
gives you 0 for inactive or 1 for active
You can actually turn it on or off at runtime with:
echo [on|off] > /sys/devices/system/cpu/smt/control
/sys/devices/system/cpu/smt/control is also possible and yields on|off|forceoff|notsupported|notimplemented.
/sys/devices/system/cpu/smt/control is on but /sys/devices/system/cpu/smt/active is 0?
If you read /sys/devices/system/cpu/cpu0/topology/core_cpus_list, it will return a comma-separated list of the "cores" on CPU 0. (It was previously was called thread_siblings_list, but that was deprecated. See below).
For instance, on my 2-socket 6-core Xeon, with hyperthreading enabled I get:
cat /sys/devices/system/cpu/cpu0/topology/core_cpus_list
0,12
But after turning off hyperthreading in BIOS, I get:
cat /sys/devices/system/cpu/cpu0/topology/core_cpus_list
0
Assuming that CPU 0 will always be available, then checking CPU 0's core_cpus_list procfs file for more than one node, or looking for a comma, or even just anything more than 0, will indicate if hyperthreading is enabled.
Source: How CPU topology info is exported via sysfs (kernel.org):
Export CPU topology info via sysfs. Items (attributes) are similar to
/proc/cpuinfooutput of some architectures. They reside in/sys/devices/system/cpu/cpuX/topology/: [...]
core_cpus:internal kernel map of CPUs within the same core. (deprecated name: “
thread_siblings”)
core_cpus_list:human-readable list of CPUs within the same core. (deprecated name: “
thread_siblings_list”);
I'd answer in Perl, but 1) I don't know Perl, and 2) I assume the solution is a pretty trivial one-liner.
Edit: thread_siblings and thread_siblings_list were deprecated in 2019 or 2020. Replaced them in answer with core_cpus and core_cpus_list.
- and not , e.g. $cat /sys/devices/system/cpu/cpu0/topology/thread_siblings_list 0-1
The above examples show if the CPU is capable of HT, but not if it is being used.
The last method works but not dual socket servers and VMs tested on Xenserver where it doesn’t display Physical CPU, since there are none.
I found this to be the easiest and less code way, which also worked on all my test environments. but requires bc.
echo "testing ################################### "
nproc=$(grep -i "processor" /proc/cpuinfo | sort -u | wc -l)
phycore=$(cat /proc/cpuinfo | egrep "core id|physical id" | tr -d "\n" | sed s/physical/\\nphysical/g | grep -v ^$ | sort | uniq | wc -l)
if [ -z "$(echo "$phycore *2" | bc | grep $nproc)" ]
then
echo "Does not look like you have HT Enabled"
if [ -z "$( dmidecode -t processor | grep HTT)" ]
then
echo "HT is also not Possible on this server"
else
echo "This server is HT Capable, However it is Disabled"
fi
else
echo "yay HT Is working"
fi
echo "testing ################################### "
I believe this will work on all platforms, and will tell you if its CPU is capable, and if it is enabled. May be a little messy, I'm a beginner at scripting though. I tested with centos XENSERVER vm, Ubuntu, and Openfiler (rpath)
/sys/devices/system/cpu/smt/control. See also Oscar's answer
This one liner seems to do the trick for me (requires root privileges):
dmidecode -t processor | grep -E '(Core Count|Thread Count)'
The output is:
Core Count: 2
Thread Count: 4
Thread count is double the core count, therefore I have hyperthreading enabled.
Or if you really want your perl script, as requested...
perl -e 'print grep(/Core Count/ || /Thread Count/, `dmidecode -t processor`);'
dmidecode is reliable.
lscpu will not always be reliable. I like scottbb's answer.
On Linux this works well:
$ lscpu -e
CPU NODE SOCKET CORE L1d:L1i:L2:L3 ONLINE
0 0 0 0 0:0:0:0 yes
1 0 0 1 1:1:1:0 yes
2 0 0 2 2:2:2:0 yes
3 0 0 3 3:3:3:0 yes
4 0 0 4 4:4:4:0 yes
5 0 0 5 5:5:5:0 yes
6 0 0 6 6:6:6:0 yes
7 0 0 7 7:7:7:0 yes
8 1 1 8 8:8:8:1 yes
9 1 1 9 9:9:9:1 yes
10 1 1 10 10:10:10:1 yes
11 1 1 11 11:11:11:1 yes
12 1 1 12 12:12:12:1 yes
13 1 1 13 13:13:13:1 yes
14 1 1 14 14:14:14:1 yes
15 1 1 15 15:15:15:1 yes
16 0 0 0 0:0:0:0 yes
17 0 0 1 1:1:1:0 yes
18 0 0 2 2:2:2:0 yes
19 0 0 3 3:3:3:0 yes
20 0 0 4 4:4:4:0 yes
21 0 0 5 5:5:5:0 yes
22 0 0 6 6:6:6:0 yes
23 0 0 7 7:7:7:0 yes
24 1 1 8 8:8:8:1 yes
25 1 1 9 9:9:9:1 yes
26 1 1 10 10:10:10:1 yes
27 1 1 11 11:11:11:1 yes
28 1 1 12 12:12:12:1 yes
29 1 1 13 13:13:13:1 yes
30 1 1 14 14:14:14:1 yes
31 1 1 15 15:15:15:1 yes
In the above example, we have 2 NUMA sockets (SOCKET=1 or 2). We have 16 physical cores (CORE=0 through 15). Each CORE has a sibling hyperthread (For example CORE=0 contains CPU 0,16.
We can verify the hyperthread like so:
$ cat /sys/devices/system/cpu/cpu0/topology/thread_siblings_list
0,16
The cache memory hierarchy is:
CPU 0 --> L1D_0|L1I_0 -> L2_0 -> L3_0
^ ^
CPU 16 ---| |
|
CPU 1 --> L1D_1|L1I_1 -> L2_1 --->
^
CPU 17 ---|
...
lscpu -p gives a csv format output for easy program parsing.
$ lscpu -p
# The following is the parsable format, which can be fed to other
# programs. Each different item in every column has an unique ID
# starting from zero.
# CPU,Core,Socket,Node,,L1d,L1i,L2,L3
0,0,0,0,,0,0,0,0
1,1,0,0,,1,1,1,0
2,2,0,0,,2,2,2,0
3,3,0,0,,3,3,3,0
4,4,0,0,,4,4,4,0
...
perl -ne'
$i++ if /^\s*$/;
push @{$x[$i]}, [/^(.+?) \s*:\s* (.+)/x] if /core|sibling|physical id/; }{
$r= shift @x;
for $i (0..$#$r) {
$$r[$i][1] .= " ".$$_[$i][1] for @x;
printf "%-15s: %s\n", @{$$r[$i]};
}
' /proc/cpuinfo
This result indicates that HT is enabled as siblings number (12) is greater than cpu cores (6)
physical id : 0 0 0 0 0 0 1 1 1 1 1 1 0 0 0 0 0 0 1 1 1 1 1 1
siblings : 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12
core id : 0 1 2 8 9 10 0 1 2 8 9 10 0 1 2 8 9 10 0 1 2 8 9 10
cpu cores : 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6
You can check HT capability of CPU with this command
# grep ht /proc/cpuinfo
You can list physical and logiciel CPU seen by Kernel with the following command:
# egrep -i "processor|physical id" /proc/cpuinfo
It gives this output on a single-core HT enabled CPU:
processor : 0
physical id : 0
processor : 1
physical id : 0
You can read the result like this:
processor : 0 (CPU 0, first logical)
physical id : 0 (CPU 0 is on the first physical)
processor : 1 (CPU 1, second logical)
physical id : 0 (CPU 1 is on the first physical)
=> It means I have HT enabled
ht in the CPU flags.
physical id seems to represent the socket/chip. The core id seems to point to the same physical core
Lot's of caveats and what-if's in the answers here... it seems the answer is not so obvious. lscpu has its gotcha's, which apply to any "count cores and logical processors, then compare" answer. Because you can shut off logical processors with a simple echo command (...this could be critical in a large enterprise environment where you're depending on turbo mode, for example).
Here's my try; thanks to @scottbb for the inspiration:
printf "HT is "; egrep -q [:punct:] /sys/devices/system/cpu/cpu0/topology/thread_siblings_list && echo on || echo off
On my Dell Xeon-based machines, the sibling list includes a comma when HT is on. On my laptop, it includes a hyphen (i5-3210m processor). So I'm egrep'ing for punctuation.
Thoughts? Criticisms?
The requester asked for perl, so here you go:
perl -ane 'chomp; print "Hyperthreading is "; if (/\D/) { print "ON\n" } else { print "OFF\n" }' < /sys/devices/system/cpu/cpu0/topology/thread_siblings_list
grep -q [-.] as this is less to type. FWIW, I've checked several Xeons/i5/i7's (including mobile variants) and none of them have a hyphen in the thread_siblings_list. It isn't sufficient to just check cpu0 - thus, something like this would be more robust: grep -q , /sys/devices/system/cpu/cpu*/topology/thread_siblings_list. However, just a grep 1 /sys/devices/system/cpu/smt/active -q is even more to the point - cf. Oscar's answer
lscpu | grep Thread
Returns -> Thread(s) per core: 1
If 1 hyper threading is NOT enabled.
Here's a python based approach - it also suggests ways to disable it if needed.
import re
total_logical_cpus = 0
total_physical_cpus = 0
total_cores = 0
logical_cpus = {}
physical_cpus = {}
cores = {}
hyperthreading = False
for line in open('/proc/cpuinfo').readlines():
if re.match('processor', line):
cpu = int(line.split()[2])
if cpu not in logical_cpus:
logical_cpus[cpu] = []
total_logical_cpus += 1
if re.match('physical id', line):
phys_id = int(line.split()[3])
if phys_id not in physical_cpus:
physical_cpus[phys_id] = []
total_physical_cpus += 1
if re.match('core id', line):
core = int(line.split()[3])
if core not in cores:
cores[core] = []
total_cores += 1
cores[core].append(cpu)
if (total_cores * total_physical_cpus) * 2 == total_logical_cpus:
hyperthreading = True
print(" This system has %d physical CPUs" % total_physical_cpus)
print(" This system has %d cores per physical CPU" % total_cores)
print(" This system has %d total cores" % (total_cores * total_physical_cpus))
print(" This system has %d logical CPUs" % total_logical_cpus)
if hyperthreading:
print(" HT detected, if you want to disable it:")
print(" Edit your grub config and add 'noht'")
print(" -OR- disable hyperthreading in the BIOS")
print(" -OR- try the following to offline those CPUs:")
for c in cores:
for p, val in enumerate(cores[c]):
if p > 0:
print(" echo 0 > /sys/devices/system/cpu/cpu%d/online" % (val))
echo off > /sys/devices/system/cpu/smt/control (besides turning it off in the bios). See also Oscar's answer for a direct check.
Stephaniea has already mentioned lscpu. I wanted to add a bit more to that.
On my AMD Epyc Processor, whenever there is an offline logical core, lscpu displays a new additional line called Off-line CPU(s) list:
# echo 0 > /sys/devices/system/cpu/cpu9/online
# echo 0 > /sys/devices/system/cpu/cpu16/online
#
#lscpu
CPU(s): 64
On-line CPU(s) list: 0-8,10-15,17-63
Off-line CPU(s) list: 9,16
Better you check lscpu, where you can see "Thread(s) per core: 1", means only one thread per 1 core.
# lscpu
Architecture: x86_64
CPU op-mode(s): 32-bit, 64-bit
Byte Order: Little Endian
CPU(s): 8
On-line CPU(s) list: 0-7
Thread(s) per core: 1
Core(s) per socket: 4
Socket(s): 2
NUMA node(s): 2
Vendor ID: GenuineIntel
CPU family: 6
Model: 63
Model name: Intel(R) Xeon(R) CPU E5-2623 v3 @ 3.00GHz
Stepping: 2
CPU MHz: 1200.000
BogoMIPS: 5992.82
Virtualization: VT-x
L1d cache: 32K
L1i cache: 32K
L2 cache: 256K
L3 cache: 10240K
NUMA node0 CPU(s): 0,1,4,5
NUMA node1 CPU(s): 2,3,6,7
dmidecodeyou have to be root.[perl]unset ^^