Trova a livello di codice il numero di core su una macchina


464

C'è un modo per determinare quanti core ha una macchina da C / C ++ in modo indipendente dalla piattaforma? Se non esiste nulla del genere, che ne dici di determinarlo per piattaforma (Windows / * nix / Mac)?


4
Se vuoi usarlo scopri quanti thread avviare, utilizza NUMBER_OF_PROCESSORS come misura principale. Vi lascio come un esercizio per voi perché questo è molto meglio (se la gente lo usasse di più) quindi usare i core hardware. Quanti core appartengono al tuo programma sono un problema ambientale!
Lothar,

Si noti che std::thread::hardware_concurrencyrestituisce il numero di core fisici della CPU, ma nprocin Linux mostra solo il numero di core della CPU su cui può essere eseguito il processo corrente, che può essere controllato sched_setaffinity. Non ho trovato un modo per ottenere che invece dallo standard C ++ :, vedere ad esempio in Python: stackoverflow.com/questions/1006289/...
Ciro Santilli郝海东冠状病六四事件法轮功

Risposte:


706

C ++ 11

#include <thread>

//may return 0 when not able to detect
const auto processor_count = std::thread::hardware_concurrency();

Riferimento: std :: thread :: hardware_concurrency


In C ++ prima di C ++ 11, non esiste un modo portatile. Invece, dovrai usare uno o più dei seguenti metodi (sorvegliati da #ifdeflinee appropriate ):

  • Win32

    SYSTEM_INFO sysinfo;
    GetSystemInfo(&sysinfo);
    int numCPU = sysinfo.dwNumberOfProcessors;
    
  • Linux, Solaris, AIX e Mac OS X> = 10.4 (ovvero Tiger in poi)

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

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

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

5
@mcandre: che viene lasciato come esercizio per il lettore. Se avessi implementato, probabilmente avrei usato l'approccio modello-politica in cui la politica era definita nelle direttive del preprocessore. Oppure ... potresti usare boost thread :: hardware_concurrency ().
paxos1977,

3
come punto di chiarimento la soluzione Win32 restituisce il numero totale di core (ciò che è stato richiesto) non il numero totale di CPU fisiche.
Eric

1
Il modo Linux / Solaris / AIX funziona anche su FreeBSD e lo ha almeno dal 2006. Inoltre, ciò restituirà le CPU online, se un sistema è in grado di spegnerne alcune potrebbero non essere conteggiate. La chiamata a sysconf con "_SC_NPROCESSORS_CONF" restituirà il totale delle CPU configurate.
Chris S,

3
Un paio di cose da tenere presente. HW_NCPUè obsoleto su OS X. Su Windows GetSystemInfoè utile solo se il tuo sistema ha 32 processori logici o meno, usa GetLogicalProcessorInformationper sistemi che hanno più di 32 processori logici.

1
@Trejkaz il documentaion dice chiaramente "logico" - che conta sempre i core HT, la parola "fisico" si riferisce sempre ai core riportati dal BIOS / UEFI poiché i core possono anche essere emulati / virtualizzati. È possibile distinguere tra core HT / non HT con funzioni come GetLogicalProcessorInformation , ad esempio. Nota: HT! = Emulazione o virtualizzazione, questa è una grande differenza, HT è un'ottimizzazione hardware, per così dire
specializt

202

Questa funzionalità fa parte dello standard C ++ 11.

#include <thread>

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

Per i compilatori meno recenti , è possibile utilizzare la libreria Boost.Thread .

#include <boost/thread.hpp>

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

In entrambi i casi, hardware_concurrency()restituisce il numero di thread che l'hardware è in grado di eseguire contemporaneamente in base al numero di core della CPU e unità di hyper-threading.


1
In secondo luogo ... avrebbe usato il codice di esempio sopra e alcune macro di preprocessore per esporre una singola funzione, ma il duro lavoro è stato fatto per me.
jkp,

Per win32, è una chiamata a GetSystemInfo. (A partire dalla versione 1.41.0 di boost) Cattura tutte le informazioni per determinare quanti thread di lavoro sarebbero efficaci? È necessario considerare sia il numero di core che l'hyper-threading? thread unsigned :: hardware_concurrency () {SYSTEM_INFO info = {0}; GetSystemInfo (e informazioni); return info.dwNumberOfProcessors; }
Jive Dadson,

Secondo MSDN, GetSystemInfo () restituisce il numero di "processori fisici" in dwNumberOfProcessors ma non definisce cosa significhi. La documentazione di Boost sembra affermare che include unità hyperthreading.
Ferruccio,


57

OpenMP è supportato su molte piattaforme (incluso Visual Studio 2005) e offre un

int omp_get_num_procs();

funzione che restituisce il numero di processori / core disponibili al momento della chiamata.


perché è una risposta sbagliata. Da gcc.gnu.org/bugzilla/show_bug.cgi?id=37586 "omp_get_num_procs () restituirà solo un numero inferiore rispetto al numero di CPU di sistema online, se viene utilizzato GOMP_CPU_AFFINITY env var o se il processo di chiamata e / o il thread ha Affinità CPU limitata a un sottoinsieme di CPU ". Quindi, se in precedenza si chiama ad esempio, sched_setaffinityquesto non funzionerà.
angainor

7
Questa funzione restituisce il numero di CPU disponibili per il processo di chiamata. Non è comunque il caso d'uso più comune? Fuori misura per alcuni scopi di report inutili, il numero effettivo di core hardware della CPU non è rilevante per te se non puoi sfruttarli nel tuo codice.
macbirdie,

@EvanTeran Oltre al fatto che era lo scopo della domanda, può ovviamente essere utile. Ad esempio, allo scopo di impostare l'affinità del thread. Dì, voglio eseguire 4 thread associati a quattro core della CPU sul mio computer, anziché a quattro core. Inoltre, ci sono altri modi per parallelizzare il codice tranne OpenMP. Potrei voler generare pthreads da solo. Questi sono sicuramente disponibili e non limitati dalle variabili di ambiente OpenMP.
angainor

2
Ciò restituisce il numero di CPU logiche, non i core (CPU fisiche) in quanto tali.
Michael Konečný,

37

Se si dispone dell'accesso in linguaggio assembly, è possibile utilizzare l'istruzione CPUID per ottenere tutti i tipi di informazioni sulla CPU. È portatile tra i sistemi operativi, sebbene sia necessario utilizzare le informazioni specifiche del produttore per determinare come trovare il numero di core. Ecco un documento che descrive come farlo su chip Intel e la pagina 11 di questo descrive le specifiche AMD.


4
Potrebbe essere stato sottoposto a downgrade perché la domanda è contrassegnata come C ++ e questa risposta non si applica ai sistemi che eseguono C ++ su architetture non x86 (ARM, PPC, ecc.). Non sto dicendo che sia una buona ragione per votare una risposta, solo una possibilità.
Ferruccio,

3
Un inconveniente di questo metodo è se si utilizza CPUID per rilevare HyperThreading su processori Intel. Mi sono imbattuto in questo problema sul mio laptop: mentre la CPU che ho inserito nella macchina supporta HyperThreading (e, ovviamente, segnala che lo fa tramite CPUID), il BIOS no. Pertanto, non si dovrebbe tentare di utilizzare la funzionalità HT semplicemente da una lettura CPUID. Dal momento che non è possibile eseguire una query sul BIOS in merito al supporto HT (nessun modo che ho visto), è necessario eseguire una query sul sistema operativo per ottenere il conteggio del processore logico.
Chuck R,

32

(Quasi) Funzione indipendente dalla piattaforma in codice 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
}

