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

时间:2008-09-29 19:51:46

标签: c++ c

有没有办法以独立于平台的方式确定一台机器有多少来自C / C ++的内核?如果不存在这样的事情,那么每个平台确定它(Windows / * nix / Mac)呢?

20 个答案:

答案 0 :(得分:662)

C ++ 11

//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;
    }
    
  • HPUX

    int numCPU = mpctl(MPC_GETNUMSPUS, NULL, NULL);
    
  • IRIX

    int numCPU = sysconf(_SC_NPROC_ONLN);
    
  • Objective-C(Mac OS X&gt; = 10.5或iOS)

    NSUInteger a = [[NSProcessInfo processInfo] processorCount];
    NSUInteger b = [[NSProcessInfo processInfo] activeProcessorCount];
    

答案 1 :(得分:196)

此功能是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内核和超线程单元的数量返回硬件能够并发执行的线程数。

答案 2 :(得分:55)

许多平台(包括Visual Studio 2005)都支持

OpenMP,它提供了

int omp_get_num_procs();

返回呼叫时可用处理器/核心数的函数。

答案 3 :(得分:37)

如果您具有汇编语言访问权限,则可以使用CPUID指令获取有关CPU的各种信息。它可以在操作系统之间移植,但您需要使用制造商特定的信息来确定如何查找核心数。这里是a document that describes how to do it on Intel chipsthis one的第11页描述了AMD规范。

答案 4 :(得分:31)

(几乎)c-code中的平台无关功能

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

答案 5 :(得分:15)

在Linux上,您可以读取/ proc / cpuinfo文件并计算核心数。

答案 6 :(得分:10)

请注意,“核心数”可能不是特别有用的数字,您可能需要更多地限定它。您想如何计算多线程CPU,例如Intel HT,IBM Power5和Power6,以及最着名的Sun的Niagara / UltraSparc T1和T2?或者更有趣的是,MIPS 1004k具有两级硬件线程(管理员和用户级)...更不用说当你进入虚拟机管理程序支持的系统时会发生什么,其中硬件可能有几十个CPU而你的特定操作系统只看到一些。

您可以期望的最好的方法是告诉您在本地操作系统分区中拥有的逻辑处理单元的数量。除非你是一个虚拟机管理程序,否则忘了看真机。今天这个规则的唯一例外是x86版本,但非虚拟机的结束正在快速发展......

答案 7 :(得分:7)

您可能无法以独立于平台的方式获取它。 Windows获得了多个处理器。

Win32 System Information

答案 8 :(得分:7)

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

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

答案 9 :(得分:5)

Windows(x64和Win32)和C ++ 11

