使用CPUID检测CPU规格,可靠的解决方案吗?
我正在尝试使用 __cpuid()
收集有关我的 CPU 的信息。虽然它在我的计算机上运行正常,但当我在同事的计算机上运行程序时,它会检测到 Intel Core2 Quad Q6600 为超线程,尽管根据英特尔自己网站上的规格,事实并非如此。
__cpuid()
还检测到错误数量的“逻辑核心”,如下所示: 以编程方式检测物理处理器/核心的数量,或者如果超线程在 Windows、Mac 和 Linux 上处于活动状态。它声称 Intel Xeon E5520 拥有 16 个逻辑核心和 8 个物理核心。
我尝试在自己的计算机上运行该线程中找到的代码,Intel i7 2600K 给我的数字与 Xeon 相同。
那么__cpuid()
到底有多可靠呢?以我自己的经验来看,似乎不太靠谱。我是否犯了一些非常根本的错误?
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?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
几乎可以肯定,您的处理器上的 [x2]APIC id 中存在间隙,这意味着 APIC id 的某些值不会映射到任何逻辑处理器。您应该使用 cpuid 的 0xB 叶子来查找。您可以查看参考英特尔代码和算法(https://software.intel.com/en-us/articles/intel-64-architecture-processor-topology-enumeration/)了解步骤,但归结为调用EAX=0xB,ECX=0,并在 EBX 中获取每个核心的逻辑处理器(线程)数量,然后使用 EAX=0xB,ECX=1 再次调用 cpuid,并在 EBX 中获取每个处理器包的逻辑处理器数量。
使用叶 0x1 的旧方法无法解决 APIC id 间隙。唉,MSDN Visual C++ 2013 参考页上仍然给出了示例代码 (http:// /msdn.microsoft.com/en-us/library/hskdteyh.aspx),并且对于 2010 年及之后生产的处理器来说是不正确的,正如您所发现的,无论是使用 MSDN 中的代码还是其他地方类似的错误代码。关于 cpuid 的维基百科页面,我最近在努力理解这个问题后进行了更新,现在在“Intel 线程/核心和缓存拓扑”部分中提供了一个示例,用于枚举具有 APIC id 间隙的处理器上的拓扑,以及其他详细信息,包括如何确定 APIC id 的哪些位已实际使用以及哪些位“已失效”。
鉴于 Microsoft 当前在其 __cpuid() 页面上提供的代码示例,这基本上与 逻辑 CPU 计数返回 16 而不是 4,因为它源于与 Intel 规范相同的解释错误。作为对 MSDN 糟糕表现的解释,他们提供的代码在 2010 年左右之前运行良好;在引入 x2APIC 之前,英特尔曾经提供过类似的方法,如您在这个旧视频/文章中看到的:https://software.intel.com/en-us/articles/hyper-threading-technology-and-multi-core-processor-detection 如果你看在 __cpuid 上的 MSDN 页面的各个版本中,自 2008 年以来,它们的代码示例基本上保持不变...
至于单个超线程检测位,这是一个较长的故事,我已经在 为什么超线程被报告为受支持没有它的处理器?。简而言之,这一相当传统的位会告诉您处理器包是否支持多个逻辑处理器,无论是通过超线程还是多核技术。因此,该位的名称相当具有误导性。
另外,我建议将您的问题标题更改为“使用 CPUID 检测 CPU 拓扑,可靠的解决方案吗?”因为我完全偶然发现了你的问题。当我发现你的问题时,我正在谷歌上搜索 Sandy Bridge cpuid 转储。
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是可以信任的,你只需要正确使用它即可。在这种情况下,这意味着正确枚举拓扑。您将获得 16 个逻辑处理器,因为获取的字段表示它可以支持的最大值,而不是实际数量。为核心检索的值实际上是逻辑计数。
本主题中的代码非常基础,旨在作为起点,在我的系统 (i7 2720QM) 上,我还记录了无效数据,但使用我自己的代码根据 Intel CPUID 映射检查拓扑,我得到了正确的结果。
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.