Bir makinedeki çekirdek sayısını programlı olarak bulma


464

Bir makinenin C / C ++ 'dan kaç tane çekirdeğe sahip olduğunu platformdan bağımsız bir şekilde belirlemenin bir yolu var mı? Böyle bir şey yoksa, platform başına (Windows / * nix / Mac) belirlemeye ne dersiniz?


4
Kullanmak için kaç tane konu başlatacağını öğrenmek istiyorsanız, lütfen birincil ölçü olarak NUMBER_OF_PROCESSORS kullanın. Bunun neden daha iyi olduğunu (insanlar daha fazla kullanırsa) donanım çekirdeğini kullanarak size bir egzersiz olarak bırakıyorum. Programınıza ne kadar çekirdek ait olduğu çevre sorunudur!
Lothar

Not std::thread::hardware_concurrencyfiziksel CPU çekirdek sayısını verir, ancak nprocLinux gösterir sadece CPU sayısı ile kontrol edilebilir üzerinde çalışabilir mevcut süreç, göbekler sched_setaffinity. Bunu standart C ++ 'dan almanın bir yolunu bulamadım: örneğin bkz. Python: stackoverflow.com/questions/1006289/…
Ciro Santilli 法轮功 冠状 病 六四 事件 法轮功

Yanıtlar:


706

C ++ 11

#include <thread>

//may return 0 when not able to detect
const auto processor_count = std::thread::hardware_concurrency();

Referans: std :: thread :: hardware_concurrency


