Wie erhalte ich die Anzahl der CPUs in Linux mit C?
Lesezeit: 7 Minuten
Treviño
Gibt es eine API, um die Anzahl der in Linux verfügbaren CPUs abzurufen? Ich meine, ohne /proc/cpuinfo oder eine andere Sys-Node-Datei zu verwenden …
Ich habe diese Implementierung mit sched.h gefunden:
int GetCPUCount()
{
cpu_set_t cs;
CPU_ZERO(&cs);
sched_getaffinity(0, sizeof(cs), &cs);
int count = 0;
for (int i = 0; i < 64; i++)
{
if (CPU_ISSET(i, &cs))
count++;
else
break;
}
return count;
}
Aber gibt es nicht etwas Höheres, das gemeinsame Bibliotheken verwendet?
Warum haben die Leute solche Angst, /proc zu verwenden? Jede Linux-Box, die ich in den letzten 15 Jahren gesehen habe, hat es, es ist immer auf dem neuesten Stand mit dem, was der Kernel weiß, und das Format der darin vorhandenen Dinge ändert sich nicht viel.
– chao
3. Januar 2011 um 16:58 Uhr
Ich finde es toll, dass du versuchst, verschiedene Vorgehensweisen zu lernen, aber versuchst du, das Rad neu zu erfinden?
– David Weiser
3. Januar 2011 um 17:09 Uhr
Siehe auch stackoverflow.com/questions/150355/…
– Jay Sullivan
1. Februar 2020 um 15:53 Uhr
/proc ist nicht portabel
– Edd Barrett
2. Juni 2021 um 11:07 Uhr
@cHao Weil /proc Cgroups ignoriert, was zu einer “Überbelegung” führen kann, wenn der Prozess mehr Threads ausführt, als ihm in der Cpuset-Cgroup gewährt werden.
– phzx_munki
14. Februar um 21:28 Uhr
chrisaycock
#include <unistd.h>
long number_of_processors = sysconf(_SC_NPROCESSORS_ONLN);
Diese Antwort liefert nicht das gleiche Ergebnis wie der in der Frage angegebene Ausschnitt. Wenn ein Prozess an eine Teilmenge der CPUs auf der Maschine gebunden ist, die verwendet wird tasksetdann die Methode mit sched_getaffinity() gibt die Anzahl der zugewiesenen CPUs an, während get_nprocs() gibt die Gesamtzahl der CPUs an, die der Maschine zur Verfügung stehen. Dies ist schlecht, wenn Sie dies verwenden, um sich für eine Reihe von Threads zu entscheiden, denn wenn nur ein einzelner Kern auf einer Maschine mit vielen Kernen zugewiesen wird, wird der Prozess ins Stocken geraten.
– Ed Bennett
1. September 2021 um 9:59 Uhr
Vikram.exe
Dieser Code (gezeichnet aus hier) sollte sowohl auf Windows- als auch auf *NIX-Plattformen funktionieren.
#ifdef _WIN32
#define WIN32_LEAN_AND_MEAN
#include <windows.h>
#else
#include <unistd.h>
#endif
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
int main() {
long nprocs = -1;
long nprocs_max = -1;
#ifdef _WIN32
#ifndef _SC_NPROCESSORS_ONLN
SYSTEM_INFO info;
GetSystemInfo(&info);
#define sysconf(a) info.dwNumberOfProcessors
#define _SC_NPROCESSORS_ONLN
#endif
#endif
#ifdef _SC_NPROCESSORS_ONLN
nprocs = sysconf(_SC_NPROCESSORS_ONLN);
if (nprocs < 1)
{
fprintf(stderr, "Could not determine number of CPUs online:\n%s\n",
strerror (errno));
exit (EXIT_FAILURE);
}
nprocs_max = sysconf(_SC_NPROCESSORS_CONF);
if (nprocs_max < 1)
{
fprintf(stderr, "Could not determine number of CPUs configured:\n%s\n",
strerror (errno));
exit (EXIT_FAILURE);
}
printf ("%ld of %ld processors online\n",nprocs, nprocs_max);
exit (EXIT_SUCCESS);
#else
fprintf(stderr, "Could not determine number of CPUs");
exit (EXIT_FAILURE);
#endif
}
Ich habe diesen Code vor langer Zeit von jemandem bekommen (erinnere mich nicht an den Namen).
– Vikram.exe
3. Januar 2011 um 18:10 Uhr
Ich bin mir nicht sicher, ob das Posten dieses Code-Snippets die Frage des OP wirklich beantwortet, obwohl sie möglicherweise einige nützliche Informationen daraus zurückentwickeln.
– MarkR
4. Januar 2011 um 6:47 Uhr
Ich stimme MarkR zu. Chrisaycock gibt eine prägnante Antwort.
– Zeiger
5. Juli 2012 um 17:41 Uhr
Sie sollten die verwenden #error Präprozessordirektive if _SC_NPROCESSORS_ONLN ist nicht definiert. Dies ist ein Kompilierzeitfehler, kein Laufzeitfehler.
– Guido Flohr
3. Februar 2019 um 11:43 Uhr
Verwenden /proc/cpuinfo ist die sauberste und tragbarste Lösung. Falls das Öffnen fehlschlägt, können Sie einfach von 1 CPU oder 2 CPUs ausgehen. Code, der davon abhängt, die Anzahl der CPUs für einen anderen Zweck als die Mikrooptimierung zu kennen (z. B. die Auswahl der idealen Anzahl von auszuführenden Threads), macht mit ziemlicher Sicherheit etwas Dummes.
Das _SC_NPROCESSORS_ONLN Lösung hängt von einem Nicht-Standard ab (glibc-spezifisch) sysconf Erweiterung, die eine viel größere Abhängigkeit als ist /proc (Alle Linux-Systeme haben /procaber einige haben nicht-glibc-libcs oder ältere glibc-Versionen, die fehlen _SC_NPROCESSORS_ONLN).
RCL
sched_affinity() Version, die Sie am Anfang erwähnen, ist immer noch besser als /proc/cpuinfo und/oder _SC_NPROCESSORS_ONLN da es nur CPUs zählt, die für einen bestimmten Prozess verfügbar sind (einige können durch deaktiviert werden sched_setaffinity() von einem externen Prozess aufgerufen). Die einzige Änderung wäre die Verwendung CPU_COUNT() statt zu tun CPU_ISSET in einer Schleife.
Peter Kordes
Persönlich für neuere Intel-CPUs (allgemein nicht x86, nur Intel) Ich benutze die EAX=0Bhcpuid Blatt. Sehen Wikipedia für einige Details darüber, welche Informationen Sie über die Kerne im aktuellen Socket-Aka-Paket erhalten. Auf einem Multi-Socket-System kann dies die Hälfte oder ein Viertel der systemweiten Anzahl physischer/logischer Kerne sein. Intel hat ein Whitepaper zum Aufzählen von CPUs mit Details darüber, was bei Multi-Socket-Systemen zu überprüfen ist. Dieser Code macht das nicht, er prüft nur ein Unterblatt (ECX=1).
#include <stdio.h>
int main()
{
unsigned int ncores=0,nthreads=0,ht=0;
asm volatile("cpuid": "=a" (ncores), "=b" (nthreads) : "a" (0xb), "c" (0x1) : );
ht=(ncores!=nthreads);
printf("Cores: %d\nThreads: %d\nHyperThreading: %s\n",ncores,nthreads,ht?"Yes":"No");
return 0;
}
Ausgabe:
Cores: 4
Threads: 8
HyperThreading: Yes
Damien Zamit
Keine der Antworten, die beinhalten sysconf(...) oder get_nprocs() sind korrekt, um die Anzahl der Prozessoren zu berücksichtigen, die durch die CPU-Affinität auf eine Aufgabe beschränkt sind.
Sie brauchen so etwas, um die Anzahl der für eine Aufgabe verfügbaren Prozessoren zu erhalten:
Wäre dies immer noch richtig, wenn der Prozess cpu_setaffinity aufgerufen hat, um die Anzahl der affinen CPUs zu beschränken?
– Benutzer1637056
10. August 2020 um 23:43 Uhr
Für den Test habe ich ein Bash-Skript while : ; do echo 0 > /sys/devices/system/cpu/cpu3/online && sleep 0.5 && echo 1 > /sys/devices/system/cpu/cpu3/online ; sleep 0.5 ; echo Hey! ; done ; es schaltet CPU3 sehr schnell aus und ein. sysconf(_SC_NPROCESSORS_ONLN) zeigt nicht die richtige CPU an, wenn ich sie in eine while-Schleife stecke, aber wenn ich das in eine watch -n 0.1 ./a.out (schreckliche Wahl), dann zeigt es die Kernzahlen korrekt an. Dasselbe gilt für getconf, es startet jedes Mal neu, wenn es überwacht wird, und zeigt die korrekten Informationen an. Ihr Skript zeigt auch die richtigen Werte.
– S.Goswami
20. Dezember 2020 um 21:18 Uhr
Aber die Einschränkung ist, wenn ich benutze task -c 0 ./a.outes gibt mir procs=1 statt 4, d.h. es zählt nur die dem Prozess zugeordnete CPU.
– S. Goswami
21. Dezember 2020 um 7:42 Uhr
@S.Goswami: Genau das soll dieser Code tun; Lassen Sie wissen, wie viele Threads Sie beginnen könnten, um die Anzahl der Kerne in der Affinitätsmaske zu maximieren, mit der Ihr Prozess gestartet wurde. Das ist für einige Szenarien nützlich.
– Peter Cordes
28. Juli um 22:20 Uhr
14171100cookie-checkWie erhalte ich die Anzahl der CPUs in Linux mit C?yes
Warum haben die Leute solche Angst, /proc zu verwenden? Jede Linux-Box, die ich in den letzten 15 Jahren gesehen habe, hat es, es ist immer auf dem neuesten Stand mit dem, was der Kernel weiß, und das Format der darin vorhandenen Dinge ändert sich nicht viel.
– chao
3. Januar 2011 um 16:58 Uhr
Ich finde es toll, dass du versuchst, verschiedene Vorgehensweisen zu lernen, aber versuchst du, das Rad neu zu erfinden?
– David Weiser
3. Januar 2011 um 17:09 Uhr
Siehe auch stackoverflow.com/questions/150355/…
– Jay Sullivan
1. Februar 2020 um 15:53 Uhr
/proc ist nicht portabel
– Edd Barrett
2. Juni 2021 um 11:07 Uhr
@cHao Weil /proc Cgroups ignoriert, was zu einer “Überbelegung” führen kann, wenn der Prozess mehr Threads ausführt, als ihm in der Cpuset-Cgroup gewährt werden.
– phzx_munki
14. Februar um 21:28 Uhr