Sembra HW_NCPUdeprecato sulla fonte

16

Su Linux, puoi leggere il file / proc / cpuinfo e contare i core.


Tranne il fatto che conta anche hyperthreaded o altre soluzioni SMT come più core ...
jakobengblom2,

13
@Arafangion: l'hyperthreading non è una vera esecuzione parallela, è una tecnologia per ridurre l'overhead del cambio di contesto. Una CPU hyperthreaded può eseguire solo un thread alla volta, ma può memorizzare lo stato architettonico (valori di registro ecc.) Di due thread contemporaneamente. Le caratteristiche prestazionali sono molto diverse dall'avere due core.
Wim Coenen,

7
@Wim: Non è del tutto corretto. Le CPU con hyperthreading generalmente hanno più ALU e possono inviare più istruzioni per ciclo. Se a causa delle dipendenze dei dati e delle bancarelle, non tutti gli ALU possono essere occupati da un thread, tali ALU verranno invece utilizzati per l'esecuzione simultanea del secondo thread hardware.
Ben Voigt,

11

Si noti che "numero di core" potrebbe non essere un numero particolarmente utile, potrebbe essere necessario qualificarlo un po 'di più. Come si desidera contare CPU multi-thread come Intel HT, IBM Power5 e Power6 e, soprattutto, Sun's Niagara / UltraSparc T1 e T2? O ancora più interessante, MIPS 1004k con i suoi due livelli di threading hardware (supervisore E livello utente) ... Per non parlare di ciò che accade quando si passa a sistemi supportati da hypervisor in cui l'hardware potrebbe avere decine di CPU ma il proprio sistema operativo specifico ne vede solo alcuni.

