web-dev-qa-db-fra.com

Trouver par programme le nombre de cœurs sur une machine

Existe-t-il un moyen de déterminer le nombre de cœurs d’une machine à partir de C/C++ d’une manière indépendante de la plate-forme? Si rien de tel n’existe, qu’en est-il de la déterminer par plate-forme (Windows/* nix/Mac)?

438
hazzen

C++ 11

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

Référence: std :: thread :: hardware_concurrency


En C++ avant C++ 11, il n'y a pas de moyen portable. Au lieu de cela, vous devrez utiliser une ou plusieurs des méthodes suivantes (protégées par les lignes #ifdef appropriées):

  • Win32

    SYSTEM_INFO sysinfo;
    GetSystemInfo(&sysinfo);
    int numCPU = sysinfo.dwNumberOfProcessors;
    
  • Linux, Solaris, AIX et Mac OS X> = 10.4 (c.-à-d. Tiger et plus)

    int numCPU = sysconf(_SC_NPROCESSORS_ONLN);
    
  • FreeBSD, MacOS X, NetBSD, OpenBSD, etc.

    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 ou iOS)

    NSUInteger a = [[NSProcessInfo processInfo] processorCount];
    NSUInteger b = [[NSProcessInfo processInfo] activeProcessorCount];
    
674
paxos1977

Cette fonctionnalité fait partie de la norme C++ 11.

#include <thread>

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

Pour les anciens compilateurs, vous pouvez utiliser la bibliothèque Boost.Thread .

#include <boost/thread.hpp>

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

Dans les deux cas, hardware_concurrency() renvoie le nombre de threads que le matériel est capable d'exécuter simultanément en fonction du nombre de cœurs de processeur et d'unités d'hyper-threading.

197
Ferruccio

OpenMP est pris en charge sur de nombreuses plates-formes (y compris Visual Studio 2005) et offre une

int omp_get_num_procs();

fonction qui renvoie le nombre de processeurs/cœurs disponibles au moment de l'appel.

55
macbirdie

Si vous avez accès au langage d'assemblage, vous pouvez utiliser l'instruction CPUID pour obtenir toutes sortes d'informations sur la CPU. Il est portable entre les systèmes d'exploitation. Vous devrez toutefois utiliser les informations spécifiques du fabricant pour déterminer comment trouver le nombre de cœurs. Voici n document décrivant la procédure à suivre pour les puces Intel , et la page 11 de celle-ci décrit la spécification AMD.

37
Head Geek

Fonction (presque) indépendante de la plate-forme en c-code

#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
}
31
Dirk-Jan Kroon

Sous Linux, vous pouvez lire le fichier/proc/cpuinfo et compter les cœurs.

15
JesperE

Notez que "nombre de cœurs" peut ne pas être un nombre particulièrement utile, vous devrez peut-être le qualifier un peu plus. Comment voulez-vous compter les processeurs multi-threads tels que Intel HT, IBM Power5 et Power6 et, plus célèbre, les serveurs Niagara/UltraSparc T1 et T2 de Sun? Ou encore plus intéressant, le MIPS 1004k avec ses deux niveaux de threading matériel (superviseur ET niveau utilisateur) ... Sans parler de ce qui se passe lorsque vous passez dans des systèmes pris en charge par l'hyperviseur, où le matériel peut comporter des dizaines de CPU mais votre système d'exploitation particulier n'en voit que quelques-uns.

Le mieux que vous puissiez espérer est d'indiquer le nombre d'unités de traitement logique que vous avez dans votre partition OS locale. Oubliez de voir la vraie machine sauf si vous êtes un hyperviseur. La seule exception à cette règle aujourd'hui concerne les pays x86, mais la fin des machines non virtuelles arrive rapidement ...

10
jakobengblom2

Une recette Windows supplémentaire: utilisez la variable d'environnement système _NUMBER_OF_PROCESSORS_:

_printf("%d\n", atoi(getenv("NUMBER_OF_PROCESSORS")));
_
7
Constantin

Vous ne pourrez probablement pas l'obtenir d'une manière indépendante de la plate-forme. Windows vous obtenez le nombre de processeurs.

Informations système Win32

7
Ken

Windows (x64 et Win32) et C++ 11

Nombre de groupes de processeurs logiques partageant un seul cœur de processeur. (Utilisation de GetLogicalProcessorInformationEx , voir GetLogicalProcessorInformation = aussi bien)

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

Notez que l'implémentation de NumberOfPhysicalCores est un IMHO loin d'être trivial (c'est-à-dire "utilisez GetLogicalProcessorInformation ou GetLogicalProcessorInformationEx"). Au lieu de cela, il est plutôt subtil si on lit la documentation (explicitement présente pour GetLogicalProcessorInformation et implicitement présente pour GetLogicalProcessorInformationEx) sur MSDN.

Nombre de processeurs logiques. (Utilisation de 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);
}

Notez que les deux méthodes peuvent facilement être converties en C/C++ 98/C++ 03.

6
Matthias

Plus sur OS X: sysconf(_SC_NPROCESSORS_ONLN) est disponible uniquement pour les versions> = 10.5, et non 10.4.

Une alternative est le code HW_AVAILCPU/sysctl() BSD disponible sur les versions> = 10.2.

5
sezero

Windows Server 2003 et versions ultérieures vous permettent d'exploiter la fonction GetLogicalProcessorInformation

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

4
Chris Ballance

Non lié au C++, mais sous Linux, je fais habituellement:

grep processor /proc/cpuinfo | wc -l

Pratique pour les langages de script tels que bash/Perl/python/Ruby.

4
Chris

Sous Linux, il peut ne pas être sûr d'utiliser _SC_NPROCESSORS_ONLN car il ne fait pas partie de la norme POSIX et le manuel sysconf indique tout autant. Donc, il est possible que _SC_NPROCESSORS_ONLN ne soit pas présent:

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

Une approche simple consisterait à lire /proc/stat ou /proc/cpuinfo et à les compter:

#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;
}

Utiliser /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;
}

La même approche dans Shell utilisant grep:

grep -c ^processor /proc/cpuinfo

Ou

grep -c ^cpu /proc/stat # subtract 1 from the result
3
P.P.

hwloc (http://www.open-mpi.org/projects/hwloc/) vaut la peine d’être examiné. Bien que cela nécessite une autre intégration de bibliothèque dans votre code, il peut fournir toutes les informations sur votre processeur (nombre de cœurs, topologie, etc.).

3
Akhil

Pour Win32:

Alors que GetSystemInfo () vous obtient le nombre de processeurs logiques , utilisez GetLogicalProcessorInformationEx () pour obtenir le nombre de physiques processeurs.

2
irrlicht_ist_toll

Alternative à OS X: La solution décrite précédemment basée sur [[NSProcessInfo processInfo] CPUCount] est uniquement disponible sur OS X 10.5.0, conformément à la documentation. Pour les versions antérieures de OS X, utilisez la fonction Carbon MPProcessors ().

Si vous êtes un programmeur Cocoa, ne soyez pas effrayé par le fait qu'il s'agisse de Carbon. Vous devez simplement ajouter le cadre Carbon à votre projet Xcode et MPProcessors () sera disponible.

2
gauss256

Sur Linux, le meilleur moyen de programmation que je connaisse consiste à utiliser

sysconf(_SC_NPROCESSORS_CONF)

ou

sysconf(_SC_NPROCESSORS_ONLN)

Ce ne sont pas standard, mais sont dans ma page de manuel pour Linux.

2
Evan Teran