以编程方式查找计算机上的内核数

时间:2020-03-06 14:53:34  来源:igfitidea点击:

有没有一种方法可以以平台无关的方式确定C / C ++中一台计算机有多少个内核?如果不存在这样的东西,那么如何根据平台确定它(Windows / * nix / Mac)?

解决方案

Windows Server 2003和更高版本允许我们利用GetLogicalProcessorInformation函数

http://msdn.microsoft.com/en-us/library/ms683194.aspx

在Linux上,我们可以读取/ proc / cpuinfo文件并计算内核数。

我们可能将无法以独立于平台的方式获得它。在Windows中,我们可以获得处理器数量。

Win32系统信息

此功能是C ++ 11标准的一部分。

#include <thread>

unsigned int nthreads = std::thread::hardware_concurrency();

对于较旧的编译器,可以使用Boost.Thread库。

#include <boost/thread.hpp>

unsigned int nthreads = boost::thread::hardware_concurrency();

无论哪种情况," hardware_concurrency()"都会根据CPU内核和超线程单元的数量返回硬件能够同时执行的线程数。

据我所知,在Linux上,最好的编程方式是使用

sysconf(_SC_NPROCESSORS_CONF)

或者

sysconf(_SC_NPROCESSORS_ONLN)

这些不是标准的,但是在我的Linux手册页中。

如果我们具有汇编语言访问权限,则可以使用CPUID指令来获取有关CPU的各种信息。尽管我们需要使用制造商特定的信息来确定如何找到内核数量,但是它可以在操作系统之间移植。这是描述如何在Intel芯片上执行此操作的文档,该文档的第11页介绍了AMD规范。

//may return 0 when not able to detect
unsigned concurentThreadsSupported = std::thread::hardware_concurrency();

参考:std :: thread :: hardware_concurrency

在C ++ 11之前的C ++中,没有可移植的方法。相反,我们将需要使用以下一种或者多种方法(由相应的#ifdef行保护):

  • Win32的
SYSTEM_INFO sysinfo;
GetSystemInfo(&sysinfo);
int numCPU = sysinfo.dwNumberOfProcessors;
  • Linux,Solaris,AIX和Mac OS X> = 10.4(即从Tiger起)
int numCPU = sysconf(_SC_NPROCESSORS_ONLN);
  • FreeBSD,MacOS X,NetBSD,OpenBSD等
int mib[4];
int numCPU;
std::size_t len = sizeof(numCPU); 

/* set the mib for hw.ncpu */
mib[0] = CTL_HW;
mib[1] = HW_AVAILCPU;  // alternatively, try HW_NCPU;

/* get the number of CPUs from the system */
sysctl(mib, 2, &numCPU, &len, NULL, 0);

if (numCPU < 1) 
{
    mib[1] = HW_NCPU;
    sysctl(mib, 2, &numCPU, &len, NULL, 0);
    if (numCPU < 1)
        numCPU = 1;
}
  • 惠普
int numCPU = mpctl(MPC_GETNUMSPUS, NULL, NULL);
  • 虹膜
int numCPU = sysconf(_SC_NPROC_ONLN);
  • Objective-C(Mac OS X> = 10.5或者iOS)
NSUInteger a = [[NSProcessInfo processInfo] processorCount];
NSUInteger b = [[NSProcessInfo processInfo] activeProcessorCount];

请注意,"核心数"可能不是一个特别有用的数字,我们可能需要对其进行更多限定。我们想如何计算多线程CPU,例如Intel HT,IBM Power5和Power6,以及最著名的Sun的Niagara / UltraSparc T1和T2?甚至更有趣的是,具有两个级别的硬件线程的MIPS 1004k(管理程序和用户级别)...更不用说当我们进入虚拟机管理程序支持的系统时,硬件可能有数十个CPU但特定操作系统只看到一些。

最好的希望是告诉我们本地OS分区中逻辑处理单元的数量。除非我们是虚拟机监控程序,否则不要再看真实的机器了。今天,此规则的唯一例外是在x86领域,但非虚拟机的终结日趋迅速。

许多平台(包括Visual Studio 2005)都支持OpenMP,并且它提供了

int omp_get_num_procs();

该函数返回调用时可用的处理器/内核数。

Windows的另一个秘诀:使用系统范围的环境变量NUMBER_OF_PROCESSORS

printf("%d\n", atoi(getenv("NUMBER_OF_PROCESSORS")));

我们也可以在.net中使用WMI,但是我们依赖于运行的WMI服务
等等。有时它在本地运行,但是当在服务器上运行相同的代码时失败。
我认为这是一个名称空间问题,与我们正在读取其值的"名称"有关。

在Linux中,我们可以检出dmesg并过滤ACPI初始化CPU的行,例如:

dmesg | grep'ACPI:Processor'

其他可能性是使用dmidecode过滤掉处理器信息。

OS X替代品:根据文档,先前基于[[NSProcessInfo processInfo] processorCount]描述的解决方案仅在OS X 10.5.0上可用。对于OS X的早期版本,请使用Carbon函数MPProcessors()。

如果我们是Cocoa程序员,请不要因为这是Carbon而感到惊讶。我们只需要向Xcode项目中添加Carbon框架,即可使用MPProcessors()。

(几乎)C代码中与平台无关的功能

#ifdef _WIN32
#include <windows.h>
#elif MACOS
#include <sys/param.h>
#include <sys/sysctl.h>
#else
#include <unistd.h>
#endif

int getNumCores() {
#ifdef WIN32
    SYSTEM_INFO sysinfo;
    GetSystemInfo(&sysinfo);
    return sysinfo.dwNumberOfProcessors;
#elif MACOS
    int nm[2];
    size_t len = 4;
    uint32_t count;

    nm[0] = CTL_HW; nm[1] = HW_AVAILCPU;
    sysctl(nm, 2, &count, &len, NULL, 0);

    if(count < 1) {
        nm[1] = HW_NCPU;
        sysctl(nm, 2, &count, &len, NULL, 0);
        if(count < 1) { count = 1; }
    }
    return count;
#else
    return sysconf(_SC_NPROCESSORS_ONLN);
#endif
}