如何在 Windows、Mac 和 Linux 上检测物理处理器/内核的数量 [英] How to Detect the Number of Physical Processors / Cores on Windows, Mac and Linux

查看:23
本文介绍了如何在 Windows、Mac 和 Linux 上检测物理处理器/内核的数量的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个多线程 C++ 应用程序,可以在 Windows、Mac 和一些 Linux 版本上运行.

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.

推荐答案

由于英特尔的持续困惑,这不再是 100% 正确的.

我理解这个问题的方式是,您问的是如何检测 CPU 内核数与 CPU 线程数,这与检测系统中的逻辑和物理内核数不同.CPU 内核通常不被操作系统视为物理内核,除非它们有自己的封装或芯片.因此,操作系统将报告 Core 2 Duo,例如,具有 1 个物理 CPU 和 2 个逻辑 CPU,而具有超线程的 Intel P4 将以完全相同的方式报告,即使 2 个超线程与 2 个 CPU 内核非常相似不同的事情表现明智.

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.

我一直在努力解决这个问题,直到我拼凑出下面的解决方案,我相信它适用于 AMD 和 Intel 处理器.据我所知,我可能是错的,AMD 还没有 CPU 线程,但他们提供了一种检测它们的方法,我认为这些方法将适用于未来可能具有 CPU 线程的 AMD 处理器.

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.

简而言之,这里是使用 CPUID 指令的步骤:

In short here are the steps using the CPUID instruction:

  1. 使用 CPUID 函数 0 检测 CPU 供应商
  2. 从 CPUID 函数 1 检查 CPU 特性 EDX 中的 HTT 位 28
  3. 从 CPUID 函数 1 的 EBX[23:16] 中获取逻辑核心数
  4. 获取实际的非线程 CPU 核心数
  1. Detect CPU vendor using CPUID function 0
  2. Check for HTT bit 28 in CPU features EDX from CPUID function 1
  3. Get the logical core count from EBX[23:16] from CPUID function 1
  4. Get actual non-threaded CPU core count
  1. 如果 vendor == 'GenuineIntel' 这是 1 加上来自 CPUID 函数 4 的 EAX[31:26]
  2. 如果 vendor == 'AuthenticAMD' 这是 1 加上来自 CPUID 函数 0x80000008 的 ECX[7:0]

听起来很困难,但这里有一个希望能够做到这一点的独立于平台的 C++ 程序:

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;
}

我还没有在 Windows 或 OSX 上实际测试过这个,但它应该可以工作,因为 CPUID 指令在 i686 机器上有效.显然,这不适用于 PowerPC,但它们也没有超线程.

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.

以下是几台不同的 Intel 机器上的输出:

Here is the output on a few different Intel machines:

Intel(R) Core(TM)2 Duo CPU T7500 @ 2.20GHz:

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:

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(带 x2 物理 CPU 包):

Intel(R) Xeon(R) CPU E5520 @ 2.27GHz (w/ x2 physical CPU packages):

 logical cpus: 16
    cpu cores: 8
hyper-threads: true

英特尔(R) Pentium(R) 4 CPU 3.00GHz:

Intel(R) Pentium(R) 4 CPU 3.00GHz:

 logical cpus: 2
    cpu cores: 1
hyper-threads: true

这篇关于如何在 Windows、Mac 和 Linux 上检测物理处理器/内核的数量的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