6

我正在尝试收集有关我的 CPU 的信息__cpuid()。虽然它在我的计算机上运行良好,但当我在同事的计算机上运行我的程序时,它检测到Intel Core2 Quad Q6600是超线程的,尽管根据 Intel 自己网站上的规范它不是。

__cpuid()还检测到错误数量的“逻辑内核”,如下所示:以 编程方式检测物理处理器/内核的数量,或者超线程是否在 Windows、Mac 和 Linux 上处于活动状态。它声称Intel Xeon E5520有 16 个逻辑内核和 8 个物理内核。

我尝试在我自己的计算机上运行在该线程中找到的代码,Intel i7 2600K给了我与 Xeon 相同的数字。

那么究竟有多可靠__cpuid()呢?根据我自己的经验,它似乎并不那么可靠。我有什么非常根本的错误吗?

4

2 回答 2

5

几乎可以肯定,处理器上的 [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 上的 Wikipedia 页面,我最近在努力理解这个问题后进行了更新,现在在“英特尔线程/核心和缓存拓扑”部分中有一个已解决的示例,用于枚举具有 APIC id 间隙的处理器上的拓扑,附加详细信息,包括如何确定 APIC id 的哪些位实际使用以及哪些是“死的”。

鉴于 Microsoft 当前在其 __cpuid() 页面上提供的代码示例,这与逻辑 CPU 计数返回 16 而不是 4基本上是相同的问题,因为它源于英特尔规范的相同解释错误。作为对 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 转储。

于 2014-07-11T13:50:00.807 回答
3

CPUID是可以信任的,你只需要正确使用它。在这种情况下,这意味着正确地枚举拓扑。你得到 16 个逻辑处理器,因为它得到的字段代表它可以支持的最大值,而不是实际有多少。为核心检索的值实际上是逻辑计数。

该主题中的代码非常基础,作为一个起点,在我的系统(i7 2720QM)上,我也记录了无效数据,但是使用我自己的代码根据英特尔 CPUID 映射检查拓扑,我得到了正确的结果。

于 2012-02-13T21:20:15.707 回答