Trouver par programme le nombre de cœurs sur une machine
464
Existe-t-il un moyen de déterminer le nombre de cœurs d'une machine en C / C ++ de manière indépendante de la plate-forme? Si une telle chose n'existe pas, qu'en est-il de la déterminer par plate-forme (Windows / * nix / Mac)?
Si vous voulez l'utiliser, découvrez combien de threads commencer, veuillez utiliser NUMBER_OF_PROCESSORS comme mesure principale. Je vous laisse comme un exercice pourquoi cela est beaucoup mieux (si les gens l'utilisent plus) que d'utiliser des cœurs matériels. Combien de cœurs appartiennent à votre programme sont un problème environnemental!
Lothar
Notez que std::thread::hardware_concurrencyrenvoie le nombre de cœurs de processeur physiques, mais nprocsous Linux affiche uniquement le nombre de cœurs de processeur sur lesquels le processus en cours peut s'exécuter, qui peut être contrôlé avec sched_setaffinity. Je n'ai pas trouvé de moyen d'obtenir cela à la place du C ++ standard, voir par exemple dans Python: stackoverflow.com/questions/1006289/…
Ciro Santilli 郝海东 冠状 病 六四 事件 法轮功
Réponses:
706
C ++ 11
#include<thread>//may return 0 when not able to detectconstauto processor_count = std::thread::hardware_concurrency();
En C ++ avant C ++ 11, il n'y a pas de moyen portable. À la place, vous devrez utiliser une ou plusieurs des méthodes suivantes (protégées par des #ifdeflignes appropriées ):
Linux, Solaris, AIX et Mac OS X> = 10,4 (c'est-à-dire Tiger à partir de)
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];
@mcandre: cela reste un exercice pour le lecteur. Si je l'implémentais, j'utiliserais probablement une approche de modèle de politique où la politique était définie dans les directives du préprocesseur. Ou ... vous pouvez utiliser boost thread :: hardware_concurrency ().
paxos1977
3
à titre de clarification, la solution Win32 renvoie le nombre total de cœurs (ce qui a été demandé) et non le nombre total de CPU physiques.
Eric
1
La méthode Linux / Solaris / AIX fonctionne également sur FreeBSD et a depuis au moins 2006. De plus, cela rendra les CPU en ligne, si un système est capable de désactiver certains, ils pourraient ne pas être comptés. L'appel de sysconf avec "_SC_NPROCESSORS_CONF" renverra le nombre total de CPU configurés.
Chris S
3
Quelques choses à savoir. HW_NCPUest déconseillé sous OS X. Sous Windows, il GetSystemInfon'est utile que si votre système dispose de 32 processeurs logiques ou moins, à utiliser GetLogicalProcessorInformationpour les systèmes qui ont plus de 32 processeurs logiques.
1
@Trejkaz la documentaion dit clairement "logique" - qui compte toujours les cœurs HT, le mot "physique" fait toujours référence aux cœurs signalés par le BIOS / UEFI car les cœurs peuvent également être émulés / virtualisés. Vous pouvez différencier les cœurs HT / non-HT avec des fonctions comme GetLogicalProcessorInformation , par exemple. Remarque: HT! = Émulation ou virtualisation, c'est une grande différence, HT est une optimisation matérielle, pour ainsi dire
specializt
202
Cette fonctionnalité fait partie de la norme C ++ 11.
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.
Secondé ... allait utiliser l'exemple de code ci-dessus et certaines macros de préprocesseur pour exposer une seule fonction, mais le travail a été fait pour moi.
jkp
Pour win32, c'est un appel à GetSystemInfo. (À partir de la version 1.41.0 de boost) Est-ce que cela capture toutes les informations pour déterminer combien de threads de travail seraient efficaces? Faut-il considérer à la fois le nombre de cœurs et l'hyper-threading? thread non signé :: hardware_concurrency () {SYSTEM_INFO info = {0}; GetSystemInfo (& info); return info.dwNumberOfProcessors; }
Jive Dadson
Selon MSDN, GetSystemInfo () renvoie le nombre de "processeurs physiques" dans dwNumberOfProcessors mais il ne définit pas ce que cela signifie par cela. La documentation Boost semble prétendre qu'elle comprend des unités d'hyperthreading.
parce que c'est une mauvaise réponse. Depuis gcc.gnu.org/bugzilla/show_bug.cgi?id=37586 "omp_get_num_procs () ne renverra qu'un nombre inférieur au nombre de CPU système en ligne, si GOMP_CPU_AFFINITY env var est utilisé, ou si le processus d'appel et / ou le thread a Affinité CPU limitée à un sous-ensemble de CPU ". Donc, si vous appelez plus tôt, par exemple, sched_setaffinitycela ne fonctionnera pas.
angainor
7
Cette fonction renvoie le nombre de CPU disponibles pour le processus appelant. N'est-ce pas le cas d'utilisation le plus courant? Surdimensionné à des fins de rapport inutiles, le nombre réel de cœurs de matériel CPU ne vous concerne pas si vous ne pouvez pas en tirer parti dans votre code.
macbirdie
@EvanTeran Outre le fait que c'était le but de la question, cela peut bien sûr être utile. Par exemple, dans le but de définir l'affinité de thread. Dites, je veux exécuter 4 threads liés à quatre derniers cœurs de processeur sur ma machine, au lieu de quatre premiers cœurs. Et en plus, il existe d'autres façons de paralléliser le code à l'exception d'OpenMP. Je veux peut-être générer des pthreads moi-même. Celles-ci sont sûrement disponibles et ne sont pas limitées par les variables d'environnement OpenMP.
angainor
2
Cela renvoie le nombre de CPU logiques, pas les cœurs (CPU physiques) en tant que tels.
Michael Konečný
37
Si vous disposez d'un accès en langage assembleur, vous pouvez utiliser l'instruction CPUID pour obtenir toutes sortes d'informations sur le processeur. Il est portable entre les systèmes d'exploitation, mais vous devrez utiliser des informations spécifiques au fabricant pour déterminer comment trouver le nombre de cœurs. Voici un document qui décrit comment le faire sur des puces Intel , et la page 11 de celui-ci décrit la spécification AMD.
Il a peut-être été déclassé car la question est balisée en C ++ et cette réponse ne s'applique pas aux systèmes exécutant C ++ sur des architectures non x86 (ARM, PPC, etc.). Je ne dis pas que c'est une bonne raison de voter contre une réponse, juste une possibilité.
Ferruccio
3
Un écueil de cette méthode est que si vous utilisez CPUID pour détecter HyperThreading sur les processeurs Intel. J'ai rencontré ce problème sur mon ordinateur portable: alors que le CPU que j'ai mis dans la machine prend en charge HyperThreading (et, bien sûr, signale qu'il le fait via CPUID), le BIOS ne le fait pas. Par conséquent, vous ne devriez pas essayer d'utiliser la capacité HT simplement à partir d'une lecture CPUID. Comme vous ne pouvez pas interroger le BIOS sur la prise en charge HT (pas du tout ce que j'ai vu), le système d'exploitation doit être interrogé pour obtenir le nombre de processeurs logiques.
Chuck R
32
(Presque) Fonction indépendante de la plateforme en code C
Sauf que ça compte aussi les solutions hyperthreadées ou autres solutions SMT comme plus de cœurs ...
jakobengblom2
13
@Arafangion: l'hyperthreading n'est pas une véritable exécution parallèle, c'est une technologie pour réduire les frais généraux de commutation de contexte. Un processeur hyperthreadé ne peut exécuter qu'un seul thread à la fois, mais il peut stocker l'état architectural (valeurs de registre, etc.) de deux threads en même temps. Les caractéristiques de performance sont très différentes d'avoir deux cœurs.
Wim Coenen
7
@Wim: Ce n'est pas tout à fait correct. Les CPU avec hyperthreading ont généralement plusieurs ALU et peuvent envoyer plusieurs instructions par cycle. Si, en raison des dépendances de données et des blocages, toutes les ALU ne peuvent pas être occupées par un seul thread, ces ALU seront plutôt utilisées pour l'exécution simultanée du deuxième thread matériel.
Ben Voigt
11
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 multithread tels que Intel HT, IBM Power5 et Power6, et surtout, les 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 supportés par hyperviseur où le matériel peut avoir des dizaines de CPU mais votre OS 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 à moins que vous ne soyez un hyperviseur. La seule exception à cette règle est aujourd'hui en terre x86, mais la fin des machines non virtuelles arrive rapidement ...
Notez que la mise en œuvre de NumberOfPhysicalCoresest à mon humble avis loin d'être triviale (c'est-à-dire "utiliser GetLogicalProcessorInformationou GetLogicalProcessorInformationEx"). Au lieu de cela, il est plutôt subtil si on lit la documentation (explicitement présente pour GetLogicalProcessorInformationet implicitement présente pour GetLogicalProcessorInformationEx) sur MSDN.
Le nombre de processeurs logiques. (Utilisation de GetSystemInfo )
Je vous remercie! Je cherchais cela parce que je GetLogicalProcessorInformationne travaillais pas avec les différentes tailles de tampons que j'utilisais. Plus que satisfait! ^^
KeyWeeUsr
@KeyWeeUsr Merci La programmation Windows est quelque peu loin d'être triviale et logique. En attendant, j'utilise une version C ++ 17 légèrement plus mise à jour qui est aussi plus correcte selon l'analyseur statique PVS-Studio en ce qui concerne certains size_tcasts. (Bien que msvc ++ ne se plaigne pas à W4.)
Matthias
5
Plus sur OS X: sysconf(_SC_NPROCESSORS_ONLN)est disponible uniquement les versions> = 10.5, pas 10.4.
Une alternative est le HW_AVAILCPU/sysctl()code BSD qui est disponible sur les versions> = 10.2.
Pour python:import multiprocessingprint multiprocessing.cpu_count()
initzero
3
Cela fait longtemps, mais grepa un -cdrapeau pour compter les entrées!
Lapshin Dmitry
3
hwloc (http://www.open-mpi.org/projects/hwloc/) mérite d'être examiné. Bien qu'il nécessite une autre intégration de bibliothèque dans votre code mais il peut fournir toutes les informations sur votre processeur (nombre de cœurs, topologie, etc.)
Sous Linux, il n'est peut-être pas sûr de l'utiliser _SC_NPROCESSORS_ONLNcar il ne fait pas partie de la norme POSIX et le manuel sysconf l' indique autant. Il y a donc une possibilité qui _SC_NPROCESSORS_ONLNpeut ne pas être présente:
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 serait de les lire /proc/statou de les /proc/cpuinfocompter:
#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);return0;}
En utilisant /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);return0;}
La même approche en shell utilisant grep:
grep -c ^processor /proc/cpuinfo
Ou
grep -c ^cpu /proc/stat # subtract 1 from the result
Alternative à OS X: La solution décrite précédemment basée sur [[NSProcessInfo processInfo] processorCount] n'est disponible que sur OS X 10.5.0, selon la documentation. Pour les versions antérieures d'OS X, utilisez la fonction Carbon MPProcessors ().
Si vous êtes un programmeur Cocoa, ne soyez pas paniqué par le fait qu'il s'agit de Carbon. Vous avez juste besoin d'ajouter le framework Carbon à votre projet Xcode et MPProcessors () sera disponible.
Alors que GetSystemInfo () vous obtient le nombre de processeurs logiques , utilisez
GetLogicalProcessorInformationEx ()
pour obtenir le nombre de processeurs physiques .
vous pouvez également utiliser WMI dans .net mais vous dépendez alors du service wmi en cours d'exécution, etc. Parfois, cela fonctionne localement, mais échoue lorsque le même code est exécuté sur des serveurs. Je crois que c'est un problème d'espace de noms, lié aux "noms" dont vous lisez les valeurs.
std::thread::hardware_concurrency
renvoie le nombre de cœurs de processeur physiques, maisnproc
sous Linux affiche uniquement le nombre de cœurs de processeur sur lesquels le processus en cours peut s'exécuter, qui peut être contrôlé avecsched_setaffinity
. Je n'ai pas trouvé de moyen d'obtenir cela à la place du C ++ standard, voir par exemple dans Python: stackoverflow.com/questions/1006289/…Réponses:
C ++ 11
Référence: std :: thread :: hardware_concurrency
En C ++ avant C ++ 11, il n'y a pas de moyen portable. À la place, vous devrez utiliser une ou plusieurs des méthodes suivantes (protégées par des
#ifdef
lignes appropriées ):Win32
Linux, Solaris, AIX et Mac OS X> = 10,4 (c'est-à-dire Tiger à partir de)
FreeBSD, MacOS X, NetBSD, OpenBSD, etc.
HPUX
IRIX
Objective-C (Mac OS X> = 10.5 ou iOS)
la source
HW_NCPU
est déconseillé sous OS X. Sous Windows, ilGetSystemInfo
n'est utile que si votre système dispose de 32 processeurs logiques ou moins, à utiliserGetLogicalProcessorInformation
pour les systèmes qui ont plus de 32 processeurs logiques.Cette fonctionnalité fait partie de la norme C ++ 11.
Pour les compilateurs plus anciens, vous pouvez utiliser la bibliothèque Boost.Thread .
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.la source
OpenMP est pris en charge sur de nombreuses plates-formes (y compris Visual Studio 2005) et il offre un
fonction qui renvoie le nombre de processeurs / cœurs disponibles au moment de l'appel.
la source
sched_setaffinity
cela ne fonctionnera pas.Si vous disposez d'un accès en langage assembleur, vous pouvez utiliser l'instruction CPUID pour obtenir toutes sortes d'informations sur le processeur. Il est portable entre les systèmes d'exploitation, mais vous devrez utiliser des informations spécifiques au fabricant pour déterminer comment trouver le nombre de cœurs. Voici un document qui décrit comment le faire sur des puces Intel , et la page 11 de celui-ci décrit la spécification AMD.
la source
(Presque) Fonction indépendante de la plateforme en code C
la source
HW_NCPU
obsolète sur la sourceSous Linux, vous pouvez lire le fichier / proc / cpuinfo et compter les cœurs.
la source
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 multithread tels que Intel HT, IBM Power5 et Power6, et surtout, les 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 supportés par hyperviseur où le matériel peut avoir des dizaines de CPU mais votre OS 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 à moins que vous ne soyez un hyperviseur. La seule exception à cette règle est aujourd'hui en terre x86, mais la fin des machines non virtuelles arrive rapidement ...
la source
Encore une recette Windows: utilisez la variable d'environnement à l'échelle du système
NUMBER_OF_PROCESSORS
:la source
Vous ne pourrez probablement pas l'obtenir de manière indépendante de la plate-forme. Windows vous obtenez un certain nombre de processeurs.
Informations système Win32
la source
Windows (x64 et Win32) et C ++ 11
Nombre de groupes de processeurs logiques partageant un seul cœur de processeur. (À l'aide de GetLogicalProcessorInformationEx , consultez également GetLogicalProcessorInformation )
Notez que la mise en œuvre de
NumberOfPhysicalCores
est à mon humble avis loin d'être triviale (c'est-à-dire "utiliserGetLogicalProcessorInformation
ouGetLogicalProcessorInformationEx
"). Au lieu de cela, il est plutôt subtil si on lit la documentation (explicitement présente pourGetLogicalProcessorInformation
et implicitement présente pourGetLogicalProcessorInformationEx
) sur MSDN.Le nombre de processeurs logiques. (Utilisation de GetSystemInfo )
Notez que les deux méthodes peuvent facilement être converties en C / C ++ 98 / C ++ 03.
la source
GetLogicalProcessorInformation
ne travaillais pas avec les différentes tailles de tampons que j'utilisais. Plus que satisfait! ^^size_t
casts. (Bien que msvc ++ ne se plaigne pas à W4.)Plus sur OS X:
sysconf(_SC_NPROCESSORS_ONLN)
est disponible uniquement les versions> = 10.5, pas 10.4.Une alternative est le
HW_AVAILCPU/sysctl()
code BSD qui est disponible sur les versions> = 10.2.la source
Windows Server 2003 et versions ultérieures vous permettent de tirer parti de la fonction GetLogicalProcessorInformation
http://msdn.microsoft.com/en-us/library/ms683194.aspx
la source
Sans rapport avec C ++, mais sous Linux, je fais habituellement:
Pratique pour les langages de script comme bash / perl / python / ruby.
la source
import multiprocessing
print multiprocessing.cpu_count()
grep
a un-c
drapeau pour compter les entrées!hwloc (http://www.open-mpi.org/projects/hwloc/) mérite d'être examiné. Bien qu'il nécessite une autre intégration de bibliothèque dans votre code mais il peut fournir toutes les informations sur votre processeur (nombre de cœurs, topologie, etc.)
la source
Sous Linux, la meilleure façon de programmation, pour autant que je sache, est d'utiliser
ou
Ce ne sont pas standard, mais sont dans ma page de manuel pour Linux.
la source
Sous Linux, il n'est peut-être pas sûr de l'utiliser
_SC_NPROCESSORS_ONLN
car il ne fait pas partie de la norme POSIX et le manuel sysconf l' indique autant. Il y a donc une possibilité qui_SC_NPROCESSORS_ONLN
peut ne pas être présente:Une approche simple serait de les lire
/proc/stat
ou de les/proc/cpuinfo
compter:En utilisant
/proc/cpuinfo
:La même approche en shell utilisant grep:
Ou
la source
Alternative à OS X: La solution décrite précédemment basée sur [[NSProcessInfo processInfo] processorCount] n'est disponible que sur OS X 10.5.0, selon la documentation. Pour les versions antérieures d'OS X, utilisez la fonction Carbon MPProcessors ().
Si vous êtes un programmeur Cocoa, ne soyez pas paniqué par le fait qu'il s'agit de Carbon. Vous avez juste besoin d'ajouter le framework Carbon à votre projet Xcode et MPProcessors () sera disponible.
la source
Pour Win32:
Alors que GetSystemInfo () vous obtient le nombre de processeurs logiques , utilisez GetLogicalProcessorInformationEx () pour obtenir le nombre de processeurs physiques .
la source
vous pouvez également utiliser WMI dans .net mais vous dépendez alors du service wmi en cours d'exécution, etc. Parfois, cela fonctionne localement, mais échoue lorsque le même code est exécuté sur des serveurs. Je crois que c'est un problème d'espace de noms, lié aux "noms" dont vous lisez les valeurs.
la source
Sous Linux, vous pouvez extraire dmesg et filtrer les lignes où ACPI initialise les CPU, quelque chose comme:
dmesg | grep 'ACPI: Processor
"Une autre possibilité consiste à utiliser dmidecode pour filtrer les informations du processeur.
la source