I'm trying to gather information about my CPU with __cpuid()
. Though it is getting it right on my computer, when I run my program on my colleague's computer it is detecting the Intel Core2 Quad Q6600 to be hyper-threaded, though according to the specifications on Intel's own site it isn't.
__cpuid()
is also detecting the wrong amount of "logical cores" as can be shown here:
Programmatically detect number of physical processors/cores or if hyper-threading is active on Windows, Mac and Linux. Where it claims that the Intel Xeon E5520 has 16 logical cores and 8 physical.
I tried running the code found in that thread on my own computer, a Intel i7 2600K giving me the same numbers as for the Xeon.
So how reliable is __cpuid()
really? From my own experience it doesn't seem to be that reliable. Have I got something very fundamental wrong?
In the x86 architecture, the CPUID instruction (identified by a CPUID opcode) is a processor supplementary instruction (its name derived from CPU IDentification) allowing software to discover details of the processor. It was introduced by Intel in 1993 with the launch of the Pentium and SL-enhanced 486 processors.
CPU-Z is a freeware that gathers information on some of the main devices of your system : Processor name and number, codename, process, package, cache levels. Mainboard and chipset. Memory type, size, timings, and module specifications (SPD).
There is almost certainly a gap in the [x2]APIC ids on your processor, meaning that some value of the APIC ids don't map to any logical processors. You should use the 0xB leaf of cpuid to find out. You can look at the reference Intel code and algorithm (https://software.intel.com/en-us/articles/intel-64-architecture-processor-topology-enumeration/) for the steps, but it broils down to calling with EAX=0xB, ECX=0 and obtaining in EBX the number of logical processors (threads) per core and then calling cpuid again with EAX=0xB, ECX=1 and getting in EBX the number of logical processors per processor package.
The old method of using leaf 0x1 cannot account for APIC id gaps. Alas that's the sample code still given on the MSDN Visual C++ 2013 reference page (http://msdn.microsoft.com/en-us/library/hskdteyh.aspx), and it is incorrect for processors made in 2010 and thereafter, as you found out whether by using the code from MSDN or similarly incorrect code from elsewhere. The Wikipedia page on cpuid, which I've recently updated after struggling myself to understand the issue, now has a worked out example in the section on "Intel thread/core and cache topology" for enumerating topology on a processor with APIC id gaps, with additional details, including how to determine which bits of the APIC ids are actually used and which are "dead".
Given the code sample currently offered by Microsoft on their __cpuid() page, this is basically the same question as Logical CPU count return 16 instead of 4 because it's rooted in the same interpretation error of the Intel specs. As an explanation for MSDN's poor show, the code they offer worked okay before 2010 or so; Intel used to provide a similar method before the x2APIC was introduced as you can see in this old video/article: https://software.intel.com/en-us/articles/hyper-threading-technology-and-multi-core-processor-detection If you look at the various versions of the MSDN page on __cpuid, their code sample has basically remained the same since 2008...
As for the single hyperthreaded detection bit, that is a longer story, already answered by me at Why does Hyper-threading get reported as supported on processors without it?. The nutshell is that that rather legacy bit tells you if the processor package supports more than one logical processor, be it via hypethreading or multi-core technology. The name of the bit is thus rather misleading.
Also, I suggest changing the title of you question to "Using CPUID to detect CPU topology, reliable solution?" because I've found your question completely by accident. I was searching for Sandy Bridge cpuid dumps on google when I found your question.
CPUID can be trusted, you just need to use it correctly. in this case, it means enumerating the topology correctly. you get 16 logical processors because the field its gotten from represents the maximum it can support, not how many there actually are. the value retrieved for cores is actually the logical count.
the code in the topic is very basic and meant as a starting point, on my system (i7 2720QM) i also record invalid data, but using my own code that checks the topology as per Intel CPUID mappings, I get correct results.
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