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



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

514   20  
c

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 для получения всевозможной информации о процессоре. Он переносится между операционными системами, хотя вам нужно будет использовать информацию о производителе, чтобы определить, как найти Количество ядер. Вот это документ, который описывает, как это сделать на чипы 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'S 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 альтернатива: решение, описанное ранее на основе [[NSProcessInfo processInfo] processorCount] доступно только в OS X 10.5.0, согласно документам. Для более ранних версий OS X Используйте функцию углерода MPProcessors ().

Если вы программист какао, не пугайтесь того факта, что это углерод. Вам просто нужно добавить Carbon framework в свой проект 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 для фильтрации информации о процессоре.

Comments

    Ничего не найдено.