我正在尝试收集有关我的CPU的信息__cpuid().虽然它在我的计算机上运行正常,但当我在我的同事的计算机上运行我的程序时,它检测到英特尔酷睿2四核Q6600是超线程的,但根据英特尔自己网站上的规格,它不是.
__cpuid()还可以检测错误数量的"逻辑核心",如下所示:以
编程方式检测物理处理器/核心的数量,或者在Windows,Mac和Linux上是否激活超线程.声称英特尔至强E5520拥有16个逻辑核心和8个物理核心.
我尝试在我自己的计算机上运行该线程中的代码,Intel i7 2600K给我的数字与Xeon相同.
那__cpuid()真的可靠吗?根据我自己的经验,它似乎并不那么可靠.我有一些非常根本的错误吗?
几乎可以肯定,您的处理器上的 [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 转储。