Czy istnieje sposób na określenie liczby rdzeni maszyny w C / C ++ w sposób niezależny od platformy? Jeśli nic takiego nie istnieje, co powiesz na określenie tego na platformę (Windows / * nix / Mac)?
Jeśli chcesz go użyć, dowiedz się, ile wątków zacząć, użyj NUMBER_OF_PROCESSORS jako podstawowej miary. Pozostawiam wam jako wytłumaczenie, dlaczego jest to o wiele lepsze (jeśli ludzie używają go częściej) niż używanie rdzeni sprzętowych. Ile rdzeni należy do twojego programu to problem środowiskowy!
Lothar
Zauważ, że std::thread::hardware_concurrencyzwraca liczbę fizycznych rdzeni procesora, ale nprocw Linuksie pokazuje tylko liczbę rdzeni procesora, na których może działać bieżący proces, którymi można sterować sched_setaffinity. Nie znalazłem sposobu na uzyskanie tego zamiast standardowego C ++: patrz np. W Pythonie: stackoverflow.com/questions/1006289/...
Ciro Santilli 法轮功 冠状 病 六四 事件 法轮功
Odpowiedzi:
706
C ++ 11
#include<thread>//may return 0 when not able to detectconstauto processor_count = std::thread::hardware_concurrency();
W C ++ przed C ++ 11 nie ma przenośnego sposobu. Zamiast tego musisz użyć jednej lub więcej z następujących metod (strzeżonych odpowiednimi #ifdefliniami):
Linux, Solaris, AIX i Mac OS X> = 10,4 (tj. Tiger i nowsze)
int numCPU = sysconf(_SC_NPROCESSORS_ONLN);
FreeBSD, MacOS X, NetBSD, OpenBSD itp.
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);
Cel C (Mac OS X> = 10.5 lub iOS)
NSUInteger a =[[NSProcessInfo processInfo] processorCount];NSUInteger b =[[NSProcessInfo processInfo] activeProcessorCount];
@mcandre: pozostawia to ćwiczenie czytelnikowi. Gdybym wdrażał, prawdopodobnie użyłbym podejścia opartego na szablonach, gdzie zasady zostały zdefiniowane w dyrektywach preprocesora. Lub ... możesz użyć boost thread :: hardware_concurrency ().
paxos1977
3
dla wyjaśnienia rozwiązanie Win32 zwraca całkowitą liczbę rdzeni (o co poproszono), a nie całkowitą liczbę fizycznych procesorów.
Eric
1
Sposób Linux / Solaris / AIX działa również na FreeBSD i działa od co najmniej 2006 roku. To również spowoduje powrót procesorów do trybu online, jeśli system jest w stanie wyłączyć niektóre z nich, mogą nie zostać policzone. Wywołanie sysconf z „_SC_NPROCESSORS_CONF” zwróci całkowitą liczbę skonfigurowanych procesorów.
Chris S
3
Kilka rzeczy, o których należy pamiętać. HW_NCPUjest przestarzały w systemie OS X. W systemie Windows GetSystemInfojest przydatny tylko wtedy, gdy twój system ma 32 procesory logiczne lub mniej, używaj GetLogicalProcessorInformationw systemach, które mają więcej niż 32 procesory logiczne.
1
@Trejkaz dokumentacja wyraźnie mówi „logiczny” - co zawsze liczy rdzenie HT, słowo „fizyczny” zawsze odnosi się do rdzeni zgłaszanych przez BIOS / UEFI, ponieważ rdzenie mogą być również emulowane / wirtualizowane. Można odróżnić rdzenie HT / non-HT za pomocą funkcji takich jak GetLogicalProcessorInformation , na przykład. Uwaga: HT! = Emulacja lub wirtualizacja, to duża różnica, HT to optymalizacja sprzętowa, że tak powiem
W obu przypadkach hardware_concurrency()zwraca liczbę wątków, które sprzęt może wykonywać jednocześnie, w oparciu o liczbę rdzeni procesora i jednostek hiperwątkowości.
Seconded ... zamierzał użyć powyższego przykładowego kodu i niektórych makr preprocesora, aby ujawnić jedną funkcję, ale ciężka praca została dla mnie wykonana.
jkp
W przypadku win32 jest to wywołanie GetSystemInfo. (Od wersji boost 1.41.0) Czy to przechwytuje wszystkie informacje, aby określić, ile wątków roboczych będzie efektywnych? Czy trzeba wziąć pod uwagę zarówno liczbę rdzeni, jak i hiperwątkowość? niepodpisany wątek :: hardware_concurrency () {SYSTEM_INFO info = {0}; GetSystemInfo (i informacje); return info.dwNumberOfProcessors; }
Jive Dadson
Według MSDN GetSystemInfo () zwraca liczbę „fizycznych procesorów” w dwNumberOfProcessors, ale nie definiuje co to oznacza. Dokumentacja Boost wydaje się twierdzić, że obejmuje jednostki hipertekstowe.
Ferruccio
patrz
hyperoverreading
57
OpenMP jest obsługiwany na wielu platformach (w tym Visual Studio 2005) i oferuje
int omp_get_num_procs();
funkcja zwracająca liczbę procesorów / rdzeni dostępnych w momencie połączenia.
ponieważ jest to zła odpowiedź. Z gcc.gnu.org/bugzilla/show_bug.cgi?id=37586 „omp_get_num_procs () zwróci tylko mniejszą liczbę niż liczba procesorów systemowych w trybie online, jeśli użyto GOMP_CPU_AFFINITY env var lub jeśli proces wywołujący i / lub wątek ma Powinowactwo procesora ograniczone do podzbioru procesorów ". Więc jeśli wcześniej zadzwonisz, np. sched_setaffinityTo nie zadziała.
angainor
7
Ta funkcja zwraca liczbę procesorów dostępnych dla procesu wywołującego. Czy to zresztą nie jest najczęstszy przypadek użycia? Poza niektórymi bezużytecznymi celami raportowania, faktyczna liczba rdzeni procesora nie jest dla ciebie istotna, jeśli nie możesz z nich skorzystać w swoim kodzie.
macbirdie
@EvanTeran Oprócz tego, że był to cel pytania, może być oczywiście użyteczny. Na przykład w celu ustawienia powinowactwa wątku. Powiedzmy, że chcę uruchomić 4 wątki powiązane z czterema ostatnimi rdzeniami procesora na moim komputerze, zamiast z czterema pierwszymi rdzeniami. Poza tym istnieją inne sposoby zrównoleglenia kodu oprócz OpenMP. Mogę sam chcieć spawnować wątki. Są one z pewnością dostępne i nie są ograniczone zmiennymi środowiskowymi OpenMP.
angainor
2
Zwraca liczbę procesorów logicznych, a nie rdzeni (procesorów fizycznych) jako takich.
Michael Konečný
37
Jeśli masz dostęp w języku asemblera, możesz użyć instrukcji CPUID, aby uzyskać wszelkiego rodzaju informacje o CPU. Jest przenośny między systemami operacyjnymi, ale musisz użyć informacji specyficznych dla producenta, aby ustalić, jak znaleźć liczbę rdzeni. Oto dokument opisujący, jak to zrobić na układach Intel , a strona 11 tego opisu opisuje specyfikację AMD.
Być może zostało to odrzucone, ponieważ pytanie jest oznaczone jako C ++, a ta odpowiedź nie dotyczy systemów z C ++ na architekturze innej niż x86 (ARM, PPC itp.). Nie twierdzę, że to dobry powód, by głosować za odpowiedzią, tylko taka możliwość.
Ferruccio
3
Jedną z pułapek tej metody jest użycie CPUID do wykrywania HyperThreading na procesorach Intel. Napotkałem ten problem na moim laptopie: podczas gdy procesor, który wkładam do komputera, obsługuje HyperThreading (i, oczywiście, informuje, że robi to przez CPUID), BIOS nie. Dlatego nie powinieneś próbować wykorzystywać możliwości HT po prostu z odczytu CPUID. Ponieważ nie można zapytać BIOS-u o obsługę HT (nie ma mowy, żebym widział), system operacyjny powinien zostać zapytany, aby uzyskać logiczną liczbę procesorów.
Chuck R
32
(Prawie) Niezależna od platformy funkcja w kodzie c
Z wyjątkiem, że liczy się także hyperthreaded lub inne rozwiązania SMT jak więcej rdzeni ...
jakobengblom2
13
@Arafangion: hyperthreading nie jest prawdziwym równoległym wykonywaniem, jest technologią zmniejszającą obciążenie związane z przełączaniem kontekstu. Hyperthreaded procesor może wykonywać tylko jeden wątek na raz, ale może przechowywać stan architektury (wartości rejestru itp.) Dwóch wątków jednocześnie. Charakterystyka wydajności bardzo różni się od posiadania dwóch rdzeni.
Wim Coenen,
7
@Wim: To nie do końca poprawne. Procesory z hiperwątkiem mają na ogół wiele jednostek ALU i mogą wysyłać wiele instrukcji na cykl. Jeśli z powodu zależności danych i przeciągnięć, nie wszystkie jednostki ALU mogą być zajęte przez jeden wątek, te jednostki ALU zostaną zamiast tego wykorzystane do jednoczesnego wykonania drugiego wątku sprzętowego.
Ben Voigt,
11
Zauważ, że „liczba rdzeni” może nie być szczególnie przydatną liczbą, być może będziesz musiał ją jeszcze bardziej zakwalifikować. Jak chcesz policzyć wielowątkowe procesory, takie jak Intel HT, IBM Power5 i Power6, a najbardziej znany, Sun's Niagara / UltraSparc T1 i T2? Lub jeszcze bardziej interesujące, MIPS 1004k z dwoma poziomami wątków sprzętowych (nadzorca ORAZ poziom użytkownika) ... Nie wspominając o tym, co dzieje się, gdy przejdziesz do systemów obsługiwanych przez hypervisor, w których sprzęt może mieć dziesiątki procesorów, ale twój system operacyjny widzi tylko kilka.
Najlepsze, na co możesz liczyć, to podanie liczby jednostek przetwarzania logicznego na lokalnej partycji systemu operacyjnego. Zapomnij o zobaczeniu prawdziwej maszyny, chyba że jesteś hiperwizorem. Jedyny wyjątek od tej reguły jest dzisiaj na ziemi x86, ale koniec maszyn nie-wirtualnych nadchodzi szybko ...
Zauważ, że implementacja NumberOfPhysicalCoresIMHO jest daleka od trywialnej (tj. „Use GetLogicalProcessorInformationor GetLogicalProcessorInformationEx”). Zamiast tego jest raczej subtelne, jeśli czyta się dokumentację (jawnie obecną GetLogicalProcessorInformationi niejawnie obecną GetLogicalProcessorInformationEx) w MSDN.
Liczba procesorów logicznych. (Korzystanie z GetSystemInfo )
Dziękuję Ci! Szukałem tego, ponieważ GetLogicalProcessorInformationnie pracowałem z różnymi rozmiarami buforów, których użyłem. Więcej niż zadowolony! ^^
KeyWeeUsr
@KeyWeeUsr Dzięki Programowanie w systemie Windows jest nieco dalekie od trywialnych i logicznych. Tymczasem używam nieco zaktualizowanej wersji C ++ 17, która jest również bardziej poprawna według analizatora statycznego PVS-Studio w odniesieniu do niektórych size_trzutów. (Chociaż msvc ++ nie narzeka na W4.)
Matthias
5
Więcej informacji na temat systemu OS X: sysconf(_SC_NPROCESSORS_ONLN)dostępne są tylko wersje> = 10,5, a nie 10,4.
Alternatywą jest HW_AVAILCPU/sysctl()kod BSD, który jest dostępny w wersjach> = 10.2.
W przypadku pytona:import multiprocessingprint multiprocessing.cpu_count()
initzero
3
Minęło dużo czasu, ale grepma -cflagę do liczenia wpisów!
Lapshin Dmitry
3
Warto przyjrzeć się hwloc (http://www.open-mpi.org/projects/hwloc/). Chociaż wymaga kolejnej integracji biblioteki z twoim kodem, ale może dostarczyć wszystkich informacji o twoim procesorze (liczba rdzeni, topologia itp.)
W Linuksie korzystanie z niego może nie być bezpieczne, _SC_NPROCESSORS_ONLNponieważ nie jest ono częścią standardu POSIX, a instrukcja sysconf podaje tyle samo. Istnieje więc możliwość, że _SC_NPROCESSORS_ONLNmoże nie być obecna:
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).
Prostym podejściem byłoby ich przeczytanie /proc/statlub /proc/cpuinfopoliczenie:
#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;}
Używanie /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;}
To samo podejście w powłoce przy użyciu grep:
grep -c ^processor /proc/cpuinfo
Lub
grep -c ^cpu /proc/stat # subtract 1 from the result
Alternatywa dla OS X: Rozwiązanie opisane wcześniej w oparciu o [[NSProcessInfo processInfo] processCount] jest dostępne tylko w OS X 10.5.0, zgodnie z dokumentacją. W przypadku wcześniejszych wersji OS X użyj funkcji Carbon MPProcessors ().
Jeśli jesteś programistą Cocoa, nie przejmuj się faktem, że jest to Carbon. Musisz tylko dodać platformę Carbon do swojego projektu Xcode, a MPProcessors () będzie dostępny.
Podczas gdy GetSystemInfo () uzyskuje liczbę procesorów logicznych , użyj
GetLogicalProcessorInformationEx (),
aby uzyskać liczbę procesorów fizycznych .
możesz również używać WMI w .net, ale jesteś zależny od działającej usługi wmi itp. Czasami działa ona lokalnie, ale potem kończy się niepowodzeniem, gdy ten sam kod jest uruchamiany na serwerach. Uważam, że jest to problem związany z przestrzenią nazw, związany z „nazwami”, których wartości czytasz.
std::thread::hardware_concurrency
zwraca liczbę fizycznych rdzeni procesora, alenproc
w Linuksie pokazuje tylko liczbę rdzeni procesora, na których może działać bieżący proces, którymi można sterowaćsched_setaffinity
. Nie znalazłem sposobu na uzyskanie tego zamiast standardowego C ++: patrz np. W Pythonie: stackoverflow.com/questions/1006289/...Odpowiedzi:
C ++ 11
Odniesienie: std :: thread :: hardware_concurrency
W C ++ przed C ++ 11 nie ma przenośnego sposobu. Zamiast tego musisz użyć jednej lub więcej z następujących metod (strzeżonych odpowiednimi
#ifdef
liniami):Win32
Linux, Solaris, AIX i Mac OS X> = 10,4 (tj. Tiger i nowsze)
FreeBSD, MacOS X, NetBSD, OpenBSD itp.
HPUX
IRIX
Cel C (Mac OS X> = 10.5 lub iOS)
źródło
HW_NCPU
jest przestarzały w systemie OS X. W systemie WindowsGetSystemInfo
jest przydatny tylko wtedy, gdy twój system ma 32 procesory logiczne lub mniej, używajGetLogicalProcessorInformation
w systemach, które mają więcej niż 32 procesory logiczne.Ta funkcjonalność jest częścią standardu C ++ 11.
W przypadku starszych kompilatorów możesz użyć biblioteki Boost.Thread .
W obu przypadkach
hardware_concurrency()
zwraca liczbę wątków, które sprzęt może wykonywać jednocześnie, w oparciu o liczbę rdzeni procesora i jednostek hiperwątkowości.źródło
OpenMP jest obsługiwany na wielu platformach (w tym Visual Studio 2005) i oferuje
funkcja zwracająca liczbę procesorów / rdzeni dostępnych w momencie połączenia.
źródło
sched_setaffinity
To nie zadziała.Jeśli masz dostęp w języku asemblera, możesz użyć instrukcji CPUID, aby uzyskać wszelkiego rodzaju informacje o CPU. Jest przenośny między systemami operacyjnymi, ale musisz użyć informacji specyficznych dla producenta, aby ustalić, jak znaleźć liczbę rdzeni. Oto dokument opisujący, jak to zrobić na układach Intel , a strona 11 tego opisu opisuje specyfikację AMD.
źródło
(Prawie) Niezależna od platformy funkcja w kodzie c
źródło
HW_NCPU
jest przestarzałe w źródleW systemie Linux możesz odczytać plik / proc / cpuinfo i policzyć rdzenie.
źródło
Zauważ, że „liczba rdzeni” może nie być szczególnie przydatną liczbą, być może będziesz musiał ją jeszcze bardziej zakwalifikować. Jak chcesz policzyć wielowątkowe procesory, takie jak Intel HT, IBM Power5 i Power6, a najbardziej znany, Sun's Niagara / UltraSparc T1 i T2? Lub jeszcze bardziej interesujące, MIPS 1004k z dwoma poziomami wątków sprzętowych (nadzorca ORAZ poziom użytkownika) ... Nie wspominając o tym, co dzieje się, gdy przejdziesz do systemów obsługiwanych przez hypervisor, w których sprzęt może mieć dziesiątki procesorów, ale twój system operacyjny widzi tylko kilka.
Najlepsze, na co możesz liczyć, to podanie liczby jednostek przetwarzania logicznego na lokalnej partycji systemu operacyjnego. Zapomnij o zobaczeniu prawdziwej maszyny, chyba że jesteś hiperwizorem. Jedyny wyjątek od tej reguły jest dzisiaj na ziemi x86, ale koniec maszyn nie-wirtualnych nadchodzi szybko ...
źródło
Jeszcze jeden przepis na Windows: użyj ogólnosystemowej zmiennej środowiskowej
NUMBER_OF_PROCESSORS
:źródło
Prawdopodobnie nie będziesz w stanie uzyskać go w sposób niezależny od platformy. Windows dostajesz liczbę procesorów.
Informacje o systemie Win32
źródło
Windows (x64 i Win32) oraz C ++ 11
Liczba grup procesorów logicznych współużytkujących jeden rdzeń procesora. (Używając GetLogicalProcessorInformationEx , zobacz także GetLogicalProcessorInformation )
Zauważ, że implementacja
NumberOfPhysicalCores
IMHO jest daleka od trywialnej (tj. „UseGetLogicalProcessorInformation
orGetLogicalProcessorInformationEx
”). Zamiast tego jest raczej subtelne, jeśli czyta się dokumentację (jawnie obecnąGetLogicalProcessorInformation
i niejawnie obecnąGetLogicalProcessorInformationEx
) w MSDN.Liczba procesorów logicznych. (Korzystanie z GetSystemInfo )
Zauważ, że obie metody można łatwo przekonwertować na C / C ++ 98 / C ++ 03.
źródło
GetLogicalProcessorInformation
nie pracowałem z różnymi rozmiarami buforów, których użyłem. Więcej niż zadowolony! ^^size_t
rzutów. (Chociaż msvc ++ nie narzeka na W4.)Więcej informacji na temat systemu OS X:
sysconf(_SC_NPROCESSORS_ONLN)
dostępne są tylko wersje> = 10,5, a nie 10,4.Alternatywą jest
HW_AVAILCPU/sysctl()
kod BSD, który jest dostępny w wersjach> = 10.2.źródło
Windows Server 2003 i nowsze wersje umożliwiają wykorzystanie funkcji GetLogicalProcessorInformation
http://msdn.microsoft.com/en-us/library/ms683194.aspx
źródło
Nie jest związany z C ++, ale w Linuksie zwykle robię:
Przydatny do języków skryptowych, takich jak bash / perl / python / ruby.
źródło
import multiprocessing
print multiprocessing.cpu_count()
grep
ma-c
flagę do liczenia wpisów!Warto przyjrzeć się hwloc (http://www.open-mpi.org/projects/hwloc/). Chociaż wymaga kolejnej integracji biblioteki z twoim kodem, ale może dostarczyć wszystkich informacji o twoim procesorze (liczba rdzeni, topologia itp.)
źródło
Na Linuksie najlepszym sposobem programistycznym, o ile wiem, jest użycie
lub
Nie są to standardowe, ale są na mojej stronie podręcznika użytkownika dla systemu Linux.
źródło
W Linuksie korzystanie z niego może nie być bezpieczne,
_SC_NPROCESSORS_ONLN
ponieważ nie jest ono częścią standardu POSIX, a instrukcja sysconf podaje tyle samo. Istnieje więc możliwość, że_SC_NPROCESSORS_ONLN
może nie być obecna:Prostym podejściem byłoby ich przeczytanie
/proc/stat
lub/proc/cpuinfo
policzenie:Używanie
/proc/cpuinfo
:To samo podejście w powłoce przy użyciu grep:
Lub
źródło
Alternatywa dla OS X: Rozwiązanie opisane wcześniej w oparciu o [[NSProcessInfo processInfo] processCount] jest dostępne tylko w OS X 10.5.0, zgodnie z dokumentacją. W przypadku wcześniejszych wersji OS X użyj funkcji Carbon MPProcessors ().
Jeśli jesteś programistą Cocoa, nie przejmuj się faktem, że jest to Carbon. Musisz tylko dodać platformę Carbon do swojego projektu Xcode, a MPProcessors () będzie dostępny.
źródło
Dla Win32:
Podczas gdy GetSystemInfo () uzyskuje liczbę procesorów logicznych , użyj GetLogicalProcessorInformationEx (), aby uzyskać liczbę procesorów fizycznych .
źródło
możesz również używać WMI w .net, ale jesteś zależny od działającej usługi wmi itp. Czasami działa ona lokalnie, ale potem kończy się niepowodzeniem, gdy ten sam kod jest uruchamiany na serwerach. Uważam, że jest to problem związany z przestrzenią nazw, związany z „nazwami”, których wartości czytasz.
źródło
W systemie Linux możesz pobrać dmesg i filtrować wiersze, w których ACPI inicjuje procesory, na przykład:
dmesg | grep 'ACPI: Processor
„Inną możliwością jest użycie dmidecode do odfiltrowania informacji o procesorze.
źródło