Secara terprogram menemukan jumlah inti pada mesin
464
Apakah ada cara untuk menentukan berapa core yang dimiliki mesin dari C / C ++ dengan cara yang bebas platform? Jika tidak ada hal seperti itu, bagaimana dengan menentukannya per-platform (Windows / * nix / Mac)?
Jika Anda ingin menggunakannya, cari tahu berapa banyak utas untuk memulai, gunakan NUMBER_OF_PROCESSORS sebagai ukuran utama. Saya meninggalkannya sebagai latihan untuk Anda mengapa ini jauh lebih baik (jika orang akan menggunakannya lebih banyak) kemudian menggunakan inti perangkat keras. Berapa banyak inti yang dimiliki oleh program Anda merupakan masalah lingkungan!
Lothar
Perhatikan bahwa std::thread::hardware_concurrencymengembalikan jumlah core CPU fisik, tetapi nprocdi Linux hanya menunjukkan jumlah core CPU proses saat ini dapat berjalan, yang dapat dikontrol dengan sched_setaffinity. Saya belum menemukan cara untuk mendapatkannya dari standar C ++ :, lihat misalnya dengan Python: stackoverflow.com/questions/1006289/...
Ciro Santilli 郝海东 冠状 病 六四 事件 事件 法轮功
Jawaban:
706
C ++ 11
#include<thread>//may return 0 when not able to detectconstauto processor_count = std::thread::hardware_concurrency();
Di C ++ sebelum C ++ 11, tidak ada cara portabel. Sebagai gantinya, Anda harus menggunakan satu atau lebih metode berikut (dijaga oleh #ifdefbaris yang sesuai ):
Linux, Solaris, AIX dan Mac OS X> = 10.4 (yaitu Tiger dan seterusnya)
int numCPU = sysconf(_SC_NPROCESSORS_ONLN);
FreeBSD, MacOS X, NetBSD, OpenBSD, dll.
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 atau iOS)
NSUInteger a =[[NSProcessInfo processInfo] processorCount];NSUInteger b =[[NSProcessInfo processInfo] activeProcessorCount];
@ mcandre: yang tersisa sebagai latihan untuk pembaca. Jika saya menerapkan saya mungkin akan menggunakan pendekatan templat-kebijakan di mana kebijakan itu didefinisikan dalam arahan preprosesor. Atau ... Anda bisa menggunakan boost thread :: hardware_concurrency ().
paxos1977
3
sebagai titik klarifikasi, solusi Win32 mengembalikan jumlah inti (yang diminta) bukan jumlah total CPU fisik.
Eric
1
Cara Linux / Solaris / AIX juga bekerja pada FreeBSD dan telah ada setidaknya sejak tahun 2006. Juga, yang akan mengembalikan CPU secara online, jika suatu sistem mampu mematikan sebagian, mereka mungkin tidak dihitung. Memanggil sysconf dengan "_SC_NPROCESSORS_CONF" akan mengembalikan total CPU yang dikonfigurasi.
Chris S
3
Beberapa hal yang harus diperhatikan. HW_NCPUdihentikan pada OS X. Pada Windows GetSystemInfohanya berguna jika sistem Anda memiliki 32 prosesor logis atau kurang, gunakan GetLogicalProcessorInformationuntuk sistem yang memiliki lebih dari 32 prosesor logis.
1
@Trejkaz , documentaion dengan jelas mengatakan "logis" - yang selalu menghitung inti HT, kata "fisik" selalu merujuk ke inti yang dilaporkan oleh BIOS / UEFI karena inti juga dapat ditiru / divirtualisasi. Anda dapat membedakan antara inti HT / non-HT dengan fungsi seperti GetLogicalProcessorInformation , misalnya. Catatan: HT! = Emulasi atau virtualisasi, itu perbedaan besar , HT adalah optimasi perangkat keras, sehingga untuk berbicara
specializt
202
Fungsionalitas ini adalah bagian dari standar C ++ 11.
Dalam kedua kasus tersebut, hardware_concurrency()kembalikan jumlah utas yang dapat dieksekusi perangkat keras secara bersamaan berdasarkan jumlah inti CPU dan unit hyper-threading.
Diperbantukan ... akan menggunakan kode contoh di atas dan beberapa macro preprocessor untuk mengekspos fungsi tunggal, tetapi kerja keras itu dilakukan untuk saya.
jkp
Untuk win32, ini adalah panggilan ke GetSystemInfo. (Pada dorongan Versi 1.41.0) Apakah itu menangkap semua info untuk menentukan berapa banyak utas pekerja akan efektif? Apakah orang perlu mempertimbangkan jumlah core dan hyper-threading? utas unsigned :: hardware_concurrency () {SYSTEM_INFO info = {0}; GetSystemInfo (& info); kembalikan info.dwNumberOfProcessors; }
Jive Dadson
Menurut MSDN, GetSystemInfo () mengembalikan jumlah "prosesor fisik" di dwNumberOfProcessors tetapi tidak mendefinisikan apa artinya dengan itu. Dokumentasi Boost tampaknya mengklaim bahwa itu termasuk unit hyperthreading.
karena itu jawaban yang salah. Dari gcc.gnu.org/bugzilla/show_bug.cgi?id=37586 "omp_get_num_procs () hanya akan mengembalikan angka yang lebih kecil daripada jumlah CPU sistem online, jika GOMP_CPU_AFFINITY env var digunakan, atau jika proses panggilan dan / atau utas memiliki Afinitas CPU terbatas pada subset CPU ". Jadi, jika sebelumnya Anda menelepon misalnya, sched_setaffinityini tidak akan berfungsi.
angainor
7
Fungsi ini mengembalikan jumlah CPU yang tersedia untuk proses panggilan. Bukankah ini kasus penggunaan yang paling umum? Lebih besar dari beberapa tujuan pelaporan yang tidak berguna, jumlah inti perangkat keras CPU sebenarnya tidak relevan bagi Anda jika Anda tidak dapat memanfaatkannya dalam kode Anda.
macbirdie
@ EvanTeran Selain fakta bahwa itu adalah tujuan dari pertanyaan itu, tentu saja dapat bermanfaat. Misalnya, untuk tujuan mengatur afinitas utas. Katakanlah, saya ingin menjalankan 4 utas yang terikat pada empat inti CPU terakhir di mesin saya, alih-alih empat inti pertama. Dan selain itu, ada cara lain untuk memparalelkan kode kecuali OpenMP. Saya mungkin ingin menelurkan pthreads sendiri. Itu pasti tersedia dan tidak dibatasi oleh variabel lingkungan OpenMP.
angainor
2
Ini mengembalikan jumlah CPU logis, bukan inti (CPU fisik).
Michael Konečný
37
Jika Anda memiliki akses bahasa assembly, Anda dapat menggunakan instruksi CPUID untuk mendapatkan semua jenis informasi tentang CPU. Ini portabel di antara sistem operasi, meskipun Anda harus menggunakan informasi khusus pabrikan untuk menentukan cara menemukan jumlah inti. Berikut adalah dokumen yang menjelaskan cara melakukannya pada chip Intel , dan halaman 11 ini menjelaskan spesifikasi AMD.
Mungkin telah diturunkan karena pertanyaannya ditandai sebagai C ++ dan jawaban ini tidak berlaku untuk sistem yang menjalankan C ++ pada arsitektur non-x86 (ARM, PPC, dll.). Saya tidak mengatakan itu alasan yang bagus untuk menurunkan pilihan jawaban, hanya sebuah kemungkinan.
Ferruccio
3
Salah satu perangkap metode ini adalah jika Anda menggunakan CPUID untuk mendeteksi HyperThreading pada prosesor Intel. Saya mengalami masalah ini pada laptop saya: sementara CPU yang saya masukkan ke dalam mesin mendukung HyperThreading (dan, tentu saja, melaporkan bahwa itu dilakukan melalui CPUID), BIOS tidak. Oleh karena itu, Anda tidak boleh mencoba memanfaatkan kemampuan HT hanya dari pembacaan CPUID. Karena Anda tidak dapat menanyakan BIOS tentang dukungan HT (tidak seperti yang saya lihat), OS harus ditanya untuk mendapatkan jumlah prosesor logis.
Kecuali itu yang juga menghitung solusi hyperthreaded atau SMT lainnya sebagai lebih banyak core ...
jakobengblom2
13
@Arafangion: hyperthreading bukanlah eksekusi paralel yang sebenarnya, ini adalah teknologi untuk mengurangi overhead pergantian konteks. CPU hyphreaded hanya dapat mengeksekusi satu utas pada satu waktu, tetapi ia dapat menyimpan status arsitektur (nilai register dll.) Dari dua utas pada saat yang sama. Karakteristik kinerja sangat berbeda dari memiliki dua core.
Wim Coenen
7
@ Win: Itu tidak sepenuhnya benar. CPU dengan hyperthreading umumnya memiliki beberapa ALU dan dapat mengirimkan beberapa instruksi per siklus. Jika karena ketergantungan data dan warung, tidak semua ALU dapat tetap sibuk oleh satu utas, maka ALU tersebut akan digunakan untuk eksekusi simultan utas perangkat keras kedua.
Ben Voigt
11
Perhatikan bahwa "jumlah inti" mungkin bukan angka yang sangat berguna, Anda mungkin harus membuatnya sedikit lebih memenuhi syarat. Bagaimana Anda ingin menghitung CPU multi-threaded seperti Intel HT, IBM Power5 dan Power6, dan yang paling terkenal, Sun's Niagara / UltraSparc T1 dan T2? Atau bahkan lebih menarik, MIPS 1004k dengan dua tingkat threading perangkat keras (pengawas DAN tingkat pengguna) ... Belum lagi apa yang terjadi ketika Anda pindah ke sistem yang didukung hypervisor di mana perangkat keras mungkin memiliki puluhan CPU tetapi OS khusus Anda hanya melihat beberapa.
Yang terbaik yang dapat Anda harapkan adalah memberi tahu jumlah unit pemrosesan logis yang Anda miliki di partisi OS lokal Anda. Lupakan tentang melihat mesin yang sebenarnya kecuali Anda adalah hypervisor. Satu-satunya pengecualian untuk aturan ini hari ini adalah di tanah x86, tetapi akhir dari mesin non-virtual datang dengan cepat ...
Perhatikan bahwa implementasi NumberOfPhysicalCoresIMHO jauh dari sepele (yaitu "gunakan GetLogicalProcessorInformationatau GetLogicalProcessorInformationEx"). Sebaliknya itu agak halus jika seseorang membaca dokumentasi (secara eksplisit hadir untuk GetLogicalProcessorInformationdan secara implisit hadir untuk GetLogicalProcessorInformationEx) di MSDN.
Terima kasih! Saya mencari ini karena GetLogicalProcessorInformationtidak bekerja dengan berbagai ukuran buffer yang saya gunakan. Lebih dari puas! ^^
KeyWeeUsr
@KeyWeeUsr Terima kasih pemrograman Windows agak jauh dari sepele dan logis. Sementara itu, saya menggunakan versi C ++ 17 yang sedikit lebih diperbarui yang juga lebih tepat menurut analisa statis PVS-Studio sehubungan dengan beberapa size_tgips. (Meskipun, msvc ++ tidak mengeluh di W4.)
Matthias
5
Lebih lanjut tentang OS X: sysconf(_SC_NPROCESSORS_ONLN)hanya tersedia versi> = 10.5, bukan 10.4.
Alternatifnya adalah HW_AVAILCPU/sysctl()kode BSD yang tersedia pada versi> = 10.2.
Untuk python:import multiprocessingprint multiprocessing.cpu_count()
initzero
3
Sudah lama, tetapi grepmemiliki -cbendera untuk menghitung entri!
Lapshin Dmitry
3
hwloc (http://www.open-mpi.org/projects/hwloc/) layak untuk dilihat. Meskipun memerlukan integrasi pustaka lain ke dalam kode Anda, tetapi itu dapat memberikan semua informasi tentang prosesor Anda (jumlah inti, topologi, dll.)
Di Linux, ini mungkin tidak aman untuk digunakan _SC_NPROCESSORS_ONLNkarena itu bukan bagian dari standar POSIX dan status manual sysconf . Jadi ada kemungkinan yang _SC_NPROCESSORS_ONLNtidak ada:
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).
Pendekatan sederhana adalah membaca /proc/statatau /proc/cpuinfomenghitungnya:
#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;}
Menggunakan /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;}
Pendekatan yang sama di shell menggunakan grep:
grep -c ^processor /proc/cpuinfo
Atau
grep -c ^cpu /proc/stat # subtract 1 from the result
Alternatif OS X: Solusi yang dijelaskan sebelumnya berdasarkan [[NSProcessInfo processInfo] processorCount] hanya tersedia di OS X 10.5.0, menurut dokumen. Untuk versi OS X yang lebih lama, gunakan fungsi Karbon MPProcessors ().
Jika Anda seorang programmer Cocoa, jangan takut dengan kenyataan bahwa ini adalah Carbon. Anda hanya perlu menambahkan kerangka Karbon ke proyek Xcode Anda dan MPProcessor () akan tersedia.
Anda dapat menggunakan WMI di .net juga tetapi Anda kemudian tergantung pada layanan wmi yang berjalan dll. Kadang-kadang bekerja secara lokal, tetapi kemudian gagal ketika kode yang sama dijalankan di server. Saya percaya itu masalah namespace, terkait dengan "nama" yang nilainya Anda baca.
std::thread::hardware_concurrency
mengembalikan jumlah core CPU fisik, tetapinproc
di Linux hanya menunjukkan jumlah core CPU proses saat ini dapat berjalan, yang dapat dikontrol dengansched_setaffinity
. Saya belum menemukan cara untuk mendapatkannya dari standar C ++ :, lihat misalnya dengan Python: stackoverflow.com/questions/1006289/...Jawaban:
C ++ 11
Referensi: std :: thread :: hardware_concurrency
Di C ++ sebelum C ++ 11, tidak ada cara portabel. Sebagai gantinya, Anda harus menggunakan satu atau lebih metode berikut (dijaga oleh
#ifdef
baris yang sesuai ):Win32
Linux, Solaris, AIX dan Mac OS X> = 10.4 (yaitu Tiger dan seterusnya)
FreeBSD, MacOS X, NetBSD, OpenBSD, dll.
HPUX
IRIX
Objective-C (Mac OS X> = 10.5 atau iOS)
sumber
HW_NCPU
dihentikan pada OS X. Pada WindowsGetSystemInfo
hanya berguna jika sistem Anda memiliki 32 prosesor logis atau kurang, gunakanGetLogicalProcessorInformation
untuk sistem yang memiliki lebih dari 32 prosesor logis.Fungsionalitas ini adalah bagian dari standar C ++ 11.
Untuk kompiler lama, Anda bisa menggunakan perpustakaan Boost.Thread .
Dalam kedua kasus tersebut,
hardware_concurrency()
kembalikan jumlah utas yang dapat dieksekusi perangkat keras secara bersamaan berdasarkan jumlah inti CPU dan unit hyper-threading.sumber
OpenMP didukung pada banyak platform (termasuk Visual Studio 2005) dan ia menawarkan a
fungsi yang mengembalikan jumlah prosesor / inti yang tersedia pada saat panggilan.
sumber
sched_setaffinity
ini tidak akan berfungsi.Jika Anda memiliki akses bahasa assembly, Anda dapat menggunakan instruksi CPUID untuk mendapatkan semua jenis informasi tentang CPU. Ini portabel di antara sistem operasi, meskipun Anda harus menggunakan informasi khusus pabrikan untuk menentukan cara menemukan jumlah inti. Berikut adalah dokumen yang menjelaskan cara melakukannya pada chip Intel , dan halaman 11 ini menjelaskan spesifikasi AMD.
sumber
(Hampir) Platform Fungsi independen dalam kode-c
sumber
HW_NCPU
sudah usang pada sumberDi Linux, Anda dapat membaca file / proc / cpuinfo dan menghitung inti.
sumber
Perhatikan bahwa "jumlah inti" mungkin bukan angka yang sangat berguna, Anda mungkin harus membuatnya sedikit lebih memenuhi syarat. Bagaimana Anda ingin menghitung CPU multi-threaded seperti Intel HT, IBM Power5 dan Power6, dan yang paling terkenal, Sun's Niagara / UltraSparc T1 dan T2? Atau bahkan lebih menarik, MIPS 1004k dengan dua tingkat threading perangkat keras (pengawas DAN tingkat pengguna) ... Belum lagi apa yang terjadi ketika Anda pindah ke sistem yang didukung hypervisor di mana perangkat keras mungkin memiliki puluhan CPU tetapi OS khusus Anda hanya melihat beberapa.
Yang terbaik yang dapat Anda harapkan adalah memberi tahu jumlah unit pemrosesan logis yang Anda miliki di partisi OS lokal Anda. Lupakan tentang melihat mesin yang sebenarnya kecuali Anda adalah hypervisor. Satu-satunya pengecualian untuk aturan ini hari ini adalah di tanah x86, tetapi akhir dari mesin non-virtual datang dengan cepat ...
sumber
Satu lagi resep Windows: gunakan variabel lingkungan sistem-lebar
NUMBER_OF_PROCESSORS
:sumber
Anda mungkin tidak akan bisa mendapatkannya di platform mandiri. Windows Anda mendapatkan sejumlah prosesor.
Informasi Sistem Win32
sumber
Windows (x64 dan Win32) dan C ++ 11
Jumlah kelompok prosesor logis yang berbagi inti prosesor tunggal. (Menggunakan GetLogicalProcessorInformationEx , lihat GetLogicalProcessorInformation juga)
Perhatikan bahwa implementasi
NumberOfPhysicalCores
IMHO jauh dari sepele (yaitu "gunakanGetLogicalProcessorInformation
atauGetLogicalProcessorInformationEx
"). Sebaliknya itu agak halus jika seseorang membaca dokumentasi (secara eksplisit hadir untukGetLogicalProcessorInformation
dan secara implisit hadir untukGetLogicalProcessorInformationEx
) di MSDN.Jumlah prosesor logis. (Menggunakan GetSystemInfo )
Perhatikan bahwa kedua metode dapat dengan mudah dikonversi ke C / C ++ 98 / C ++ 03.
sumber
GetLogicalProcessorInformation
tidak bekerja dengan berbagai ukuran buffer yang saya gunakan. Lebih dari puas! ^^size_t
gips. (Meskipun, msvc ++ tidak mengeluh di W4.)Lebih lanjut tentang OS X:
sysconf(_SC_NPROCESSORS_ONLN)
hanya tersedia versi> = 10.5, bukan 10.4.Alternatifnya adalah
HW_AVAILCPU/sysctl()
kode BSD yang tersedia pada versi> = 10.2.sumber
Windows Server 2003 dan yang lebih baru memungkinkan Anda memanfaatkan fungsi GetLogicalProcessorInformation
http://msdn.microsoft.com/en-us/library/ms683194.aspx
sumber
Tidak terkait dengan C ++, tetapi di Linux biasanya saya lakukan:
Berguna untuk bahasa skrip seperti bash / perl / python / ruby.
sumber
import multiprocessing
print multiprocessing.cpu_count()
grep
memiliki-c
bendera untuk menghitung entri!hwloc (http://www.open-mpi.org/projects/hwloc/) layak untuk dilihat. Meskipun memerlukan integrasi pustaka lain ke dalam kode Anda, tetapi itu dapat memberikan semua informasi tentang prosesor Anda (jumlah inti, topologi, dll.)
sumber
Di linux cara pemrograman terbaik sejauh yang saya tahu adalah menggunakan
atau
Ini bukan standar, tetapi ada di halaman manual saya untuk Linux.
sumber
Di Linux, ini mungkin tidak aman untuk digunakan
_SC_NPROCESSORS_ONLN
karena itu bukan bagian dari standar POSIX dan status manual sysconf . Jadi ada kemungkinan yang_SC_NPROCESSORS_ONLN
tidak ada:Pendekatan sederhana adalah membaca
/proc/stat
atau/proc/cpuinfo
menghitungnya:Menggunakan
/proc/cpuinfo
:Pendekatan yang sama di shell menggunakan grep:
Atau
sumber
Alternatif OS X: Solusi yang dijelaskan sebelumnya berdasarkan [[NSProcessInfo processInfo] processorCount] hanya tersedia di OS X 10.5.0, menurut dokumen. Untuk versi OS X yang lebih lama, gunakan fungsi Karbon MPProcessors ().
Jika Anda seorang programmer Cocoa, jangan takut dengan kenyataan bahwa ini adalah Carbon. Anda hanya perlu menambahkan kerangka Karbon ke proyek Xcode Anda dan MPProcessor () akan tersedia.
sumber
Untuk Win32:
Sementara GetSystemInfo () memberi Anda jumlah prosesor logis , gunakan GetLogicalProcessorInformationEx () untuk mendapatkan jumlah prosesor fisik .
sumber
Anda dapat menggunakan WMI di .net juga tetapi Anda kemudian tergantung pada layanan wmi yang berjalan dll. Kadang-kadang bekerja secara lokal, tetapi kemudian gagal ketika kode yang sama dijalankan di server. Saya percaya itu masalah namespace, terkait dengan "nama" yang nilainya Anda baca.
sumber
Di Linux, Anda dapat checkout dmesg dan memfilter garis tempat ACPI menginisialisasi CPU, seperti:
dmesg | grep 'ACPI: Processor
'Kemungkinan lain adalah menggunakan dmidecode untuk menyaring informasi prosesor.
sumber