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

383

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

  • 4
    Если вы хотите использовать его, выясните, сколько потоков для запуска, используйте NUMBER_OF_PROCESSORS в качестве основного показателя. Я оставляю вам в качестве упражнения, почему это намного лучше (если люди будут использовать это больше), чем использование аппаратных ядер. Сколько ядер принадлежит вашей программе - экологическая проблема!
Теги:

20 ответов

606
Лучший ответ

С++ 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];
    
  • 0
    Добавьте директивы препроцессора, чтобы выполнялся только специфичный для ОС код.
  • 4
    @mcandre: это оставлено в качестве упражнения для читателя. Если бы я реализовывал, я бы, вероятно, использовал бы подход шаблонной политики, где политика была определена в директивах препроцессора. Или ... вы можете использовать boost thread :: hardware_concurrency ().
Показать ещё 15 комментариев
195

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

  • 1
    Seconded ... собирался использовать приведенный выше пример кода и некоторые макросы препроцессора для раскрытия одной функции, но тяжелая работа для меня была сделана.
  • 0
    Для win32 это вызов GetSystemInfo. (Начиная с версии Boost 1.41.0). Собирает ли она всю информацию, чтобы определить, сколько рабочих потоков будет эффективным? Нужно ли учитывать как количество ядер, так и гиперпоточность? неподписанный поток :: hardware_concurrency () {SYSTEM_INFO info = {0}; GetSystemInfo (& информация); return info.dwNumberOfProcessors; }
Показать ещё 2 комментария
55

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

int omp_get_num_procs();

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

  • 0
    потому что это неправильный ответ. От gcc.gnu.org/bugzilla/show_bug.cgi?id=37586 "omp_get_num_procs () будет возвращать только меньшее число, чем количество системных процессоров в сети, если используется env var GOMP_CPU_AFFINITY или если вызывающий процесс и / или поток имеет Сродство процессора ограничено подмножеством процессоров ». Так что если вы ранее вызываете, например, sched_setaffinity это не будет работать.
  • 7
    Эта функция возвращает количество процессоров, доступных вызывающему процессу. Разве это не самый распространенный вариант использования? Помимо некоторых бесполезных целей отчетности, фактическое количество аппаратных ядер ЦП не имеет к вам отношения, если вы не можете использовать их в своем коде.
Показать ещё 2 комментария
35

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

  • 4
    Возможно, он был отвергнут, потому что вопрос помечен как C ++, и этот ответ не относится к системам, использующим C ++ на архитектурах, отличных от x86 (ARM, PPC и т. Д.). Я не говорю, что это хорошая причина для отрицательного ответа, просто возможность.
  • 2
    К вашему сведению ... обе ссылки теперь битые ...
Показать ещё 2 комментария
31

(Почти) Независимая от платформы функция в 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
}
  • 0
    Кажется, что HW_NCPU устарела в источнике OS X
16

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

  • 0
    За исключением того, что это также считает гиперпоточные или другие решения SMT как больше ядер ...
  • 2
    jakobengblom2: И как это / неправильно /?
Показать ещё 2 комментария
10

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

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

8

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

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

  • 1
    Осторожно: процессоры Hyperthreaded говорят, что их два. Таким образом, вам также необходимо проверить, поддерживает ли процессор технологию Hyperthread.
7

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

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

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

grep processor /proc/cpuinfo | wc -l

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

  • 4
    Для python: import multiprocessing print multiprocessing.cpu_count()
  • 3
    Это было давно, но у grep есть флаг -c для подсчета записей!
5

Windows Server 2003 и более поздние версии позволяют использовать функцию GetLogicalProcessorInformation

http://msdn.microsoft.com/en-us/library/ms683194.aspx

4

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

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

3

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

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

2

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

sysconf(_SC_NPROCESSORS_CONF)

или

sysconf(_SC_NPROCESSORS_ONLN)

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

1

Для Win32:

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

1

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

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

0

Windows (x64 и Win32) и С++ 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 является 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.

  • 1
    Спасибо! Я искал это, потому что GetLogicalProcessorInformation не работает с различными размерами буфера, которые я использовал. Более чем доволен! ^^
  • 0
    @KeyWeeUsr Благодаря Windows, программирование несколько далеко от тривиального и логического. В то же время я использую немного более обновленную версию C ++ 17, которая также более корректна в соответствии со статическим анализатором PVS-Studio в отношении некоторых приведений size_t . (Хотя msvc ++ не жалуется на W4.)
-1

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

-4

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

dmesg | grep 'ACPI: Processor

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

  • 0
    Не работает на моем компьютере

Ещё вопросы

Сообщество Overcoder
Наверх
Меню