Il meglio che puoi sperare è di dire il numero di unità di elaborazione logica che hai nella partizione del sistema operativo locale. Dimentica di vedere la vera macchina se non sei un hypervisor. L'unica eccezione a questa regola oggi è nella terra x86, ma la fine delle macchine non virtuali sta arrivando velocemente ...


7

Un'altra ricetta per Windows: utilizzare la variabile di ambiente a livello di sistema NUMBER_OF_PROCESSORS:

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

7

Probabilmente non sarai in grado di ottenerlo in modo indipendente dalla piattaforma. Windows ottieni il numero di processori.

Informazioni sul sistema Win32


1
Attenzione: i processori hyperthreaded affermano che ce ne sono due. Quindi devi anche vedere se il processore è in grado di eseguire l'hyperthread.
Martin York,

6

Windows (x64 e Win32) e C ++ 11

Il numero di gruppi di processori logici che condividono un singolo core del processore. (Utilizzando GetLogicalProcessorInformationEx , consultare anche 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;
}

Si noti che l'implementazione di NumberOfPhysicalCoresIMHO è tutt'altro che banale (ovvero "uso GetLogicalProcessorInformationo GetLogicalProcessorInformationEx"). Invece è piuttosto sottile se si legge la documentazione (esplicitamente presente GetLogicalProcessorInformatione implicitamente presente GetLogicalProcessorInformationEx) su MSDN.

Il numero di processori logici. (Utilizzo di 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);
}

Si noti che entrambi i metodi possono essere facilmente convertiti in C / C ++ 98 / C ++ 03.


1
Grazie! Lo stavo cercando perché GetLogicalProcessorInformationnon funzionavo con varie dimensioni di buffer che ho usato. Più che soddisfatto! ^^
KeyWeeUsr

@KeyWeeUsr Grazie La programmazione di Windows è un po 'lontana dall'essere banale e logica. Nel frattempo, uso una versione C ++ 17 leggermente più aggiornata , che è anche più corretta secondo l'analizzatore statico PVS-Studio per quanto riguarda alcuni size_tcast. (Anche se msvc ++ non si lamenta di W4.)
Matthias,

5

Altro su OS X: sysconf(_SC_NPROCESSORS_ONLN)sono disponibili solo versioni> = 10.5, non 10.4.

Un'alternativa è il HW_AVAILCPU/sysctl()codice BSD che è disponibile nelle versioni> = 10.2.



4

Non correlato al C ++, ma su Linux di solito faccio:

grep processor /proc/cpuinfo | wc -l

Comodo per i linguaggi di scripting come bash / perl / python / ruby.


4
Per python:import multiprocessing print multiprocessing.cpu_count()
initzero

3
È passato molto tempo, ma grepha la -cbandiera per contare le voci!
Lapshin Dmitry,

3

Vale la pena dare un'occhiata a hwloc (http://www.open-mpi.org/projects/hwloc/). Tuttavia richiede un'altra integrazione della libreria nel codice ma può fornire tutte le informazioni sul processore (numero di core, topologia, ecc.)


3

Su Linux il miglior modo programmatico per quanto ne so è usare

sysconf(_SC_NPROCESSORS_CONF)

o

sysconf(_SC_NPROCESSORS_ONLN)

Questi non sono standard, ma sono nella mia pagina man per Linux.


3

Su Linux, potrebbe non essere sicuro da usare _SC_NPROCESSORS_ONLNpoiché non fa parte dello standard POSIX e il manuale di sysconf lo afferma altrettanto. Quindi c'è una possibilità che _SC_NPROCESSORS_ONLNpotrebbe non essere presente:

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

Un approccio semplice sarebbe quello di leggerli /proc/stato /proc/cpuinfocontarli:

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

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

Lo stesso approccio in shell usando grep:

grep -c ^processor /proc/cpuinfo

O

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

2

Alternativa OS X: la soluzione descritta in precedenza basata su [[NSProcessInfo processInfo] processorCount] è disponibile solo su OS X 10.5.0, secondo i documenti. Per le versioni precedenti di OS X, utilizzare la funzione Carbon MPProcessors ().

Se sei un programmatore di cacao, non essere spaventato dal fatto che questo è Carbon. Devi solo aggiungere il framework Carbon al tuo progetto Xcode e MPProcessors () sarà disponibile.



-2

puoi usare WMI anche in .net ma sei quindi dipendente dal servizio wmi in esecuzione ecc. A volte funziona localmente, ma poi fallisce quando lo stesso codice viene eseguito sui server. Credo che sia un problema di spazio dei nomi, correlato ai "nomi" di cui stai leggendo i valori.


-3

In Linux, puoi controllare dmesg e filtrare le linee in cui ACPI inizializza le CPU, qualcosa del tipo:

dmesg | grep 'ACPI: Processor'

Un'altra possibilità è utilizzare dmidecode per filtrare le informazioni sul processore.

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.