有没有办法以独立于平台的方式确定机器有多少来自C / C ++的内核? 如果不存在这样的事情,那么每个平台确定它(Windows / * nix / Mac)呢?
如果您想使用它找出要启动的线程数,请使用NUMBER_OF_PROCESSORS作为主要衡量标准。 我把它作为练习留给你为什么这更好(如果人们会更多地使用它)然后使用硬件核心。 多少核心属于您的程序是一个环境问题!
请注意,std::thread::hardware_concurrency返回物理CPU核心数,但Linux中的nproc仅显示当前进程可以运行的CPU核心数,可以使用sched_setaffinity进行控制。 我还没有找到一种方法来从标准C ++中获取它,参见例如 在Python中:stackoverflow.com/questions/1006289/
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];
添加预处理程序指令,以便仅执行特定于操作系统的代码。
@mcandre:这是留给读者的练习。如果我正在实现,我可能会使用模板策略方法,其中策略是在预处理器指令中定义的。或者......你可以使用boost thread :: hardware_concurrency()。
原来这不适用于Centos或RHEL。
作为澄清的一点,Win32解决方案返回核心总数(要求的内容)而不是物理CPU总数。
Linux / Solaris / AIX方式也可以在FreeBSD上运行,至少从2006年开始。此外,这将使CPU在线返回,如果系统能够关闭一些,它们可能不会被计算在内。使用"_SC_NPROCESSORS_CONF"调用sysconf将返回配置的总CPU。
请注意,fbsd版本要简单得多 - 这是一个组合示例,因此看起来很复杂。
有几点需要注意。 OS X上不推荐使用HW_NCPU。在Windows GetSystemInfo上仅在系统具有32个或更少逻辑处理器时才有用,对于具有超过32个逻辑处理器的系统使用GetLogicalProcessorInformation。
@Eric据说它比这更糟糕,它实际上返回了逻辑核心的数量,所以如果你打开了超线程,它可能比你预期的要大。它不是很清楚,因为来自同一API的两个不同版本的微软文档说了两个不同的东西(一个用"物理"表示,另一个用"逻辑"表示。)
@Trejkaz文档清楚地说"逻辑" - 它总是计算HT核心,"物理"一词总是指BIOS / UEFI报告的核心,因为核心也可以被模拟/虚拟化。例如,您可以使用GetLogicalProcessorInformation等功能区分HT /非HT核心。注意:HT!=仿真或虚拟化,这是一个很大的区别,HT是硬件优化,可以这么说
@Toby Speight,您在编辑中引入了代码中的错误。 sizeof numCPU不是std::size_t*。
@specializt是的,如果你忽略了文档中一个页面的位置,将其称为"物理",另一个将其称为"逻辑",则其含义非常清楚。或者,如果在我发表评论和你做出回复之间纠正了文档,那么这也可以解决问题。
@Trejkaz我希望看到doc - MSDN通常没有这样的重大问题,我非常怀疑他们实际上是在混淆它,实际上他们甚至提到了这些术语之间的区别和联系:"有关物理处理器共享的信息通过逻辑处理器,调用GetLogicalProcessorInformationEx,并将RelationshipType参数设置为RelationProcessorPackage(3)。"
@specializt是的,太糟糕了我当时没有联系它。即使我搜索它,我现在也不太可能找到它。 :/
因为它不存在
添加所需的标题(例如#include for linux)将使答案非常适合未来的搜索者。
注意std::thread::hardware_concurrency实现不同; Visual Studio考虑了亲和性(如果进程限制为一个核心等,则返回1),而g ++则不然。
如果您使用的是现代Windows,并且无论处理器组如何都需要所有处理器(例如,您正在使用超过64个处理器的系统)并且您的目标是Windows 7/2008 R2或更高版本,则可以使用GetMaximumProcessorCount(ALL_PROCESSOR_GROUPS)检索完整的计数。有关示例,请参阅github.com/python/cpython/commit/。
此功能是C ++ 11标准的一部分。
#include
unsigned int nthreads = std::thread::hardware_concurrency();
对于较旧的编译器,您可以使用Boost.Thread库。
#include
unsigned int nthreads = boost::thread::hardware_concurrency();
在任何一种情况下,hardware_concurrency()都会根据CPU内核和超线程单元的数量返回硬件能够并发执行的线程数。
借调......将使用上面的示例代码和一些预处理器宏来公开单个函数,但是我已经完成了艰苦的工作。
对于win32,它是对GetSystemInfo的调用。 (截至升级版本1.41.0)是否捕获所有信息以确定有效的工作线程数量?是否需要同时考虑核心数量和超线程? unsigned thread :: hardware_concurrency(){SYSTEM_INFO info = {0};的GetSystemInfo(信息); return info.dwNumberOfProcessors; }
根据MSDN,GetSystemInfo()返回dwNumberOfProcessors中"物理处理器"的数量,但它没有定义它的含义。 Boost文档似乎声称它包含超线程单元。
有关超线程,请参阅stackoverflow.com/questions/642348/
许多平台(包括Visual Studio 2005)都支持OpenMP,它提供了一个
int omp_get_num_procs();
返回调用时可用的处理器/核心数的函数。
因为这是一个错误的答案。从gcc.gnu.org/bugzilla/show_bug.cgi?id=37586"omp_get_num_procs()将仅返回小于在线系统CPU数量的数字,如果使用GOMP_CPU_AFFINITY env var,或者调用进程和/或线程有CPU亲和力限于CPU的子集"。因此,如果您之前调用例如sched_setaffinity,则无效。
此函数返回调用进程可用的CPU数。这不是最常见的用例吗?如果您无法在代码中利用它们,那么CPU硬件核心的实际数量与您无关。
@EvanTeran除了问题的目的之外,它当然是有用的。例如,为了设置线程亲和性。比如说,我想在我的机器上运行绑定到最后四个CPU核心的4个线程,而不是四个第一个核心。此外,除了OpenMP之外,还有其他方法可以并行化代码。我可能想自己生成pthreads。这些肯定是可用的,不受OpenMP环境变量的限制。
这将返回逻辑CPU的数量,而不是核心(物理CPU)。
如果您具有汇编语言访问权限,则可以使用CPUID指令获取有关CPU的各种信息。它可以在操作系统之间移植,但您需要使用制造商特定的信息来确定如何查找核心数。这是一个描述如何在英特尔芯片上执行此操作的文档,本文的第11页描述了AMD规范。
它可能已被低估,因为该问题被标记为C ++,并且此答案不适用于在非x86体系结构(ARM,PPC等)上运行C ++的系统。我不是说这是一个很好的理由拒绝回答,只是一种可能性。
仅供参考......两个链接现在都被打破了......
感谢单挑,Homer6。我已经更新了两个链接。
如果您使用CPUID检测Intel处理器上的HyperThreading,则此方法的一个缺陷就是如此。我在我的笔记本电脑上遇到了这个问题:虽然我放入机器的CPU支持HyperThreading(当然,报告它通过CPUID报告),但BIOS却没有。因此,您不应仅仅尝试从CPUID读取中使用HT功能。由于您无法查询BIOS有关HT支持的信息(我没见过),因此应该查询操作系统以获取逻辑处理器数量。
(几乎)c-code中的平台无关功能
#ifdef _WIN32
#include
#elif MACOS
#include
#include
#else
#include
#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
}
在OS X源上似乎不推荐使用HW_NCPU
在Linux上,您可以读取/ proc / cpuinfo文件并计算内核。
除此之外,还将超线程或其他SMT解决方案视为更多内核......
jakobengblom2:那是/ / / /怎么样?
@Arafangion:超线程并不是真正的并行执行,它是一种减少上下文切换开销的技术。超线程cpu一次只能执行一个线程,但它可以同时存储两个线程的架构状态(寄存器值等)。性能特征与具有两个核心非常不同。
@Wim:这不完全正确。具有超线程的CPU通常具有多个ALU,并且每个周期可以分派多个指令。如果由于数据依赖性和停顿,并非所有ALU都可以由一个线程保持忙,那么这些ALU将用于同时执行第二个硬件线程。
请注意,"核心数"可能不是特别有用的数字,您可能需要更多地限定它。您想如何计算多线程CPU,例如Intel HT,IBM Power5和Power6,以及最着名的Sun的Niagara / UltraSparc T1和T2?或者更有趣的是,MIPS 1004k具有两级硬件线程(管理员和用户级)...更不用说当你进入虚拟机管理程序支持的系统时会发生什么,其中硬件可能有几十个CPU而你的特定操作系统只看到一些。
您可以期望的最好的方法是告诉您在本地操作系统分区中拥有的逻辑处理单元的数量。除非你是一个虚拟机管理程序,否则忘了看真机。今天这个规则的唯一例外是在x86领域,但非虚拟机的终结正在快速发展......
您可能无法以独立于平台的方式获取它。 Windows获得多个处理器。
Win32系统信息
Carefull:超线程处理器说有两个。所以你还需要看看处理器是否具有超线程能力。
还有一个Windows配方:使用系统范围的环境变量NUMBER_OF_PROCESSORS:
printf("%d
", atoi(getenv("NUMBER_OF_PROCESSORS")));
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。
谢谢! 我正在寻找这个,因为GetLogicalProcessorInformation没有使用我使用的各种缓冲区大小。 超过满意!^^
@KeyWeeUsr感谢Windows编程有点远非琐碎和逻辑。 同时,我使用稍微更新的C ++ 17版本,根据静态分析器PVS-Studio对于某些size_t强制转换也更正确。 (虽然,msvc ++不会在W4上抱怨。)
有关OS X的更多信息:sysconf(_SC_NPROCESSORS_ONLN)仅适用于版本> = 10.5,而不是10.4。
另一种方法是HW_AVAILCPU/sysctl() BSD代码,可在版本> = 10.2时使用。
Windows Server 2003及更高版本允许您利用GetLogicalProcessorInformation函数
http://msdn.microsoft.com/en-us/library/ms683194.aspx
与C ++无关,但在Linux上我通常会这样做:
grep processor /proc/cpuinfo | wc -l
方便脚本语言,如bash / perl / python / ruby??。
对于python:import multiprocessing print multiprocessing.cpu_count()
已经很长时间了,但grep有-c标志来计算条目!
hwloc(http://www.open-mpi.org/projects/hwloc/)值得一看。虽然需要在代码中集成另一个库,但它可以提供有关处理器的所有信息(内核数量,拓扑结构等)
在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
#include
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
", procCount);
return 0;
}
使用/proc/cpuinfo:
#include
#include
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
", procCount);
return 0;
}
shell中使用grep的方法相同:
grep -c ^processor /proc/cpuinfo
要么
grep -c ^cpu /proc/stat # subtract 1 from the result
OS X替代方案:根据文档,前面描述的基于[[NSProcessInfo processInfo] processorCount]的解决方案仅适用于OS X 10.5.0。对于早期版本的OS X,请使用Carbon函数MPProcessors()。
如果你是一个可可程序员,不要因为这是碳而被吓坏了。您只需要将Carbon框架添加到Xcode项目中,并且MPProcessors()将可用。
在Linux上,据我所知,最好的编程方式是使用
sysconf(_SC_NPROCESSORS_CONF)
要么
sysconf(_SC_NPROCESSORS_ONLN)
这些不是标准的,但是在我的Linux手册页中。
对于Win32:
虽然GetSystemInfo()可以获得逻辑处理器的数量,但请使用
GetLogicalProcessorInformationEx()
获得物理处理器的数量。
您也可以在.net中使用WMI,但是您依赖于运行的wmi服务
有时它在本地工作,但在服务器上运行相同的代码时失败。
我认为这是一个命名空间问题,与您正在阅读其值的"名称"相关。
在Linux中,您可以签出dmesg并过滤ACPI初始化CPU的行,如:
dmesg | grep 'ACPI: Processor"
其他可能性是使用dmidecode过滤掉处理器信息。
在我的电脑上不起作用