Программно найти количество ядер на машине

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

Ответ 1

С++ 11

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

Ссылка: std:: thread:: hardware_concurrency


В С++ до С++ 11 нет портативного способа. Вместо этого вам нужно будет использовать один или несколько из следующих методов (защищенных соответствующими строками #ifdef):

  • Win32

    SYSTEM_INFO sysinfo;
    GetSystemInfo(&sysinfo);
    int numCPU = sysinfo.dwNumberOfProcessors;
    
  • Linux, Solaris, AIX и Mac OS X >= 10.4 (т.е. тигр)

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

Ответ 2

Эта функциональность является частью стандарта С++ 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() возвращает количество потоков, которые аппаратное обеспечение может выполнять одновременно на основе количества ядер ЦП и блоков с гиперпотоком.

Ответ 3

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

int omp_get_num_procs();

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

Ответ 4

Если у вас есть доступ на ассемблере, вы можете использовать инструкцию CPUID для получения всякой информации о процессоре. Он переносится между операционными системами, хотя вам нужно будет использовать информацию, специфичную для производителя, чтобы определить, как найти количество ядер. Здесь документ, описывающий, как это сделать на чипах Intel, и страница этот описывает спецификацию AMD.

Ответ 5

(Почти) Независимая от платформы функция в 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
}

Ответ 6

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

Ответ 7

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

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

Ответ 8

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

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

Ответ 9

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

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

Ответ 10

Windows (x64 и Win32) и С++ 11

Число групп логических процессоров, совместно использующих одно ядро процессора. (также используя GetLogicalProcessorInformationEx, см. также GetLogicalProcessorInformation)

size_t NumberOfPhysicalCores() noexcept {

    DWORD length = 0;
    const BOOL result_first = GetLogicalProcessorInformationEx(RelationProcessorCore, nullptr, &length);
    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 != FALSE);

    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/С++ 98/С++ 03.

Ответ 11

Подробнее о OS X: sysconf(_SC_NPROCESSORS_ONLN) доступны только версии >= 10.5, а не 10.4.

Альтернативой является код HW_AVAILCPU/sysctl() BSD, который доступен в версиях >= 10.2.

Ответ 13

Не связан с С++, но в Linux я обычно делаю:

grep processor /proc/cpuinfo | wc -l

Удобен для языков сценариев, таких как bash/perl/python/ruby.

Ответ 14

hwloc (http://www.open-mpi.org/projects/hwloc/) стоит посмотреть. Хотя для интеграции вашего кода требуется другая интеграция библиотеки, но он может предоставить всю информацию о вашем процессоре (количество ядер, топология и т.д.).

Ответ 15

В 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

Ответ 16

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

sysconf(_SC_NPROCESSORS_CONF)

или

sysconf(_SC_NPROCESSORS_ONLN)

Они не являются стандартными, но находятся на моей странице man для Linux.

Ответ 17

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

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

Ответ 18

Для Win32:

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

Ответ 19

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

Ответ 20

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

dmesg | grep 'ACPI: Processor

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