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)?

hazzen
sumber
4
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 detect
const auto processor_count = std::thread::hardware_concurrency();

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 #ifdefbaris yang sesuai ):

  • Win32

    SYSTEM_INFO sysinfo;
    GetSystemInfo(&sysinfo);
    int numCPU = sysinfo.dwNumberOfProcessors;
  • 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];
paxos1977
sumber
5
@ 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.

#include <thread>

unsigned int nthreads = std::thread::hardware_concurrency();

Untuk kompiler lama, Anda bisa menggunakan perpustakaan Boost.Thread .

#include <boost/thread.hpp>

unsigned int nthreads = boost::thread::hardware_concurrency();

Dalam kedua kasus tersebut, hardware_concurrency()kembalikan jumlah utas yang dapat dieksekusi perangkat keras secara bersamaan berdasarkan jumlah inti CPU dan unit hyper-threading.

Ferruccio
sumber
1
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.
Ferruccio
lihat stackoverflow.com/questions/642348/... untuk hyperthreading
naugtur
57

OpenMP didukung pada banyak platform (termasuk Visual Studio 2005) dan ia menawarkan a

int omp_get_num_procs();

fungsi yang mengembalikan jumlah prosesor / inti yang tersedia pada saat panggilan.

macbirdie
sumber
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.

Kepala Geek
sumber
4
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.
Chuck R
32

(Hampir) Platform Fungsi independen dalam kode-c

#ifdef _WIN32
#include <windows.h>
#elif MACOS
#include <sys/param.h>
#include <sys/sysctl.h>
#else
#include <unistd.h>
#endif

int getNumCores() {
#ifdef WIN32
    SYSTEM_INFO sysinfo;
    GetSystemInfo(&sysinfo);
    return sysinfo.dwNumberOfProcessors;
#elif MACOS
    int nm[2];
    size_t len = 4;
    uint32_t count;

    nm[0] = CTL_HW; nm[1] = HW_AVAILCPU;
    sysctl(nm, 2, &count, &len, NULL, 0);

    if(count < 1) {
        nm[1] = HW_NCPU;
        sysctl(nm, 2, &count, &len, NULL, 0);
        if(count < 1) { count = 1; }
    }
    return count;
#else
    return sysconf(_SC_NPROCESSORS_ONLN);
#endif
}
Dirk-Jan Kroon
sumber
Tampaknya HW_NCPUsudah usang pada sumber
16

Di Linux, Anda dapat membaca file / proc / cpuinfo dan menghitung inti.

JesperE
sumber
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 ...

jakobengblom2
sumber
7

Satu lagi resep Windows: gunakan variabel lingkungan sistem-lebar NUMBER_OF_PROCESSORS:

printf("%d\n", atoi(getenv("NUMBER_OF_PROCESSORS")));
Konstantin
sumber
7

Anda mungkin tidak akan bisa mendapatkannya di platform mandiri. Windows Anda mendapatkan sejumlah prosesor.

Informasi Sistem Win32

Ken
sumber
1
Hati-hati: Prosesor yang diacak mengatakan ada dua. Jadi, Anda juga perlu melihat apakah prosesor tersebut memiliki kemampuan HyperShread.
Martin York
6

Windows (x64 dan Win32) dan C ++ 11

Jumlah kelompok prosesor logis yang berbagi inti prosesor tunggal. (Menggunakan GetLogicalProcessorInformationEx , lihat GetLogicalProcessorInformation juga)

size_t NumberOfPhysicalCores() noexcept {

    DWORD length = 0;
    const BOOL result_first = GetLogicalProcessorInformationEx(RelationProcessorCore, nullptr, &length);
    assert(GetLastError() == ERROR_INSUFFICIENT_BUFFER);

    std::unique_ptr< uint8_t[] > buffer(new uint8_t[length]);
    const PSYSTEM_LOGICAL_PROCESSOR_INFORMATION_EX info = 
            reinterpret_cast< PSYSTEM_LOGICAL_PROCESSOR_INFORMATION_EX >(buffer.get());

    const BOOL result_second = GetLogicalProcessorInformationEx(RelationProcessorCore, info, &length);
    assert(result_second != FALSE);

    size_t nb_physical_cores = 0;
    size_t offset = 0;
    do {
        const PSYSTEM_LOGICAL_PROCESSOR_INFORMATION_EX current_info =
            reinterpret_cast< PSYSTEM_LOGICAL_PROCESSOR_INFORMATION_EX >(buffer.get() + offset);
        offset += current_info->Size;
        ++nb_physical_cores;
    } while (offset < length);

    return nb_physical_cores;
}

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.

Jumlah prosesor logis. (Menggunakan GetSystemInfo )

size_t NumberOfSystemCores() noexcept {
    SYSTEM_INFO system_info;
    ZeroMemory(&system_info, sizeof(system_info));

    GetSystemInfo(&system_info);

    return static_cast< size_t >(system_info.dwNumberOfProcessors);
}

Perhatikan bahwa kedua metode dapat dengan mudah dikonversi ke C / C ++ 98 / C ++ 03.

Matthias
sumber
1
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.

sezero
sumber
4

Tidak terkait dengan C ++, tetapi di Linux biasanya saya lakukan:

grep processor /proc/cpuinfo | wc -l

Berguna untuk bahasa skrip seperti bash / perl / python / ruby.

Chris
sumber
4
Untuk python:import multiprocessing print 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.)

Akhil
sumber
3

Di linux cara pemrograman terbaik sejauh yang saya tahu adalah menggunakan

sysconf(_SC_NPROCESSORS_CONF)

atau

sysconf(_SC_NPROCESSORS_ONLN)

Ini bukan standar, tetapi ada di halaman manual saya untuk Linux.

Evan Teran
sumber
3

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);
return 0;
}

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);
return 0;
}

Pendekatan yang sama di shell menggunakan grep:

grep -c ^processor /proc/cpuinfo

Atau

grep -c ^cpu /proc/stat # subtract 1 from the result
PP
sumber
2

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.

gauss256
sumber
2

Untuk Win32:

Sementara GetSystemInfo () memberi Anda jumlah prosesor logis , gunakan GetLogicalProcessorInformationEx () untuk mendapatkan jumlah prosesor fisik .

irrlicht_ist_toll
sumber
-2

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
-3

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.

Hernán
sumber