79

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.

doubledecker
  • 1,807
  • 3
  • 15
  • 13

15 Answers15

147

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
Mike S
  • 2,502
  • 2
  • 18
  • 29
stephaniea
  • 1,471
  • 4
    This is the best answer yet. It requires no reading of the tea leaves, lots of helpful information, and no grepping required. – MrMas Dec 11 '15 at 19:48
  • 18
    OMG you used a shell command to get your answer?! That's so old-school- -1 for that. What about a nice Python script??? It would only take you an afternoon to write. Since it's not Python, another -1. But +3 for brevity. – Mike S Aug 05 '16 at 20:06
  • 2
    @Mike S lots of sarcasm but... The output of lscpu ain't correct when, say, only 1 hyper-threaded core is down on a 4 cores CPU (which is a fully valid scenario). Because then it'll report "Thread(s) per core: 1" although 3 cores are actually hyperthreaded (7 threads in total). – Cedric Martin Oct 25 '17 at 23:15
  • @Cedric Martin you noticed. :-) ...Oooo! Good catch... I did it! Took a dual 8-core machine (Dell R620/E5-2667 v2 CPU)... it reports 32 CPUs... Performed echo 0 > /sys/devices/system/cpu/cpu31/online, now lscpu reports Thread(s) per core: 1. Bad lscpu! Guess I won't be using this any more. – Mike S Oct 26 '17 at 14:07
  • 5
    @Mike S You can still use lscpu, but just not that line I guess. Using, say, "lscpu -e -a" correctly list each thread and tells if it's active or not. It's just that "Thread(s) per core" doesn't make much sense when you can enable/disable threads differently on each core. – Cedric Martin Oct 26 '17 at 21:03
  • lscpu is fixed for Thread(s) # with offline cores since 2.20 : fix threads-per-core calculation in commit https://git.kernel.org/pub/scm/utils/util-linux/util-linux.git/commit/?id=e282eec2a259903a02841f516b7778a1f639d8ff – simohe Oct 10 '23 at 12:27
36

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.)

xebeche
  • 911
24

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"
Nils
  • 18,492
  • If $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? – Tombart Mar 13 '16 at 17:24
  • @Tombart Currently HT is factor 2. I can imagine that it might be more in the future. A core is noted as physical. The number of cores per socket can be derived from siblings. – Nils May 05 '16 at 21:22
  • 4
    If you have 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. – Trevor Boyd Smith Jan 02 '19 at 13:20
15

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
10

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)

maxschlepzig
  • 57,532
cyford
  • 101
10

If you read /sys/devices/system/cpu/cpu0/topology/thread_siblings_list, it will return a comma-separated list of the thread siblings (i.e. Hyperthread "cores") of CPU 0.

For instance, on my 2-socket 6-core Xeon, with hyperthreading enabled I get:

cat /sys/devices/system/cpu/cpu0/topology/thread_siblings_list
0,12

But after turning off hyperthreading in BIOS, I get:

cat /sys/devices/system/cpu/cpu0/topology/thread_siblings_list
0

Assuming that CPU 0 will always be available, then checking CPU 0's thread_sibling_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.


I'd answer in Perl, but 1) I don't know Perl, and 2) I assume the solution is a pretty trivial one-liner.

Lesmana
  • 27,439
scottbb
  • 558
  • 2
    Curiously, it's the answers with only a few votes that are the most useful, informative and correct. The voting model usually works well but for this question, the votes are heavily skewed towards the earlier answers. – Anthony Geoghegan Nov 21 '19 at 18:15
  • 2
    @AnthonyG-justiceforMonica Yeah, there's definitely a point bias based on the "early land rush" answers. That's okay though. I was looking to solve the problem at the time, when I came across this solution, so I wanted to share it with the community. – scottbb Nov 21 '19 at 18:19
  • 1
    Note, that on some distros, the separator could be - and not , e.g. $cat /sys/devices/system/cpu/cpu0/topology/thread_siblings_list 0-1 – Shmil The Cat Jun 30 '22 at 10:06
7

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`);'
billyw
  • 283
  • 1
    I have HT turned off on an Intel based HT capable system, yet Thread Count returned with dmidecode is twice the Core Count. Looks like it shows if the CPU is HT capable, not if HT is enabled or not. – Dima Chubarov Dec 16 '15 at 13:58
  • @Dmitri Weird. I just ran this on an HT-capable server (has two Intel Xeon E5-2670 v3's) with hyperthreading disabled, and the core and thread count were the same. I'm not sure what would cause the difference in behavior. I'll have to look further into it. – billyw May 26 '16 at 17:10
  • I just ran this on a Dell R610 with two X5680 processors, Hyperthreading off, and the Thread count is double the core count. stephaniea's answer (lscpu) seems to work. I have doublechecked the iDRAC (Dell's lights-out, out of band processor [for those not in the know]) and it says that Hyperthreading is off. So I don't think dmidecode is reliable. – Mike S Dec 01 '16 at 23:06
  • I checked a Dell 1950 (x5460 CPUs, no hyperthreading possible) and lscpu was correct. Also a Dell R620 (E5-2690 [v1, I believe]) and it was correct. – Mike S Dec 01 '16 at 23:13
  • But @Cedric Martin 's comment in one of the answers above shows that lscpu will not always be reliable. I like scottbb's answer. – Mike S Oct 26 '17 at 14:34
5
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
mpapec
  • 321
5

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
...
JayS
  • 151
4

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
Coren
  • 5,010
  • 2
    This will only tell you if the processor is HT capable, not if HT is actually being used. Nodes whose processor is HT-capable but where HT is not enable will still advertise ht in the CPU flags. – Riccardo Murri Apr 23 '14 at 18:01
  • @RiccardoMurri As far as I know, when HT is disabled, ht flag does not appear in /proc/cpuinfo – Coren Apr 24 '14 at 09:48
  • 7
    I'm pretty sure it's not. I have both HT-enabled and HT-disabled servers, and all of them show the ht flag. – Riccardo Murri Apr 25 '14 at 10:32
  • @RiccardoMurri Damn it, you're right. It's not like for vmx extension. I have updated my answer. – Coren May 02 '14 at 12:15
  • 2
    If you have a Xeon processor with 4 cores, it will show as one physical id and four processors. So you can have multiple processors per physical id without hyperhtreading. – Andomar Nov 09 '14 at 11:39
  • 1
    The ht flag is unreliable, at least in some cases. For instance, my dell box with Xeon 5150 reports ht in flags, but processor definitely does not support hyper-threading. – BillT Feb 11 '15 at 17:49
  • 2
    I've got a 2 socket machine, and the physical id seems to represent the socket/chip. The core id seems to point to the same physical core – Chang Hyun Park Jul 08 '15 at 03:11
  • The output of those commands simply indicate there are two logical CPUs. They could be provided by two cores on the same physical chip that information alone doesn't allow us to tell whether or not hyper-threading is being used. – Anthony Geoghegan Nov 21 '19 at 18:03
3

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
Mike S
  • 2,502
  • 2
  • 18
  • 29
  • 1
    I would just use 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 – maxschlepzig Aug 24 '19 at 15:04
3
lscpu | grep Thread

Returns -> Thread(s) per core: 1

If 1 hyper threading is NOT enabled.

mannoj
  • 231
2

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))
  • The suggestion for disabling hyperthreading is sub-optimal - the direct way to disable hyperthreading is echo off > /sys/devices/system/cpu/smt/control (besides turning it off in the bios). See also Oscar's answer for a direct check. – maxschlepzig Aug 24 '19 at 15:20
2

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
0

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
Gineesh
  • 187