C ++ 11'den önceki C ++ 'da taşınabilir bir yol yoktur. Bunun yerine, aşağıdaki yöntemlerden birini veya daha fazlasını kullanmanız gerekir (uygun #ifdefçizgilerle korunur ):

  • Win32

    SYSTEM_INFO sysinfo;
    GetSystemInfo(&sysinfo);
    int numCPU = sysinfo.dwNumberOfProcessors;
  • Linux, Solaris, AIX ve Mac OS X> = 10.4 (yani Tiger'dan sonra)

    int numCPU = sysconf(_SC_NPROCESSORS_ONLN);
  • FreeBSD, MacOS X, NetBSD, OpenBSD vb.

    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 veya iOS)

    NSUInteger a = [[NSProcessInfo processInfo] processorCount];
    NSUInteger b = [[NSProcessInfo processInfo] activeProcessorCount];

5
@mcandre: bu okuyucu için bir alıştırma olarak kaldı. Uygulamasaydım, muhtemelen politikanın önişlemci direktiflerinde tanımlandığı şablon-politika yaklaşımını kullanırdım. Veya ... boost thread :: hardware_concurrency () kullanabilirsiniz.
paxos1977

3
bir açıklama noktası olarak, Win32 çözümü toplam fiziksel CPU sayısını değil, istenen çekirdek sayısını (ne istenir) döndürür.
Eric

1
Linux / Solaris / AIX yolu da FreeBSD üzerinde çalışıyor ve en az 2006'dan beri var. Ayrıca, bir sistem bazılarını kapatabiliyorsa, CPU'ları çevrimiçi olarak döndürecek sayılmayabilir. "_SC_NPROCESSORS_CONF" ile sysconf çağrıldığında, yapılandırılan toplam CPU'lar döndürülür.
Chris S

3
Dikkat edilmesi gereken birkaç şey. HW_NCPUWindows'ta GetSystemInfoyalnızca sisteminizde 32 veya daha az mantıksal işlemci varsa, 32'den fazla mantıksal işlemcisi GetLogicalProcessorInformationolan sistemler için kullanın .

1
@Trejkaz belgesel açıkça "mantıksal" diyor - ki bu her zaman HT çekirdeklerini sayıyor, "fiziksel" kelimesi her zaman BIOS / UEFI tarafından rapor edilen çekirdekler anlamına geliyor çünkü çekirdekler de taklit edilebilir / sanallaştırılabilir. HT / HT olmayan çekirdekler arasında örneğin GetLogicalProcessorInformation gibi işlevlerle ayrım yapabilirsiniz . Not: HT! = Öykünme veya sanallaştırma, bu büyük bir fark, HT bir donanım optimizasyonudur, tabiri caizse
uzman 9

202

Bu işlevsellik, C ++ 11 standardının bir parçasıdır.

#include <thread>

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

Daha eski derleyiciler için Boost.Thread kütüphanesini kullanabilirsiniz .

#include <boost/thread.hpp>

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

Her iki durumda da, hardware_concurrency()CPU çekirdeği ve hiper iş parçacığı birimlerinin sayısına bağlı olarak donanımın eşzamanlı olarak çalıştırabildiği iş parçacığı sayısını döndürür.


1
İkincisi ... yukarıdaki örnek kodu ve bazı önişlemci makrolarını tek bir işlevi ortaya çıkarmak için kullanacaktı, ama zor iş benim için yapıldı.
jkp

Win32 için, GetSystemInfo çağrısıdır. (Boost Sürüm 1.41.0'dan itibaren) Bu, kaç çalışan iş parçacığının etkili olacağını belirlemek için tüm bilgileri yakalar mı? Kişi hem çekirdek sayısını hem de hiper iş parçacığını dikkate almalı mı? unsigned thread :: hardware_concurrency () {SYSTEM_INFO info = {0}; GetSystemInfo (& bilgi); return info.dwNumberOfProcessors; }
Jive Dadson

MSDN'ye göre, GetSystemInfo () dwNumberOfProcessors içindeki "fiziksel işlemci" sayısını döndürür, ancak bunun ne anlama geldiğini tanımlamaz. Boost belgeleri, hiper iş parçacığı birimleri içerdiğini iddia ediyor gibi görünüyor.
Ferruccio


57

OpenMP birçok platformda (Visual Studio 2005 dahil) desteklenir ve bir

int omp_get_num_procs();

çağrı sırasında kullanılabilen işlemci / çekirdek sayısını döndüren işlev.


çünkü bu yanlış bir cevap. Gönderen gcc.gnu.org/bugzilla/show_bug.cgi?id=37586 çağıran süreci ve / veya iplik varsa) ( "omp_get_num_procs sadece GOMP_CPU_AFFINITY env var kullanılırsa, çevrimiçi sistem CPU sayısından daha az sayıda iade eder Msgstr "CPU benzeşimi bir CPU alt kümesiyle sınırlı" + + msgid ". Yani daha önce örneğin ararsanız, sched_setaffinitybu işe yaramaz.
angainor

7
Bu işlev, arama işlemi için kullanılabilir CPU sayısını döndürür. Zaten en yaygın kullanım durumu değil mi? Bazı yararsız raporlama amaçlarından ötürü, kodunuzda bunlardan yararlanamıyorsanız, gerçek CPU donanım çekirdeği sayısı sizin için geçerli değildir.
macbirdie

@EvanTeran Sorunun amacı olduğu gerçeğinin yanı sıra, elbette faydalı olabilir. Örneğin, iplik yakınlığını ayarlamak amacıyla. Diyelim ki, makinemde dört adet ilk çekirdek yerine son dört CPU çekirdeğine bağlı 4 iş parçacığı çalıştırmak istiyorum. Bunun yanı sıra, OpenMP dışında kodu paralel hale getirmenin başka yolları da vardır. Pthreads'i kendim doğurmak isteyebilirim. Bunlar kesinlikle mevcuttur ve OpenMP ortam değişkenleri tarafından sınırlandırılmamıştır.
angainor

2
Bu, çekirdek (fiziksel CPU) sayısını değil, mantıksal CPU sayısını döndürür.
Michael Konečný

37

Montaj dili erişiminiz varsa, CPU hakkında her türlü bilgiyi almak için CPUID komutunu kullanabilirsiniz. İşletim sistemleri arasında taşınabilir, ancak çekirdek sayısını nasıl bulacağınızı belirlemek için üreticiye özgü bilgileri kullanmanız gerekir. İşte bir Intel çipleri üzerinde nasıl yapılacağını açıklar belge ve sayfa 11 bu bir AMD şartname açıklar.


4
Soru C ++ olarak etiketlendiğinden ve bu yanıt x86 dışı mimarilerde (ARM, PPC, vb.) C ++ çalıştıran sistemler için geçerli olmadığından aşağı indirilmiş olabilir. Bir cevabı küçümsemek için iyi bir neden olduğunu söylemiyorum, sadece bir olasılık.
Ferruccio

3
Bu yöntemin bir sorunu, Intel işlemcilerde HyperThreading'i algılamak için CPUID kullanıyorsanız. Dizüstü bilgisayarımda bu problemle karşılaştım: makineye koyduğum CPU HyperThreading'i destekliyorsa (ve tabii ki CPUID üzerinden olduğunu bildiriyorsa), BIOS desteklemiyor. Bu nedenle, HT özelliğini yalnızca bir CPUID okumasından kullanmaya çalışmamalısınız. BIOS'u HT desteği hakkında sorgulayamadığınızdan (gördüğüm şekilde değil), mantıksal işlemci sayısını elde etmek için işletim sistemi sorgulanmalıdır.
Chuck R

32

(Neredeyse) Platform C kodunda bağımsız işlev

#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
}

Görünüşe göre HW_NCPUOS X kaynağında

16

Linux'ta / proc / cpuinfo dosyasını okuyabilir ve çekirdekleri sayabilirsiniz.


Bunun dışında hiper iş parçacıklı veya diğer SMT çözümlerini daha fazla çekirdek olarak sayar ...
jakobengblom2

13
@Arafangion: hiper iş parçacığı gerçek paralel yürütme değildir, bağlam değiştirme yükünü azaltmak için bir teknolojidir. Hiper iş parçacıklı bir işlemci aynı anda yalnızca bir iş parçacığı yürütebilir , ancak aynı anda iki iş parçacığının mimari durumunu (kayıt değerleri vb.) Depolayabilir. Performans özellikleri iki çekirdeğe sahip olmaktan çok farklıdır.
Wim Coenen

7
@Wim: Bu tamamen doğru değil. Hiper iş parçacıklı CPU'lar genellikle birden fazla ALU'ya sahiptir ve döngü başına birden fazla talimat gönderebilir. Veri bağımlılıkları ve duraklamalar nedeniyle, tüm ALU'lar bir iş parçacığı tarafından meşgul edilemezse, bunun yerine bu ALU'lar ikinci donanım iş parçacığının eşzamanlı yürütülmesi için kullanılacaktır.
Ben Voigt

11

"Çekirdek sayısı" nın özellikle kullanışlı bir sayı olmayabileceğini, biraz daha nitelendirmeniz gerekebileceğini unutmayın. Intel HT, IBM Power5 ve Power6 gibi çok iş parçacıklı CPU'ları ve en ünlüsü Sun'ın Niagara / UltraSparc T1 ve T2'yi nasıl saymak istersiniz? Daha da ilginç olanı, iki donanım iş parçacığı (denetimci ve kullanıcı düzeyi) düzeyiyle MIPS 1004k ... Donanımın onlarca CPU'su olabileceği hipervizör destekli sistemlere geçtiğinizde ne olacağından bahsetmiyorum. sadece birkaç tanesini görür.

Umabileceğiniz en iyi şey, yerel işletim sistemi bölümünüzde bulunan mantıksal işlem birimlerinin sayısını söylemektir. Hipervizör değilseniz gerçek makineyi görmeyi unutun. Bugün bu kuralın tek istisnası x86 ülkesinde, ancak sanal olmayan makinelerin sonu hızla geliyor ...


7

Bir Windows tarifi daha: sistem genelinde ortam değişkenini kullanın NUMBER_OF_PROCESSORS:

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

7

Muhtemelen platformdan bağımsız bir şekilde elde edemezsiniz. Windows size işlemci sayısını alırsınız.

Win32 Sistem Bilgileri


1
Dikkatli: Hiper iş parçacıklı işlemciler iki tane olduğunu söylüyor. Bu yüzden işlemcinin hiper iş parçacığı özellikli olup olmadığını da görmeniz gerekir.
Martin York

6

Windows (x64 ve Win32) ve C ++ 11

Tek bir işlemci çekirdeğini paylaşan mantıksal işlemci gruplarının sayısı. ( GetLogicalProcessorInformationEx kullanarak , ayrıca bkz. GetLogicalProcessorInformation )

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;
}

