Ermitteln Sie programmgesteuert die Anzahl der Kerne auf einer Maschine
464
Gibt es eine Möglichkeit, plattformunabhängig zu bestimmen, wie viele Kerne eine Maschine aus C / C ++ hat? Wenn es so etwas nicht gibt, wie wäre es dann mit der Ermittlung pro Plattform (Windows / * nix / Mac)?
Wenn Sie es verwenden möchten, um herauszufinden, wie viele Threads gestartet werden sollen, verwenden Sie bitte NUMBER_OF_PROCESSORS als primäre Kennzahl. Ich überlasse es Ihnen als Übung, warum dies viel besser ist (wenn die Leute es mehr verwenden würden) als Hardware-Kerne zu verwenden. Wie viele Kerne zu Ihrem Programm gehören, ist ein Umweltproblem!
Lothar
Beachten Sie, dass std::thread::hardware_concurrencydie Anzahl der physischen CPU-Kerne zurückgegeben wird, nprocunter Linux jedoch nur die Anzahl der CPU-Kerne angezeigt wird, auf denen der aktuelle Prozess ausgeführt werden kann und mit denen gesteuert werden kann sched_setaffinity. Ich habe keinen Weg gefunden, dies stattdessen aus Standard-C ++ zu erhalten: siehe z. B. in Python: stackoverflow.com/questions/1006289/…
Ciro Santilli 5 冠状 病 六四 事件 5
Antworten:
706
C ++ 11
#include<thread>//may return 0 when not able to detectconstauto processor_count = std::thread::hardware_concurrency();
In C ++ vor C ++ 11 gibt es keinen portablen Weg. Stattdessen müssen Sie eine oder mehrere der folgenden Methoden verwenden (geschützt durch entsprechende #ifdefZeilen):
Linux, Solaris, AIX und Mac OS X> = 10.4 (dh Tiger ab)
int numCPU = sysconf(_SC_NPROCESSORS_ONLN);
FreeBSD, MacOS X, NetBSD, OpenBSD usw.
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 oder iOS)
NSUInteger a =[[NSProcessInfo processInfo] processorCount];NSUInteger b =[[NSProcessInfo processInfo] activeProcessorCount];
@mcandre: Das bleibt als Übung für den Leser. Wenn ich implementieren würde, würde ich wahrscheinlich einen Vorlagenrichtlinienansatz verwenden, bei dem die Richtlinie in Präprozessoranweisungen definiert wurde. Oder ... Sie könnten boost thread :: hardware_concurrency () verwenden.
paxos1977
3
Zur Verdeutlichung gibt die Win32-Lösung die Gesamtzahl der Kerne (was angefordert wurde) und nicht die Gesamtzahl der physischen CPUs zurück.
Eric
1
Die Linux / Solaris / AIX-Methode funktioniert auch unter FreeBSD und ist seit mindestens 2006 verfügbar. Außerdem werden die CPUs online zurückgegeben, wenn ein System in der Lage ist, einige auszuschalten, werden sie möglicherweise nicht gezählt. Wenn Sie sysconf mit "_SC_NPROCESSORS_CONF" aufrufen, werden die insgesamt konfigurierten CPUs zurückgegeben.
Chris S
3
Ein paar Dinge, die Sie beachten sollten. HW_NCPUist unter OS X veraltet. Unter Windows GetSystemInfoist es nur nützlich, wenn Ihr System über 32 logische Prozessoren oder weniger verfügt. Verwenden Sie es GetLogicalProcessorInformationfür Systeme mit mehr als 32 logischen Prozessoren.
1
@Trejkaz die Dokumentation sagt deutlich "logisch" - was immer HT-Kerne zählt, das Wort "physisch" bezieht sich immer auf Kerne, die vom BIOS / UEFI gemeldet werden, da Kerne auch emuliert / virtualisiert werden können. Sie können beispielsweise mit Funktionen wie GetLogicalProcessorInformation zwischen HT- und Nicht-HT-Kernen unterscheiden . Hinweis: HT! = Emulation oder Virtualisierung, das ist ein großer Unterschied, HT ist sozusagen eine Hardwareoptimierung
spezialisiert auf den
202
Diese Funktionalität ist Teil des C ++ 11-Standards.
Gibt in beiden Fällen hardware_concurrency()die Anzahl der Threads zurück, die die Hardware gleichzeitig ausführen kann, basierend auf der Anzahl der CPU-Kerne und Hyper-Threading-Einheiten.
Seconded ... wollte den obigen Beispielcode und einige Präprozessor-Makros verwenden, um eine einzelne Funktion verfügbar zu machen, aber die harte Arbeit wurde für mich erledigt.
JKP
Für win32 ist es ein Aufruf von GetSystemInfo. (Ab Boost Version 1.41.0) Erfasst das alle Informationen, um zu bestimmen, wie viele Arbeitsthreads effektiv wären? Muss man sowohl die Anzahl der Kerne als auch das Hyper-Threading berücksichtigen? unsigned thread :: hardware_concurrency () {SYSTEM_INFO info = {0}; GetSystemInfo (& info); return info.dwNumberOfProcessors; }
Jive Dadson
Laut MSDN gibt GetSystemInfo () die Anzahl der "physischen Prozessoren" in dwNumberOfProcessors zurück, definiert jedoch nicht, was dies bedeutet. Die Boost-Dokumentation scheint zu behaupten, dass sie Hyperthreading-Einheiten enthält.
weil es eine falsche Antwort ist. Von gcc.gnu.org/bugzilla/show_bug.cgi?id=37586 "omp_get_num_procs () gibt nur dann eine geringere Anzahl als die Anzahl der Online-System-CPUs zurück, wenn GOMP_CPU_AFFINITY env var verwendet wird oder wenn der aufrufende Prozess und / oder Thread verwendet wird CPU-Affinität auf eine Teilmenge von CPUs beschränkt ". Wenn Sie also früher anrufen, z. B. sched_setaffinityfunktioniert dies nicht.
Angainor
7
Diese Funktion gibt die Anzahl der für den aufrufenden Prozess verfügbaren CPUs zurück. Ist es nicht sowieso der häufigste Anwendungsfall? Aufgrund der Größe einiger nutzloser Berichtszwecke ist die tatsächliche Anzahl der CPU-Hardwarekerne für Sie nicht relevant, wenn Sie sie in Ihrem Code nicht nutzen können.
Macbirdie
@EvanTeran Neben der Tatsache, dass es der Zweck der Frage war, kann es natürlich nützlich sein. Zum Beispiel zum Einstellen der Thread-Affinität. Angenommen, ich möchte 4 Threads ausführen, die an vier letzte CPU-Kerne auf meinem Computer gebunden sind, anstatt vier erste Kerne. Außerdem gibt es außer OpenMP andere Möglichkeiten, den Code zu parallelisieren. Ich möchte vielleicht selbst Pthreads erzeugen. Diese sind sicherlich verfügbar und nicht durch OpenMP-Umgebungsvariablen eingeschränkt.
Angainor
2
Dies gibt die Anzahl der logischen CPUs zurück, nicht die Kerne (physische CPUs) als solche.
Michael Konečný
37
Wenn Sie Zugriff auf Assemblersprache haben, können Sie den CPUID-Befehl verwenden, um alle möglichen Informationen über die CPU abzurufen. Es ist zwischen Betriebssystemen portierbar, obwohl Sie herstellerspezifische Informationen verwenden müssen, um die Anzahl der Kerne zu ermitteln. Hier ist ein Dokument, das beschreibt, wie es auf Intel-Chips gemacht wird , und Seite 11 dieses Dokuments beschreibt die AMD-Spezifikation.
Es wurde möglicherweise abgelehnt, weil die Frage als C ++ gekennzeichnet ist und diese Antwort nicht für Systeme gilt, auf denen C ++ auf Nicht-x86-Architekturen (ARM, PPC usw.) ausgeführt wird. Ich sage nicht, dass es ein guter Grund ist, eine Antwort abzulehnen, nur eine Möglichkeit.
Ferruccio
3
Eine Gefahr dieser Methode besteht darin, dass Sie CPUT verwenden, um HyperThreading auf Intel-Prozessoren zu erkennen. Auf meinem Laptop ist dieses Problem aufgetreten: Während die CPU, die ich in den Computer eingebaut habe, HyperThreading unterstützt (und natürlich meldet, dass dies über die CPUID erfolgt), funktioniert dies im BIOS nicht. Daher sollten Sie nicht versuchen, die HT-Funktion einfach über einen CPUID-Lesevorgang zu nutzen. Da Sie das BIOS nicht nach der HT-Unterstützung abfragen können (wie ich es noch nicht gesehen habe), sollte das Betriebssystem abgefragt werden, um die Anzahl der logischen Prozessoren zu ermitteln.
Abgesehen davon, dass dies auch Hyperthreaded- oder andere SMT-Lösungen als weitere Kerne zählt ...
jakobengblom2
13
@Arafangion: Hyperthreading ist keine echte parallele Ausführung, sondern eine Technologie zur Reduzierung des Overheads bei der Kontextumschaltung. Eine Hyperthread-CPU kann jeweils nur einen Thread ausführen , jedoch den Architekturstatus (Registerwerte usw.) von zwei Threads gleichzeitig speichern. Die Leistungsmerkmale unterscheiden sich stark von denen mit zwei Kernen.
Wim Coenen
7
@ Wim: Das ist nicht ganz richtig. CPUs mit Hyperthreading haben im Allgemeinen mehrere ALUs und können mehrere Anweisungen pro Zyklus senden. Wenn aufgrund von Datenabhängigkeiten und Verzögerungen nicht alle ALUs von einem Thread belegt werden können, werden diese ALUs stattdessen für die gleichzeitige Ausführung des zweiten Hardware-Threads verwendet.
Ben Voigt
11
Beachten Sie, dass "Anzahl der Kerne" möglicherweise keine besonders nützliche Zahl ist. Möglicherweise müssen Sie sie etwas weiter qualifizieren. Wie möchten Sie Multithread-CPUs wie Intel HT, IBM Power5 und Power6 und vor allem Suns Niagara / UltraSparc T1 und T2 zählen? Oder noch interessanter ist das MIPS 1004k mit seinen zwei Hardware-Threading-Ebenen (Supervisor- UND Benutzerebene) ... Ganz zu schweigen davon, was passiert, wenn Sie auf von Hypervisor unterstützte Systeme umsteigen, auf denen die Hardware möglicherweise mehrere zehn CPUs hat, aber Ihr spezielles Betriebssystem sieht nur wenige.
Das Beste, auf das Sie hoffen können, ist, die Anzahl der logischen Verarbeitungseinheiten in Ihrer lokalen Betriebssystempartition anzugeben. Vergessen Sie, die wahre Maschine zu sehen, es sei denn, Sie sind ein Hypervisor. Die einzige Ausnahme von dieser Regel ist heute in x86-Land, aber das Ende nicht virtueller Maschinen kommt schnell ...
Beachten Sie, dass die Implementierung von NumberOfPhysicalCoresIMHO alles andere als trivial ist (dh "use GetLogicalProcessorInformationor GetLogicalProcessorInformationEx"). Stattdessen ist es ziemlich subtil, wenn man die Dokumentation (explizit vorhanden für GetLogicalProcessorInformationund implizit vorhanden für GetLogicalProcessorInformationEx) bei MSDN liest .
Die Anzahl der logischen Prozessoren. (Verwenden von GetSystemInfo )
Vielen Dank! Ich habe danach gesucht, weil ich GetLogicalProcessorInformationnicht mit verschiedenen Puffergrößen gearbeitet habe, die ich verwendet habe. Mehr als zufrieden! ^^
KeyWeeUsr
@KeyWeeUsr Dank Windows-Programmierung ist alles andere als trivial und logisch. In der Zwischenzeit verwende ich eine etwas aktuellere C ++ 17-Version, die laut dem statischen Analysator PVS-Studio in Bezug auf einige size_tCasts auch korrekter ist . (Obwohl sich msvc ++ bei W4 nicht beschwert.)
Matthias
5
Mehr zu OS X: sysconf(_SC_NPROCESSORS_ONLN) ist nur für Versionen> = 10.5 verfügbar, nicht für 10.4.
Eine Alternative ist der HW_AVAILCPU/sysctl()BSD-Code, der in Versionen> = 10.2 verfügbar ist.
Für Python:import multiprocessingprint multiprocessing.cpu_count()
Initzero
3
Es ist schon eine lange Zeit, aber grephat -cFlagge zu zählen Einträge!
Lapshin Dmitry
3
hwloc (http://www.open-mpi.org/projects/hwloc/) ist einen Blick wert. Erfordert zwar eine weitere Bibliotheksintegration in Ihren Code, kann jedoch alle Informationen zu Ihrem Prozessor (Anzahl der Kerne, Topologie usw.) bereitstellen.
Unter Linux ist die Verwendung möglicherweise nicht sicher, _SC_NPROCESSORS_ONLNda es nicht Teil des POSIX-Standards ist und das sysconf- Handbuch dies auch angibt. Es gibt also eine Möglichkeit, die _SC_NPROCESSORS_ONLNmöglicherweise nicht vorhanden ist:
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).
Ein einfacher Ansatz wäre, sie zu lesen /proc/statoder zu /proc/cpuinfozählen:
#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;}
Verwenden von /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;}
Der gleiche Ansatz in der Shell mit grep:
grep -c ^processor /proc/cpuinfo
Oder
grep -c ^cpu /proc/stat # subtract 1 from the result
OS X-Alternative: Die zuvor beschriebene Lösung basierend auf [[NSProcessInfo processInfo] processorCount] ist gemäß den Dokumenten nur unter OS X 10.5.0 verfügbar. Verwenden Sie für frühere Versionen von OS X die Carbon-Funktion MPProcessors ().
Wenn Sie ein Kakao-Programmierer sind, lassen Sie sich nicht von der Tatsache ausflippen, dass dies Carbon ist. Sie müssen lediglich das Carbon-Framework zu Ihrem Xcode-Projekt hinzufügen, und MPProcessors () ist verfügbar.
Während GetSystemInfo () die Anzahl der logischen Prozessoren ermittelt, verwenden Sie
GetLogicalProcessorInformationEx ()
, um die Anzahl der physischen Prozessoren abzurufen .
Sie können WMI auch in .net verwenden, sind dann aber auf den ausgeführten wmi-Dienst usw. angewiesen. Manchmal funktioniert es lokal, schlägt jedoch fehl, wenn derselbe Code auf Servern ausgeführt wird. Ich glaube, das ist ein Namespace-Problem, das mit den "Namen" zusammenhängt, deren Werte Sie lesen.
std::thread::hardware_concurrency
die Anzahl der physischen CPU-Kerne zurückgegeben wird,nproc
unter Linux jedoch nur die Anzahl der CPU-Kerne angezeigt wird, auf denen der aktuelle Prozess ausgeführt werden kann und mit denen gesteuert werden kannsched_setaffinity
. Ich habe keinen Weg gefunden, dies stattdessen aus Standard-C ++ zu erhalten: siehe z. B. in Python: stackoverflow.com/questions/1006289/…Antworten:
C ++ 11
Referenz: std :: thread :: hardware_concurrency
In C ++ vor C ++ 11 gibt es keinen portablen Weg. Stattdessen müssen Sie eine oder mehrere der folgenden Methoden verwenden (geschützt durch entsprechende
#ifdef
Zeilen):Win32
Linux, Solaris, AIX und Mac OS X> = 10.4 (dh Tiger ab)
FreeBSD, MacOS X, NetBSD, OpenBSD usw.
HPUX
IRIX
Objective-C (Mac OS X> = 10,5 oder iOS)
quelle
HW_NCPU
ist unter OS X veraltet. Unter WindowsGetSystemInfo
ist es nur nützlich, wenn Ihr System über 32 logische Prozessoren oder weniger verfügt. Verwenden Sie esGetLogicalProcessorInformation
für Systeme mit mehr als 32 logischen Prozessoren.Diese Funktionalität ist Teil des C ++ 11-Standards.
Für ältere Compiler können Sie die Boost.Thread- Bibliothek verwenden.
Gibt in beiden Fällen
hardware_concurrency()
die Anzahl der Threads zurück, die die Hardware gleichzeitig ausführen kann, basierend auf der Anzahl der CPU-Kerne und Hyper-Threading-Einheiten.quelle
OpenMP wird auf vielen Plattformen (einschließlich Visual Studio 2005) unterstützt und bietet eine
Funktion, die die Anzahl der zum Zeitpunkt des Aufrufs verfügbaren Prozessoren / Kerne zurückgibt.
quelle
sched_setaffinity
funktioniert dies nicht.Wenn Sie Zugriff auf Assemblersprache haben, können Sie den CPUID-Befehl verwenden, um alle möglichen Informationen über die CPU abzurufen. Es ist zwischen Betriebssystemen portierbar, obwohl Sie herstellerspezifische Informationen verwenden müssen, um die Anzahl der Kerne zu ermitteln. Hier ist ein Dokument, das beschreibt, wie es auf Intel-Chips gemacht wird , und Seite 11 dieses Dokuments beschreibt die AMD-Spezifikation.
quelle
(Fast) Plattformunabhängige Funktion im C-Code
quelle
HW_NCPU
veraltet auf OS X QuelleUnter Linux können Sie die Datei / proc / cpuinfo lesen und die Kerne zählen.
quelle
Beachten Sie, dass "Anzahl der Kerne" möglicherweise keine besonders nützliche Zahl ist. Möglicherweise müssen Sie sie etwas weiter qualifizieren. Wie möchten Sie Multithread-CPUs wie Intel HT, IBM Power5 und Power6 und vor allem Suns Niagara / UltraSparc T1 und T2 zählen? Oder noch interessanter ist das MIPS 1004k mit seinen zwei Hardware-Threading-Ebenen (Supervisor- UND Benutzerebene) ... Ganz zu schweigen davon, was passiert, wenn Sie auf von Hypervisor unterstützte Systeme umsteigen, auf denen die Hardware möglicherweise mehrere zehn CPUs hat, aber Ihr spezielles Betriebssystem sieht nur wenige.
Das Beste, auf das Sie hoffen können, ist, die Anzahl der logischen Verarbeitungseinheiten in Ihrer lokalen Betriebssystempartition anzugeben. Vergessen Sie, die wahre Maschine zu sehen, es sei denn, Sie sind ein Hypervisor. Die einzige Ausnahme von dieser Regel ist heute in x86-Land, aber das Ende nicht virtueller Maschinen kommt schnell ...
quelle
Noch ein Windows-Rezept: Verwenden Sie die systemweite Umgebungsvariable
NUMBER_OF_PROCESSORS
:quelle
Sie werden es wahrscheinlich nicht plattformunabhängig bekommen können. Windows erhalten Sie Anzahl der Prozessoren.
Win32-Systeminformationen
quelle
Windows (x64 und Win32) und C ++ 11
Die Anzahl der Gruppen logischer Prozessoren, die sich einen einzelnen Prozessorkern teilen. (Verwenden von GetLogicalProcessorInformationEx , siehe auch GetLogicalProcessorInformation )
Beachten Sie, dass die Implementierung von
NumberOfPhysicalCores
IMHO alles andere als trivial ist (dh "useGetLogicalProcessorInformation
orGetLogicalProcessorInformationEx
"). Stattdessen ist es ziemlich subtil, wenn man die Dokumentation (explizit vorhanden fürGetLogicalProcessorInformation
und implizit vorhanden fürGetLogicalProcessorInformationEx
) bei MSDN liest .Die Anzahl der logischen Prozessoren. (Verwenden von GetSystemInfo )
Beachten Sie, dass beide Methoden problemlos in C / C ++ 98 / C ++ 03 konvertiert werden können.
quelle
GetLogicalProcessorInformation
nicht mit verschiedenen Puffergrößen gearbeitet habe, die ich verwendet habe. Mehr als zufrieden! ^^size_t
Casts auch korrekter ist . (Obwohl sich msvc ++ bei W4 nicht beschwert.)Mehr zu OS X:
sysconf(_SC_NPROCESSORS_ONLN)
ist nur für Versionen> = 10.5 verfügbar, nicht für 10.4.Eine Alternative ist der
HW_AVAILCPU/sysctl()
BSD-Code, der in Versionen> = 10.2 verfügbar ist.quelle
Mit Windows Server 2003 und höher können Sie die Funktion GetLogicalProcessorInformation nutzen
http://msdn.microsoft.com/en-us/library/ms683194.aspx
quelle
Nicht mit C ++ verwandt, aber unter Linux mache ich normalerweise:
Praktisch für Skriptsprachen wie bash / perl / python / ruby.
quelle
import multiprocessing
print multiprocessing.cpu_count()
grep
hat-c
Flagge zu zählen Einträge!hwloc (http://www.open-mpi.org/projects/hwloc/) ist einen Blick wert. Erfordert zwar eine weitere Bibliotheksintegration in Ihren Code, kann jedoch alle Informationen zu Ihrem Prozessor (Anzahl der Kerne, Topologie usw.) bereitstellen.
quelle
Unter Linux ist die beste programmatische Methode, soweit ich weiß, die Verwendung
oder
Diese sind nicht Standard, befinden sich aber in meiner Manpage für Linux.
quelle
Unter Linux ist die Verwendung möglicherweise nicht sicher,
_SC_NPROCESSORS_ONLN
da es nicht Teil des POSIX-Standards ist und das sysconf- Handbuch dies auch angibt. Es gibt also eine Möglichkeit, die_SC_NPROCESSORS_ONLN
möglicherweise nicht vorhanden ist:Ein einfacher Ansatz wäre, sie zu lesen
/proc/stat
oder zu/proc/cpuinfo
zählen:Verwenden von
/proc/cpuinfo
:Der gleiche Ansatz in der Shell mit grep:
Oder
quelle
OS X-Alternative: Die zuvor beschriebene Lösung basierend auf [[NSProcessInfo processInfo] processorCount] ist gemäß den Dokumenten nur unter OS X 10.5.0 verfügbar. Verwenden Sie für frühere Versionen von OS X die Carbon-Funktion MPProcessors ().
Wenn Sie ein Kakao-Programmierer sind, lassen Sie sich nicht von der Tatsache ausflippen, dass dies Carbon ist. Sie müssen lediglich das Carbon-Framework zu Ihrem Xcode-Projekt hinzufügen, und MPProcessors () ist verfügbar.
quelle
Für Win32:
Während GetSystemInfo () die Anzahl der logischen Prozessoren ermittelt, verwenden Sie GetLogicalProcessorInformationEx () , um die Anzahl der physischen Prozessoren abzurufen .
quelle
Sie können WMI auch in .net verwenden, sind dann aber auf den ausgeführten wmi-Dienst usw. angewiesen. Manchmal funktioniert es lokal, schlägt jedoch fehl, wenn derselbe Code auf Servern ausgeführt wird. Ich glaube, das ist ein Namespace-Problem, das mit den "Namen" zusammenhängt, deren Werte Sie lesen.
quelle
Unter Linux können Sie dmesg auschecken und die Zeilen filtern, in denen ACPI die CPUs initialisiert.
dmesg | grep 'ACPI: Processor
'Eine andere Möglichkeit besteht darin, dmidecode zum Herausfiltern der Prozessorinformationen zu verwenden.
quelle