编程方式检测物理处理器/核心数或超线程活跃在Windows,Mac和Linux [英] Programatically detect number of physical processors/cores or if hyper-threading is active on Windows, Mac and Linux

查看:211
本文介绍了编程方式检测物理处理器/核心数或超线程活跃在Windows,Mac和Linux的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

为了使长话短说:为了使它以最高效率运行,我必须能够实例每个物理处理器/核心单线程。创建更多的线程之外还有物理处理器/内核降低我的程序的性能增色不少。我已经可以正确地检测正确的所有三个这些平台逻辑处理器/核的数量。为了能够检测物理处理器/核心正确我会,如果超踩的支持和积极的来检测。

因此​​,我的问题是,如果有一种方法来检测是否超线程支持和启用?如果是这样,究竟如何。


解决方案

编辑:这不再是100%正确的,由于英特尔正在进行befuddlement

我明白这个问题的方法是,你是问如何检测CPU内核的数量与CPU线程是由检测系统逻辑和物理内核的数量不同。 CPU内核往往不被考虑操作系统物理核心,除非他们有自己的包或死亡。因此,操作系统会报告一个Core 2 Duo处理器,例如,有1个物理和2个逻辑CPU和英特尔P4与超线程将完全相同的方式进行报道,尽管2超线程与2个CPU内核是一个非常不同的事情性能明智的。

我这个挣扎,直到我拼凑下面的解决方案,我相信为AMD和Intel处理器的作品。据我所知,我可能是错的,AMD还没有CPU线程,但他们提供了一个方法来检测他们,我相信会就可能会对CPU线程,AMD未来的处理器将工作。

在这里短暂使用CPUID指令的步骤:


  1. 使用检测CPU厂商的CPUID功能0

  2. 检查HTT CPU中28位来自CPUID功能1
  3. 功能EDX
  4. 从CPUID功能1
  5. 获取从EBX [23:16]逻辑核心数量
  6. 获取实际的非线程CPU核心数量

    1. 如果供应商=='GenuineIntel这是1加上从CPUID功能EAX [31:26] 4

    2. 如果供应商=='AuthenticAMD这是1加ECX [7:0]从CPUID功能0x80000008


听起来很困难,但这里是一个,希望独立于平台的C ++程序,它的伎俩:

 的#include<&iostream的GT;
#包括LT&;串GT;使用命名空间std;
CPUID无效(未签名的我,无符号暂存器[4]){
#IFDEF _WIN32
  __cpuid(为(int *)暂存器,(INT)一);#其他
  ASM挥发性
    (CPUID:=一个(暂存器[0]),= B(暂存器[1]),= C(暂存器[2]),= D(暂存器[3])
     :1(一),C(0));
  // ECX被设置为零CPUID功能4
#万一
}
INT主(INT ARGC,CHAR *的argv []){
  无符号暂存器[4];  //获取供应商
  焦炭供应商[12];
  CPUID(0,暂存器);
  ((无符号*)供应商)[0] =暂存器[1]; // EBX
  ((无符号*)供应商)[1] =暂存器[3]; // EDX
  ((无符号*)供应商)[2] =暂存器[2]; // ECX
  字符串cpuVendor =字符串(供应商,12);  //获取CPU特性
  CPUID(1,暂存器);
  无符号cpuFeatures =暂存器[3]; // EDX  每个CPU //逻辑核心数量
  CPUID(1,暂存器);
  无符号的逻辑=(暂存器[1]≥> 16)及0xFF的; // EBX [23:16]
  COUT<< 逻辑CPU:<<逻辑LT;< ENDL;
  无符号的内核=逻辑;  如果(cpuVendor ==GenuineIntel){
    //获取DCP缓存信息
    CPUID(4暂存器);
    芯=((暂存器[0]≥> 26)及0x3F的)+1; // EAX [31:26] + 1  }否则如果(cpuVendor ==AuthenticAMD){
    //获取NC:CPU核心数 - 1
    CPUID(0x80000008,暂存器);
    芯=((无符号)(暂存器[2]&放大器; 0xff的))+ 1; // ECX [7:0] +1
  }  COUT<< CPU内核:<<芯<< ENDL;  //检测超线程
  布尔超线程= cpuFeatures&安培; (1 <<;&下; 28)及与放大器;芯&LT;逻辑;  COUT&LT;&LT; 超线程:&LT;&LT; (超线程真:假)&LT;&LT; ENDL;  返回0;
}

我没有真正在Windows或OSX测试了这个尚未但它应该工作的CPUID指令是在i686机器有效。显然,为PowerPC这不会工作,但他们不具备超线程无论是。

下面是几个不同的Intel机器的输出:

英特尔(R)酷睿(TM)2双核T7500 CPU @ 2.20GHz:

 逻辑CPU:2
    CPU内核:2
超线程:假的

英特尔(R)酷睿(TM)2四核Q8400 CPU主频为2.66GHz @:

 逻辑CPU:4
    CPU内核:4
超线程:假的

英特尔(R)至强(R)CPU E5520 @ 2.27GHz(W / X2物理CPU包):

 逻辑CPU:16
    CPU内核:8
超线程:真

英特尔(R)奔腾(R)4 CPU 3.00GHz:

 逻辑CPU:2
    CPU内核:1
超线程:真

I have a multithreaded c++ application that runs on Windows, Mac and a few Linux flavours.

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 hyperthreading is supported AND ENABLED? If so, how exactly.

解决方案

EDIT: This is no longer 100% correct due to Intel's ongoing befuddlement.

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.

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.

In short here are the steps using the CPUID instruction:

  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. If vendor == 'GenuineIntel' this is 1 plus EAX[31:26] from CPUID function 4
    2. If vendor == 'AuthenticAMD' this is 1 plus ECX[7:0] from CPUID function 0x80000008

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

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.

Here is the output on a few different Intel machines:

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:

 logical cpus: 4
    cpu cores: 4
hyper-threads: false

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

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

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

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

这篇关于编程方式检测物理处理器/核心数或超线程活跃在Windows,Mac和Linux的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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