Uygulamasının NumberOfPhysicalCoresIMHO'nun önemsiz olmaktan çok uzak olduğunu unutmayın (yani "kullanım GetLogicalProcessorInformationveya GetLogicalProcessorInformationEx"). Bunun yerine, MSDN'deki belgeleri (açık bir şekilde sunmak GetLogicalProcessorInformationve dolaylı olarak sunmak için GetLogicalProcessorInformationEx) okumak oldukça incedir.

Mantıksal işlemci sayısı. ( GetSystemInfo Kullanılıyor )

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

Her iki yöntemin de kolayca C / C ++ 98 / C ++ 03'e dönüştürülebileceğini unutmayın.


1
Teşekkür ederim! GetLogicalProcessorInformationKullandığım çeşitli tampon boyutları ile çalışmadığı için bunu arıyordum . Memnun olmaktan daha fazlası! ^^
KeyWeeUsr

@KeyWeeUsr Teşekkürler Windows programlama biraz önemsiz ve mantıklı. Bu arada, biraz daha güncellenmiş C ++ 17 sürümünü kullanıyorum, bu da bazı size_toyuncular için statik analizör PVS-Studio'ya göre daha doğru . (Rağmen, msvc ++ W4 şikayet değil.)
Matthias

5

OS X hakkında daha fazla bilgi: sysconf(_SC_NPROCESSORS_ONLN)10.4 sürümünde değil, sadece> 10.5 sürümü mevcuttur.

