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

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

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

Lothar 14.12.2012 23:55

Обратите внимание, что std::thread::hardware_concurrency возвращает количество физических ядер ЦП, но nproc в Linux показывает только количество ядер ЦП, на которых может выполняться текущий процесс, которым можно управлять с помощью sched_setaffinity. Я не нашел способа получить это вместо стандартного C++ :, см., Например, в Python: stackoverflow.com/questions/1006289/…

Ciro Santilli TRUMP BAN IS BAD 05.05.2019 21:52
Стоит ли изучать PHP в 2026-2027 годах?
Стоит ли изучать PHP в 2026-2027 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
501
2
216 429
19
Перейти к ответу Данный вопрос помечен как решенный

Ответы 19

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

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

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

За исключением того, что это также учитывает гиперпоточные или другие решения SMT как большее количество ядер ...

jakobengblom2 12.10.2008 23:08

@Arafangion: гиперпоточность - это не настоящее параллельное выполнение, это технология для уменьшения накладных расходов на переключение контекста. Гиперпоточный процессор может использовать выполнять только для одного потока за раз, но он может одновременно хранить архитектурное состояние (значения регистров и т. д.) Двух потоков. Характеристики производительности сильно отличаются от двухъядерных.

Wim Coenen 10.07.2009 08:17

@Wim: Это не совсем правильно. Процессоры с гиперпоточностью обычно имеют несколько ALU и могут отправлять несколько инструкций за цикл. Если из-за зависимостей данных и остановок не все ALU могут быть заняты одним потоком, эти ALU вместо этого будут использоваться для одновременного выполнения второго аппаратного потока.

Ben Voigt 14.12.2013 20:45

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

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

Внимание! Гиперпоточные процессоры говорят, что их два. Таким образом, вам также необходимо проверить, поддерживает ли процессор гиперпоточность.

Martin York 30.09.2008 00:46

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

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

jkp 22.05.2009 12:35

Для win32 это вызов GetSystemInfo. (Начиная с версии boost 1.41.0) Захватывает ли это всю информацию, чтобы определить, сколько рабочих потоков будет эффективным? Нужно ли учитывать количество ядер и гиперпоточность? неподписанный поток :: hardware_concurrency () {SYSTEM_INFO info = {0}; GetSystemInfo (& информация); return info.dwNumberOfProcessors; }

Jive Dadson 21.04.2010 23:51

Согласно MSDN, GetSystemInfo () возвращает количество «физических процессоров» в dwNumberOfProcessors, но не определяет, что это значит. Документация Boost, кажется, утверждает, что она включает в себя гиперпоточность.

Ferruccio 22.04.2010 00:26

см. stackoverflow.com/questions/642348/… для гиперпоточности

naugtur 06.05.2010 14:58

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

sysconf(_SC_NPROCESSORS_CONF)

или же

sysconf(_SC_NPROCESSORS_ONLN)

Они не стандартные, но есть на моей странице руководства для Linux.

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

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

Ferruccio 23.02.2011 15:10

Одна из ловушек этого метода заключается в том, что вы используете CPUID для обнаружения HyperThreading на процессорах Intel. Я столкнулся с этой проблемой на своем ноутбуке: в то время как процессор, который я установил в машину, поддерживает HyperThreading (и, конечно же, сообщает об этом через CPUID), BIOS этого не делает. Следовательно, вам не следует пытаться использовать возможности HT просто из чтения CPUID. Поскольку вы не можете запросить BIOS о поддержке HT (я этого не видел), ОС следует запросить, чтобы получить количество логических процессоров.

Chuck R 29.05.2013 12:18
Ответ принят как подходящий

C++ 11

#include <thread>

//may return 0 when not able to detect
const auto processor_count = 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];
    

Добавьте директивы препроцессора, чтобы выполнялся только код, специфичный для ОС.

mcandre 21.06.2010 23:17

@mcandre: это оставлено в качестве упражнения для читателя. Если бы я реализовывал, я бы, вероятно, использовал подход шаблонной политики, когда политика была определена в директивах препроцессора. Или ... вы можете использовать boost thread :: hardware_concurrency ().

paxos1977 23.06.2010 00:26

в качестве пояснения, решение Win32 возвращает общее количество ядер (то, что было запрошено), а не общее количество физических процессоров.

Eric 03.02.2011 20:59

Способ Linux / Solaris / AIX также работает во FreeBSD и работает по крайней мере с 2006 года. Кроме того, это вернет процессоры в оперативный режим, если система способна отключать некоторые из них, они могут не учитываться. Вызов sysconf с "_SC_NPROCESSORS_CONF" вернет общее количество сконфигурированных процессоров.

Chris S 23.04.2011 22:43

Обратите внимание, что версия fbsd намного проще - это комбинированный пример, поэтому он выглядит сложным.

Good Person 20.12.2012 02:52

Несколько вещей, о которых нужно знать. HW_NCPU не рекомендуется в OS X. В Windows GetSystemInfo полезен только в том случае, если в вашей системе 32 логических процессора или меньше, используйте GetLogicalProcessorInformation для систем, которые имеют более 32 логических процессоров.

user152949 26.02.2013 14:40

@Eric Предположительно, это хуже, чем это, и он фактически возвращает количество логических ядер, поэтому, если у вас включена гиперпоточность, оно может быть больше, чем вы ожидаете. Это не очень ясно, потому что в документации Microsoft по двум разным версиям одного и того же API говорится о двух разных вещах (в одной это сформулировано как «физическое», а в другом - как «логическое»).

