I have a multi threaded c++ application that runs on Windows, Mac and a few Linux flavors.
To make a long story short: In order for it to run at maximum efficiency, I have to be able to instantiate a single thread per physical processor/core. Creating more threads than there are physical processors/cores degrades the performance of my program considerably. I can already correctly detect the number of logical processors/cores correctly on all three of these platforms. To be able to detect the number of physical processors/cores correctly I'll have to detect if hyper-treading is supported AND active.
My question therefore is if there is a way to detect whether Hyper Threading is supported and enabled? If so, how exactly.
Check CPU cores from /proc/cpuinfo File in Linux The best way to check the number of CPU cores in Linux is by looking at the /proc/cpuinfo file. Open the terminal and run this command: cat /proc/cpuinfo | grep “cpu cores” | uniq |sed -n 1p |awk '{print $4}'. It will list the number of CPU cores on your system.
EDIT: This is no longer 100% correct due to Intel's ongoing befuddlement.
The way I understand the question is that you are asking how to detect the number of CPU cores vs. CPU threads which is different from detecting the number of logical and physical cores in a system. CPU cores are often not considered physical cores by the OS unless they have their own package or die. So an OS will report that a Core 2 Duo, for example, has 1 physical and 2 logical CPUs and an Intel P4 with hyper-threads will be reported exactly the same way even though 2 hyper-threads vs. 2 CPU cores is a very different thing performance wise.
I struggled with this until I pieced together the solution below, which I believe works for both AMD and Intel processors. As far as I know, and I could be wrong, AMD does not yet have CPU threads but they have provided a way to detect them that I assume will work on future AMD processors which may have CPU threads.
In short here are the steps using the CPUID instruction:
Sounds difficult but here is a, hopefully, platform independent C++ program that does the trick:
#include <iostream> #include <string> using namespace std; void cpuID(unsigned i, unsigned regs[4]) { #ifdef _WIN32 __cpuid((int *)regs, (int)i); #else asm volatile ("cpuid" : "=a" (regs[0]), "=b" (regs[1]), "=c" (regs[2]), "=d" (regs[3]) : "a" (i), "c" (0)); // ECX is set to zero for CPUID function 4 #endif } int main(int argc, char *argv[]) { unsigned regs[4]; // Get vendor char vendor[12]; cpuID(0, regs); ((unsigned *)vendor)[0] = regs[1]; // EBX ((unsigned *)vendor)[1] = regs[3]; // EDX ((unsigned *)vendor)[2] = regs[2]; // ECX string cpuVendor = string(vendor, 12); // Get CPU features cpuID(1, regs); unsigned cpuFeatures = regs[3]; // EDX // Logical core count per CPU cpuID(1, regs); unsigned logical = (regs[1] >> 16) & 0xff; // EBX[23:16] cout << " logical cpus: " << logical << endl; unsigned cores = logical; if (cpuVendor == "GenuineIntel") { // Get DCP cache info cpuID(4, regs); cores = ((regs[0] >> 26) & 0x3f) + 1; // EAX[31:26] + 1 } else if (cpuVendor == "AuthenticAMD") { // Get NC: Number of CPU cores - 1 cpuID(0x80000008, regs); cores = ((unsigned)(regs[2] & 0xff)) + 1; // ECX[7:0] + 1 } cout << " cpu cores: " << cores << endl; // Detect hyper-threads bool hyperThreads = cpuFeatures & (1 << 28) && cores < logical; cout << "hyper-threads: " << (hyperThreads ? "true" : "false") << endl; return 0; }
I haven't actually tested this on Windows or OSX yet but it should work as the CPUID instruction is valid on i686 machines. Obviously, this wont work for PowerPC but then they don't have hyper-threads either.
Here is the output on a few different Intel machines:
Intel(R) Core(TM)2 Duo CPU T7500 @ 2.20GHz:
logical cpus: 2 cpu cores: 2 hyper-threads: false
Intel(R) Core(TM)2 Quad CPU Q8400 @ 2.66GHz:
logical cpus: 4 cpu cores: 4 hyper-threads: false
Intel(R) Xeon(R) CPU E5520 @ 2.27GHz (w/ x2 physical CPU packages):
logical cpus: 16 cpu cores: 8 hyper-threads: true
Intel(R) Pentium(R) 4 CPU 3.00GHz:
logical cpus: 2 cpu cores: 1 hyper-threads: true
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With