共享单个处理器核心的逻辑处理器组数。(使用GetLogicalProcessorInformationEx,另请参阅GetLogicalProcessorInformation

size_t NumberOfPhysicalCores() noexcept {

    DWORD length = 0;
    const BOOL result_first = GetLogicalProcessorInformationEx(RelationProcessorCore, nullptr, &length);

    Assert(result_first == FALSE);
    Assert(GetLastError() == ERROR_INSUFFICIENT_BUFFER);

    std::unique_ptr< uint8_t[] > buffer(new uint8_t[length]);
    const PSYSTEM_LOGICAL_PROCESSOR_INFORMATION_EX info = 
            reinterpret_cast< PSYSTEM_LOGICAL_PROCESSOR_INFORMATION_EX >(buffer.get());

    const BOOL result_second = GetLogicalProcessorInformationEx(RelationProcessorCore, info, &length);

    Assert(result_second == TRUE);

    size_t nb_physical_cores = 0;
    size_t offset = 0;
    do {
        const PSYSTEM_LOGICAL_PROCESSOR_INFORMATION_EX current_info =
            reinterpret_cast< PSYSTEM_LOGICAL_PROCESSOR_INFORMATION_EX >(buffer.get() + offset);
        offset += current_info->Size;
        ++nb_physical_cores;
    } while (offset < length);

    return nb_physical_cores;
}

请注意NumberOfPhysicalCores的实施是恕我直言,远非琐碎(即&#34;使用GetLogicalProcessorInformationGetLogicalProcessorInformationEx&#34;)。相反,如果在MSDN上读取文档(明确存在于GetLogicalProcessorInformation并隐式存在于GetLogicalProcessorInformationEx),则相当微妙。

逻辑处理器的数量。(使用GetSystemInfo

size_t NumberOfSystemCores() noexcept {
    SYSTEM_INFO system_info;
    ZeroMemory(&system_info, sizeof(system_info));

    GetSystemInfo(&system_info);

    return static_cast< size_t >(system_info.dwNumberOfProcessors);
}

请注意,这两种方法都可以轻松转换为C / C ++ 98 / C ++ 03。

答案 10 :(得分:5)

有关OS X的更多信息:sysconf(_SC_NPROCESSORS_ONLN)仅适用于版本&gt; = 10.5,而不是10.4。

另一种选择是HW_AVAILCPU/sysctl() BSD代码,可在版本&gt; = 10.2上使用。

答案 11 :(得分:4)

与C ++无关,但在Linux上我通常会这样做:

grep processor /proc/cpuinfo | wc -l

方便脚本语言,如bash / perl / python / ruby​​。

答案 12 :(得分:4)

Windows Server 2003及更高版本允许您利用GetLogicalProcessorInformation函数

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

答案 13 :(得分:3)

hwloc(http://www.open-mpi.org/projects/hwloc/)值得一看。虽然需要在代码中集成另一个库,但它可以提供有关处理器的所有信息(内核数量,拓扑结构等)。

答案 14 :(得分:3)

在Linux上,使用_SC_NPROCESSORS_ONLN可能不安全,因为它不是POSIX标准的一部分,sysconf手册也是如此。因此,_SC_NPROCESSORS_ONLN可能不存在的可能性:

 These values also exist, but may not be standard.

     [...]     

     - _SC_NPROCESSORS_CONF
              The number of processors configured.   
     - _SC_NPROCESSORS_ONLN
              The number of processors currently online (available).

一种简单的方法是阅读/proc/stat/proc/cpuinfo并计算它们:

#include<unistd.h>
#include<stdio.h>

int main(void)
{
char str[256];
int procCount = -1; // to offset for the first entry
FILE *fp;

if( (fp = fopen("/proc/stat", "r")) )
{
  while(fgets(str, sizeof str, fp))
  if( !memcmp(str, "cpu", 3) ) procCount++;
}

if ( procCount == -1) 
{ 
printf("Unable to get proc count. Defaulting to 2");
procCount=2;
}

printf("Proc Count:%d\n", procCount);
return 0;
}

使用/proc/cpuinfo

#include<unistd.h>
#include<stdio.h>

int main(void)
{
char str[256];
int procCount = 0;
FILE *fp;

if( (fp = fopen("/proc/cpuinfo", "r")) )
{
  while(fgets(str, sizeof str, fp))
  if( !memcmp(str, "processor", 9) ) procCount++;
}

if ( !procCount ) 
{ 
printf("Unable to get proc count. Defaulting to 2");
procCount=2;
}

printf("Proc Count:%d\n", procCount);
return 0;
}

使用grep在shell中使用相同的方法:

grep -c ^processor /proc/cpuinfo

或者

grep -c ^cpu /proc/stat # subtract 1 from the result

答案 15 :(得分:2)

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

如果你是Cocoa程序员,不要因为这是Carbon而吓到了。您只需要将Carbon框架添加到Xcode项目中,并且MPProcessors()将可用。

答案 16 :(得分:2)

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

sysconf(_SC_NPROCESSORS_CONF)

sysconf(_SC_NPROCESSORS_ONLN)

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

答案 17 :(得分:2)

对于Win32:

虽然GetSystemInfo()可以获得逻辑处理器的数量,但请使用 GetLogicalProcessorInformationEx()   获取物理处理器的数量。

答案 18 :(得分:-2)

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

答案 19 :(得分:-3)

在Linux中,您可以签出dmesg并过滤ACPI初始化CPU的行,如:

dmesg | grep 'ACPI: Processor

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