以编程方式查找一台机器上的内核数量
有没有一种方法可以确定一台机器在C / C ++中具有多less核心? 如果不存在这样的事情,那么每个平台(Windows / * nix / Mac)的确定呢?
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> = 10.5或iOS)
NSUInteger a = [[NSProcessInfo processInfo] processorCount]; NSUInteger b = [[NSProcessInfo processInfo] activeProcessorCount];
这个function是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内核和超线程单元的数量返回硬件能够并发执行的线程数。
许多平台(包括Visual Studio 2005)都支持OpenMP ,它提供了一个
int omp_get_num_procs();
函数返callback用时可用的处理器/内核的数量。
如果您具有汇编语言访问权限,则可以使用CPUID指令获取有关CPU的各种信息。 它可以在操作系统之间移植,但是您需要使用制造商特定的信息来确定如何查找内核数量。 下面是一个描述如何在英特尔芯片上实现的文档,本文的第11页介绍了AMD规范。
(几乎)c代码中的平台独立function
#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 }
在Linux上,您可以读取/ proc / cpuinfo文件并计算核心数。
请注意,“核心数量”可能不是特别有用的数字,您可能需要更多一些。 您如何计算multithreadingCPU,如Intel HT,IBM Power5和Power6,以及最着名的Sun的Niagara / UltraSparc T1和T2? 甚至更有趣的是,MIPS 1004k具有两级硬件线程(pipe理程序和用户级别)……更不用说当您进入pipe理程序支持的系统(硬件可能拥有数十个CPU但是您的特定操作系统)时会发生什么只看到几个。
你所希望的最好的就是告诉在你的本地操作系统分区中有多less个逻辑处理单元。 忘了看看真正的机器,除非你是一个pipe理程序。 这个规则今天唯一的例外是在x86的土地,但非虚拟机的末日来临… …
您可能无法以平台独立的方式获得它。 Windows你得到的处理器数量。
Win32系统信息
多一个Windows配方:使用系统范围的环境variablesNUMBER_OF_PROCESSORS
:
printf("%d\n", atoi(getenv("NUMBER_OF_PROCESSORS")));
Windows Server 2003和更高版本可让您利用GetLogicalProcessorInformation函数
与C ++无关,但在Linux上我通常这样做:
grep processor /proc/cpuinfo | wc -l
方便的脚本语言,如bash / perl / python / ruby。
hwloc(http://www.open-mpi.org/projects/hwloc/)值得一看。; 虽然需要将另一个库集成到代码中,但它可以提供有关处理器的所有信息(内核数量,拓扑结构等)
有关OS X的更多信息: sysconf(_SC_NPROCESSORS_ONLN)
仅适用于版本> = 10.5,而不是10.4。
另一种方法是可用于版本> = 10.2的HW_AVAILCPU/sysctl()
BSD代码。
在Linux上,我所知道的最好的编程方式就是使用
sysconf(_SC_NPROCESSORS_CONF)
要么
sysconf(_SC_NPROCESSORS_ONLN)
这些不是标准的,但在我的Linux手册页。
在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
OS Xselect:根据文档,基于[[NSProcessInfo processInfo] processorCount]前面所述的解决scheme仅在OS X 10.5.0上可用。 对于早期版本的OS X,使用Carbon函数MPProcessors()。
如果你是一个Cocoa程序员,不要被这个是Carbon的事实吓倒。 您只需要将Carbon框架添加到您的Xcode项目中,并且MPProcessors()将可用。
对于Win32:
GetSystemInfo()获取逻辑处理器的数量,使用GetLogicalProcessorInformationEx()获取物理处理器的数量。
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
的实现是恕我直言的(即“使用GetLogicalProcessorInformation
或GetLogicalProcessorInformationEx
”)。 相反,如果在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。
你也可以在.net中使用WMI,但是你依赖于wmi服务的运行等。有时它在本地工作,但是当在服务器上运行相同的代码时失败。 我认为这是一个命名空间问题,与您正在阅读的“名称”相关。
在Linux中,您可以检出dmesg并过滤ACPI初始化CPU的行,如下所示:
dmesg | grep 'ACPI: Processor
dmesg | grep 'ACPI: Processor
'
其他可能性是使用dmidecode来过滤处理器信息。