Есть ли способ определить, сколько ядер на машине C/С++ не зависит от платформы? Если такой вещи не существует, как определить ее на платформе (Windows/* nix/Mac)?
//may return 0 when not able to detect
unsigned concurentThreadsSupported = std::thread::hardware_concurrency();
Ссылка: std:: thread:: hardware_concurrency
В С++ до С++ 11 нет портативного способа. Вместо этого вам нужно будет использовать один или несколько из следующих методов (защищенных соответствующими строками #ifdef
):
SYSTEM_INFO sysinfo;
GetSystemInfo(&sysinfo);
int numCPU = sysinfo.dwNumberOfProcessors;
int numCPU = sysconf(_SC_NPROCESSORS_ONLN);
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);
NSUInteger a = [[NSProcessInfo processInfo] processorCount];
NSUInteger b = [[NSProcessInfo processInfo] activeProcessorCount];
Эта функциональность является частью стандарта С++ 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()
возвращает количество потоков, которые аппаратное обеспечение может выполнять одновременно на основе количества ядер ЦП и блоков с гиперпотоком.
OpenMP поддерживается на многих платформах (включая Visual Studio 2005) и предлагает
int omp_get_num_procs();
которая возвращает количество процессоров/ядер, доступных во время вызова.
sched_setaffinity
это не будет работать.
Если у вас есть доступ на ассемблере, вы можете использовать инструкцию CPUID для получения всякой информации о процессоре. Он переносится между операционными системами, хотя вам нужно будет использовать информацию, специфичную для производителя, чтобы определить, как найти количество ядер. Здесь документ, описывающий, как это сделать на чипах Intel, и страница этот описывает спецификацию AMD.
(Почти) Независимая от платформы функция в 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
}
HW_NCPU
устарела в источнике OS X
В Linux вы можете прочитать файл /proc/cpuinfo и подсчитать ядра.
Обратите внимание, что "количество ядер" может не оказаться особенно полезным числом, вам, возможно, придется немного подбирать его. Как вы можете рассчитывать многопоточные процессоры, такие как Intel HT, IBM Power5 и Power6, и, самое главное, Sun Niagara/UltraSparc T1 и T2? Или еще более интересно, MIPS 1004k с двумя уровнями аппаратной потоковой передачи (супервизор и пользовательский уровень)... Не говоря уже о том, что происходит, когда вы переходите в поддерживаемые гипервизорами системы, где аппаратное обеспечение может иметь десятки процессоров, но ваша конкретная ОС видит только несколько.
Лучшее, на что вы можете надеяться, это указать количество блоков логической обработки, которые у вас есть в вашем локальном разделе ОС. Не забудьте увидеть истинную машину, если вы не гипервизор. Единственное исключение из этого правила сегодня - на земле x86, но конец не виртуальных машин идет быстро...
Вероятно, вы не сможете получить его независимым от платформы способом. Windows вы получаете количество процессоров.
Еще один рецепт Windows: используйте общесистемную переменную окружения NUMBER_OF_PROCESSORS
:
printf("%d\n", atoi(getenv("NUMBER_OF_PROCESSORS")));
Не связан с С++, но в Linux я обычно делаю:
grep processor /proc/cpuinfo | wc -l
Удобен для языков сценариев, таких как bash/perl/python/ruby.
import multiprocessing
print multiprocessing.cpu_count()
grep
есть флаг -c
для подсчета записей!
Windows Server 2003 и более поздние версии позволяют использовать функцию GetLogicalProcessorInformation
Подробнее о OS X: sysconf(_SC_NPROCESSORS_ONLN)
доступны только версии >= 10.5, а не 10.4.
Альтернативой является код HW_AVAILCPU/sysctl()
BSD, который доступен в версиях >= 10.2.
В 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:
grep -c ^processor /proc/cpuinfo
или
grep -c ^cpu /proc/stat # subtract 1 from the result
hwloc (http://www.open-mpi.org/projects/hwloc/) стоит посмотреть. Хотя для интеграции вашего кода требуется другая интеграция библиотеки, но он может предоставить всю информацию о вашем процессоре (количество ядер, топология и т.д.).
В linux лучший программный способ, насколько я знаю, заключается в использовании
sysconf(_SC_NPROCESSORS_CONF)
или
sysconf(_SC_NPROCESSORS_ONLN)
Они не являются стандартными, но находятся на моей странице man для Linux.
Для Win32:
В то время как GetSystemInfo() получает вам количество логических процессоров, используйте GetLogicalProcessorInformationEx()для получения количества физических процессоров.
Альтернатива OS X: решение, описанное ранее на основе [[NSProcessInfo processInfo] processorCount], доступно только в OS X 10.5.0, согласно документам. Для более ранних версий OS X используйте функцию Carbon MPProcessors().
Если вы программист Cocoa, не волнуйтесь из-за того, что это Carbon. Вам просто нужно добавить каркас Carbon к вашему проекту Xcode, и MPProcessors() будет доступен.
Число групп логических процессоров, разделяющих одно процессорное ядро. (используя 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
является IMHO далекой от тривиальной (т.е. "использовать GetLogicalProcessorInformation
или GetLogicalProcessorInformationEx
" ). Вместо этого довольно тонко, если читать документацию (явно представленную для GetLogicalProcessorInformation
и неявно представленную для GetLogicalProcessorInformationEx
) в MSDN.
Число логических процессоров. (используя 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/С++ 98/С++ 03.
GetLogicalProcessorInformation
не работает с различными размерами буфера, которые я использовал. Более чем доволен! ^^
size_t
. (Хотя msvc ++ не жалуется на W4.)
вы также можете использовать WMI в .net, но тогда вы зависите от службы wmi и т.д. Иногда он работает локально, но затем не работает, когда один и тот же код запускается на серверах. Я считаю, что проблема пространства имен связана с "именами", значения которых вы читаете.
В Linux вы можете проверить dmesg и отфильтровать строки, где ACPI инициализирует процессоры, например:
dmesg | grep 'ACPI: Processor
Другая возможность - использовать dmidecode для фильтрации информации о процессоре.