Программно определить количество ядер на компьютере

есть ли способ определить, сколько ядер машина имеет от C / C++ независимым от платформы способом? Если такой вещи не существует, как насчет ее определения для каждой платформы (Windows/ * nix / Mac)?

20 ответов


C++11

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

ссылки: std::thread:: hardware_concurrency


в C++ до C++11 нет переносимого способа. Вместо этого вам нужно будет использовать один или несколько из следующих методов (защищенных соответствующим #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];
    

эта функция является частью стандарта C++11.

#include <thread>

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

для старых компиляторов, вы можете использовать импульс.Нить библиотека.

#include <boost/thread.hpp>

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

В любом случае hardware_concurrency() возвращает количество потоков, которые аппаратное обеспечение способно выполнять одновременно на основе количества ядер процессора и гиперпотоков.


OpenMP поддерживается на многих платформах (включая Visual Studio 2005) и предлагает

int omp_get_num_procs();

функция, которая возвращает количество процессоров/ядер, доступных во время вызова.


Если у вас есть доступ к ассемблеру, вы можете использовать инструкцию CPUID для получения всевозможной информации о процессоре. Он переносится между операционными системами, хотя вам нужно будет использовать информацию производителя, чтобы определить, как найти Количество ядер. Вот!--1-->документ, который описывает, как это сделать на чипы Intel, и страница 11 из этот описывает спецификацию 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
}

в Linux вы можете прочитать файл /proc/cpuinfo и подсчитать ядра.


обратите внимание, что" количество ядер " может быть не особенно полезным числом, возможно, вам придется квалифицировать его немного больше. Как вы хотите считать многопоточные процессоры, такие как Intel HT, IBM Power5 и Power6, и, самое известное, Sun Niagara/UltraSparc T1 и T2? Или, что еще более интересно, MIPS 1004k с двумя уровнями аппаратной потоковой передачи (супервизор и пользовательский уровень)... Не говоря уже о том, что происходит при переходе в системы с поддержкой гипервизора, где оборудование может иметь десятки процессоров но ваша ОС видит только несколько.

лучшее, на что вы можете надеяться, это сообщить количество логических процессоров, которые у вас есть в локальном разделе ОС. Забудьте о том, чтобы видеть истинную машину, если вы не гипервизор. Единственное исключение из этого правила сегодня находится в x86 land, но конец не виртуальных машин наступает быстро...


еще один рецепт Windows: используйте общесистемную переменную среды NUMBER_OF_PROCESSORS:

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

вы, вероятно, не сможет сделать его независимым от платформы способом. Windows вы получаете количество процессоров.

Win32 Информация О Системе


подробнее о 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.


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"). Вместо этого он довольно тонкий, Если кто-то читает документацию (явно подарок 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 и C++98 и C++03.


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

OS X alternative: решение, описанное ранее на основе [[NSProcessInfo processInfo] processorCount], доступно только в OS X 10.5.0, согласно документам. Для более ранних версий OS X Используйте функцию углерода MPProcessors ().

Если вы программист какао, не пугайтесь того факта, что это углерод. Вам просто нужно добавить углеродную структуру в свой проект Xcode, и MPProcessors () будут доступны.


в linux лучший программный способ, насколько я знаю, использовать

sysconf(_SC_NPROCESSORS_CONF)

или

sysconf(_SC_NPROCESSORS_ONLN)

это не стандарт, но в моей странице для Linux.


Для Win32:

в то время как GetSystemInfo() получает количество логическое процессоры, использовать GetLogicalProcessorInformationEx () чтобы получить номер физическая процессоры.


вы также можете использовать WMI в .net, но затем вы зависите от запущенной службы wmi так далее. Иногда он работает локально, но затем терпит неудачу, когда тот же код запускается на серверах. Я считаю, что это проблема пространства имен, связанная с "именами", значения которых Вы читаете.


в Linux вы можете проверить dmesg и отфильтровать строки, где ACPI инициализирует процессоры, что-то вроде:

dmesg | grep 'ACPI: Processor'

другая возможность - использовать dmidecode для фильтрации информации о процессоре.