Hyper-Threading is Intel's implementation of simultaneous multithreading (SMT). Current AMD processors don't implement SMT (the Bulldozer microarchitecture family has something else AMD calls cluster based multithreading but the Zen microarchitecture is suppose to have SMT). OpenMP has no builtin support to detect SMT.
If you want a general function to detect Hyper-Threading you need to support different generations of processors and make sure that the processor is an Intel processor and not AMD. It's best to use a library for this.
But you can create a function using OpenMP that works for many modern Intel processors as I described here.
The following code will count the number of physical cores on an modern Intel processors (it has worked on every Intel processor I have tried it on). You have to bind the threads to get this to work. With GCC you can use
export OMP_PROC_BIND=true
otherwise you can bind with code (which is what I do).
Note that I am not sure this method is reliable with VirtualBox. With VirtualBox on a 4 core/8 logical processor CPU with windows as Host and Linux as guess setting the number of cores for the VM to 4 this code reports 2 cores and /proc/cpuinfo shows that two of the cores are actually logical processors.
#include <stdio.h>
//cpuid function defined in instrset_detect.cpp by Agner Fog (2014 GNU General Public License)
//http://www.agner.org/optimize/vectorclass.zip
// Define interface to cpuid instruction.
// input: eax = functionnumber, ecx = 0
// output: eax = output[0], ebx = output[1], ecx = output[2], edx = output[3]
static inline void cpuid (int output[4], int functionnumber) {
#if defined (_MSC_VER) || defined (__INTEL_COMPILER) // Microsoft or Intel compiler, intrin.h included
__cpuidex(output, functionnumber, 0); // intrinsic function for CPUID
#elif defined(__GNUC__) || defined(__clang__) // use inline assembly, Gnu/AT&T syntax
int a, b, c, d;
__asm("cpuid" : "=a"(a),"=b"(b),"=c"(c),"=d"(d) : "a"(functionnumber),"c"(0) : );
output[0] = a;
output[1] = b;
output[2] = c;
output[3] = d;
#else // unknown platform. try inline assembly with masm/intel syntax
__asm {
mov eax, functionnumber
xor ecx, ecx
cpuid;
mov esi, output
mov [esi], eax
mov [esi+4], ebx
mov [esi+8], ecx
mov [esi+12], edx
}
#endif
}
int getNumCores(void) {
//Assuming an Intel processor with CPUID leaf 11
int cores = 0;
#pragma omp parallel reduction(+:cores)
{
int regs[4];
cpuid(regs,11);
if(!(regs[3]&1)) cores++;
}
return cores;
}
int main(void) {
printf("cores %d\n", getNumCores());
}