Trejkaz 30.04.2013 09:57

@Trejkaz документ четко говорит «логический» - который всегда считает HT-ядра, слово "физический"всегда относится к ядрам, о которых сообщает BIOS / UEFI, поскольку ядра также могут быть эмулированы / виртуализированы. Вы можете различать HT / не-HT ядра, например, с помощью таких функций, как GetLogicalProcessorInformation. Примечание: HT! = Эмуляция или виртуализация, это разница большой, HT - это аппаратная оптимизация, так сказать

specializt 27.06.2016 12:02

@specializt да, если вы проигнорируете бит об одной странице в документах, где она написана как «физическая», а другая - как «логическая», это будет довольно ясно по своему значению. Или, в качестве альтернативы, если бы документы были исправлены между мной, сделав этот комментарий, и вашим ответом, это также решило бы проблему.

Trejkaz 29.06.2016 08:23

@Trejkaz, я бы хотел увидеть этот документ - MSDN обычно не имеет таких серьезных проблем, я очень сомневаюсь, что они действительно перепутали его, на самом деле они даже упоминают разницу и связь между этими терминами: «Для получения информации о физических процессорах, совместно используемых логическими процессорами, вызовите GetLogicalProcessorInformationEx с параметром RelationshipType, установленным на RelationProcessorPackage (3)».

specializt 29.06.2016 11:59

@specializt да, жаль, что в то время я не связывался с этим. Маловероятно, что я найду его сейчас, даже если искал. : /

Trejkaz 30.06.2016 02:10

потому что его не существует.

specializt 30.06.2016 10:40

Добавление необходимых заголовков (например, #include <unistd.h> для linux) сделает ответ идеальным для будущих поисковиков.

MaMazav 04.06.2017 15:40
ПРИМЕЧАНИЕ that std::thread::hardware_concurrency implementations differ; Visual Studio takes into account affinity (returns 1 if process is restricted to one core etc.) whereas g++ does not.
vladr 06.09.2017 19:43

Если вы используете современную Windows и вам нужны все процессоры независимо от группы процессоров (например, вы работаете с системой с более чем 64 процессорами), и вы ориентируетесь на Windows 7/2008 R2 или выше, вы можете использовать GetMaximumProcessorCount(ALL_PROCESSOR_GROUPS) для получения полный подсчет. См. Пример github.com/python/cpython/commit/….

Anon 16.02.2018 23:58

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

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

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

int omp_get_num_procs();

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

потому что это неправильный ответ. Из gcc.gnu.org/bugzilla/show_bug.cgi?id=37586 «omp_get_num_procs () вернет только меньшее число, чем количество системных процессоров в сети, если GOMP_CPU_AFFINITY env var используется, или если вызывающий процесс и / или поток имеют привязку к процессору, ограниченную подмножеством процессоров». Поэтому, если вы ранее позвонили, например, sched_setaffinity, это не сработает.

angainor 11.11.2013 15:53

Эта функция возвращает количество процессоров, доступных вызывающему процессу. В любом случае, разве это не самый распространенный вариант использования? Из-за некоторых бесполезных целей отчетности фактическое количество аппаратных ядер ЦП не имеет значения для вас, если вы не можете использовать их в своем коде.

macbirdie 15.11.2013 00:24

@EvanTeran Помимо того, что это была цель вопроса, это, конечно, может быть полезно. Например, с целью настройки сходства потоков. Скажем, я хочу запустить 4 потока, привязанных к четырем последним ядрам ЦП на моей машине, вместо четырех первых ядер. Кроме того, есть и другие способы распараллеливания кода, кроме OpenMP. Я могу сам создавать потоки pthreads. Они, безусловно, доступны и не ограничиваются переменными среды OpenMP.

angainor 26.11.2013 01:41

Это возвращает количество логических процессоров, а не ядер (физических процессоров) как таковых.

Michael Konečný 10.06.2016 18:41

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

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

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

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

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

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

user152949 26.02.2013 14:26

Не имеет отношения к C++, но в Linux я обычно делаю:

grep processor /proc/cpuinfo | wc -l

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

Для питона: import multiprocessingprint multiprocessing.cpu_count()

initzero 22.08.2011 22:20

Прошло много времени, но grep имеет флаг -c для подсчета записей!

Lapshin Dmitry 11.10.2015 18:45

Прошло много времени, но мой Raspberry Pi имеет model name : ARMv6-compatible processor rev 7 (v6l) в своей cpuinfo, поэтому, вероятно, можно использовать grep -c ^processor /proc/cpuinfo.

n8henrie 14.06.2020 01:31

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

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

Альтернативой является код BSD HW_AVAILCPU/sysctl(), который доступен в версиях> = 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

Для Win32:

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

Windows (x64 и Win32) и C++ 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, 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 / C++ 98 / C++ 03.

Спасибо! Я искал это, потому что GetLogicalProcessorInformation не работал с различными размерами буфера, которые я использовал. Более чем доволен! ^^

Peter Badida 11.08.2018 15:19

@KeyWeeUsr Спасибо. Программирование для Windows далеко не тривиально и логично. А пока я использую чуть более обновленный Версия C++ 17, который также более правильный по данным статического анализатора PVS-Studio в отношении некоторых приведений size_t. (Хотя msvC++ не жалуется на W4.)

Matthias 11.08.2018 15:44

Другие вопросы по теме