Alternatif, HW_AVAILCPU/sysctl()> = 10.2 sürümlerinde bulunan BSD kodudur.



4

C ++ ile ilgisi yoktur, ancak Linux'ta genellikle şunu yaparım:

grep processor /proc/cpuinfo | wc -l

Bash / perl / python / ruby ​​gibi komut dilleri için kullanışlıdır.


4
Python için:import multiprocessing print multiprocessing.cpu_count()
initzero

3
Çok uzun zaman oldu, ama grepvardır -csayım girişlerine bayrak!
Lapshin Dmitry

Uzun zaman oldu, ama Raspberry model name : ARMv6-compatible processor rev 7 (v6l)grep -c ^processor /proc/cpuinfo
Pi'm cpuinfo'sunda

3

hwloc (http://www.open-mpi.org/projects/hwloc/) göz atmaya değer. Kodunuza başka bir kütüphane entegrasyonu gerektirmesine rağmen, işlemcinizle ilgili tüm bilgileri sağlayabilir (çekirdek sayısı, topoloji, vb.)


3

Linux'ta bildiğim kadarıyla en iyi programlı yöntem

sysconf(_SC_NPROCESSORS_CONF)

veya

sysconf(_SC_NPROCESSORS_ONLN)

Bunlar standart değil, Linux için man sayfamda.


3

Linux'ta, _SC_NPROCESSORS_ONLNPOSIX standardının bir parçası olmadığı ve sysconf manuel durumlarının fazla olmadığı için kullanmak güvenli olmayabilir . Yani _SC_NPROCESSORS_ONLNmevcut olmayan bir olasılık var:

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

Basit bir yaklaşım onları okumak /proc/statveya /proc/cpuinfosaymak olacaktır:

#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;
}

Kullanma /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;
}

Grep kullanarak kabukta aynı yaklaşım:

grep -c ^processor /proc/cpuinfo

Veya

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

2

OS X alternatifi: Daha önce [[NSProcessInfo processInfo] işlemciCount] 'a dayalı olarak açıklanan çözüm dokümanlara göre yalnızca OS X 10.5.0'da kullanılabilir. OS X'in önceki sürümleri için, MPProcessors () Karbon işlevini kullanın.

Bir Kakao programcısıysanız, bunun Karbon olduğu gerçeğinden korkmayın. Sadece Xcode projenize Karbon çerçevesini eklemeniz gerekir ve MPProcessors () kullanılabilir olacaktır.



-2

WMI'yı .net içinde de kullanabilirsiniz, ancak wmi hizmetinin çalışmasına vb. bağımlı olursunuz. Bazen yerel olarak çalışır, ancak sunucularda aynı kod çalıştırıldığında başarısız olur. Bence bu, değerleri okuduğunuz "adlar" ile ilgili bir ad alanı sorunu.


-3

Linux'ta, dmesg'e göz atabilir ve ACPI'nin CPU'ları başlattığı satırları filtreleyebilirsiniz, örneğin:

dmesg | grep 'ACPI: Processor'

Diğer olasılık, işlemci bilgisini filtrelemek için dmidecode kullanmaktır.

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.