프로그래밍 방식으로 머신에서 코어 수 찾기


464

플랫폼 독립적 인 방식으로 머신이 C / C ++의 코어 수를 결정하는 방법이 있습니까? 그러한 것이 없다면 플랫폼 별 (Windows / * nix / Mac)을 결정하는 것은 어떻습니까?


4
사용하려면 시작하는 스레드 수를 확인하십시오. 기본 측정으로 NUMBER_OF_PROCESSORS를 사용하십시오. 하드웨어 코어를 사용하는 것보다 더 나은 이유를 사람들이 더 많이 사용하는 이유를 설명합니다. 프로그램에 속하는 코어의 양은 환경 문제입니다!
Lothar

std::thread::hardware_concurrency물리적 CPU 코어 수 를 반환하지만 nprocLinux에서는 현재 프로세스가 실행될 수있는 CPU 코어 수만 표시합니다 sched_setaffinity. : 내가 대신 표준 C ++에서 :, 예를 들어 파이썬에서 볼 것을 얻을 수있는 방법을 발견하지 않았습니다 stackoverflow.com/questions/1006289/...
치로 틸리郝海东冠状病六四事件法轮功

답변:


706

C ++ 11

#include <thread>

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

참조 : std :: thread :: hardware_concurrency


C ++ 11 이전의 C ++에서는 이식 가능한 방법이 없습니다. 대신 다음 방법 중 하나 이상을 사용해야합니다 (적절한 #ifdef행으로 보호 ).

  • Win32

    SYSTEM_INFO sysinfo;
    GetSystemInfo(&sysinfo);
    int numCPU = sysinfo.dwNumberOfProcessors;
  • Linux, Solaris, AIX 및 Mac OS X> = 10.4 (즉, Tiger 이상)

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

    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 또는 iOS)

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

5
@ mcandre : 그것은 독자를위한 연습으로 남아 있습니다. 구현하는 경우 정책이 전 처리기 지시문에 정의 된 템플릿 정책 접근 방식을 사용했을 것입니다. 또는 ... boost thread :: hardware_concurrency ()를 사용할 수 있습니다.
paxos1977

3
설명을 위해 Win32 솔루션은 총 물리적 CPU 수가 아닌 총 코어 수 (요청한 것)를 반환합니다.
Eric

1
Linux / Solaris / AIX 방식은 FreeBSD에서도 작동하며 최소한 2006 년부터 운영되고 있습니다. 또한 시스템을 끄면 CPU를 온라인 상태로 되돌릴 수 있습니다. "_SC_NPROCESSORS_CONF"와 함께 sysconf를 호출하면 구성된 총 CPU가 반환됩니다.
Chris S

3
알아야 할 몇 가지 사항. HW_NCPUOS X에서는 더 이상 사용되지 않습니다. Windows GetSystemInfo에서는 시스템에 32 개의 논리 프로세서가있는 경우에만 유용 GetLogicalProcessorInformation하며 32 개 이상의 논리 프로세서가있는 시스템에 사용하십시오 .

1
@Trejkaz 문서는 명확하게 "논리적"이라고 말합니다. 항상 HT 코어를 계산하고 있습니다. "물리적" 이라는 단어 는 코어가 에뮬레이션 / 가상화 될 수 있으므로 BIOS / UEFI에서보고 한 코어를 항상 나타냅니다. 예를 들어 GetLogicalProcessorInformation 과 같은 기능을 사용하여 HT / 비 HT 코어를 구별 할 수 있습니다 . !주의 : HT = 에뮬레이션이나 가상화는 이잖아 HT 말하자면, 하드웨어 최적화하고, 차이를
specializt

202

이 기능은 C ++ 11 표준의 일부입니다.

#include <thread>

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

구형 컴파일러의 경우 Boost.Thread 라이브러리를 사용할 수 있습니다 .

#include <boost/thread.hpp>

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

두 경우 모두, hardware_concurrency()CPU 코어 수와 하이퍼 스레딩 장치 수에 따라 하드웨어가 동시에 실행할 수있는 스레드 수를 반환합니다.


1
두 번째로 ... 위의 샘플 코드와 일부 전 처리기 매크로를 사용하여 단일 기능을 노출하려고했지만 열심히 노력했습니다.
jkp

win32의 경우 GetSystemInfo를 호출합니다. (부스트 버전 1.41.0 현재) 얼마나 많은 작업자 스레드가 효과적인지 결정하기 위해 모든 정보를 캡처합니까? 코어 수와 하이퍼 스레딩을 모두 고려해야합니까? 부호없는 스레드 :: hardware_concurrency () {SYSTEM_INFO info = {0}; GetSystemInfo (& info); info.dwNumberOfProcessors를 리턴하십시오. }
Jive Dadson

MSDN에 따르면 GetSystemInfo ()는 dwNumberOfProcessors에서 "물리적 프로세서"의 수를 반환하지만 그 의미를 정의하지는 않습니다. Boost 문서에는 하이퍼 스레딩 장치가 포함되어 있다고 주장하는 것 같습니다.
Ferruccio

하이퍼 스레딩에 대해서는 stackoverflow.com/questions/642348/… 을 참조하십시오
naugtur

57

OpenMP 는 많은 플랫폼 (Visual Studio 2005 포함)에서 지원되며

int omp_get_num_procs();

호출시 사용 가능한 프로세서 / 코어 수를 반환하는 함수입니다.


답이 틀리기 때문입니다. 에서 gcc.gnu.org/bugzilla/show_bug.cgi?id=37586 호출 처리 및 / 또는 스레드가있는 경우) ( "omp_get_num_procs은 GOMP_CPU_AFFINITY ENV var에 사용하는 경우, 온라인 시스템 CPU의 수보다 작은 수를 반환, 또는 것 CPU 선호도는 CPU의 하위 집합으로 제한됩니다. " 따라서 예를 들어 이전에 전화하면 sched_setaffinity작동하지 않습니다.
angainor

7
이 함수는 호출 프로세스에 사용 가능한 CPU 수를 반환합니다. 어쨌든 가장 일반적인 사용 사례가 아닙니까? 일부 쓸모없는보고 목적보다 크기가 크므로 실제 CPU 하드웨어 코어 수는 코드에서이를 활용할 수없는 경우 관련이 없습니다.
macbirdie

@EvanTeran 질문의 목적이라는 사실 외에도 물론 유용 할 수 있습니다. 예를 들어 스레드 선호도를 설정하기 위해. 예를 들어, 4 개의 첫 번째 코어 대신 내 컴퓨터에서 4 개의 마지막 CPU 코어에 바인딩 된 4 개의 스레드를 실행하려고합니다. 또한 OpenMP를 제외하고 코드를 병렬화하는 다른 방법이 있습니다. pthreads를 직접 생성하고 싶을 수도 있습니다. 그것들은 확실히 사용 가능하며 OpenMP 환경 변수에 의해 제한되지 않습니다.
angainor

2
이것은 코어 (실제 CPU)가 아닌 논리 CPU 수를 반환합니다.
Michael Konečný 2016 년

37

어셈블리 언어 액세스 권한이있는 경우 CPUID 명령어를 사용하여 CPU에 대한 모든 종류의 정보를 얻을 수 있습니다. 운영 체제간에 이식 가능하지만 제조업체 별 정보를 사용하여 코어 수를 찾는 방법을 결정해야합니다. 다음 은 인텔 칩 에서 수행하는 방법을 설명하는 문서이며이 11 페이지 는 AMD 사양을 설명합니다.


4
질문에 C ++로 태그되어 있기 때문에 다운 투표되었을 수 있으며이 답변은 x86 이외의 아키텍처 (ARM, PPC 등)에서 C ++를 실행하는 시스템에는 적용되지 않습니다. 나는 대답을 내리는 것이 좋은 이유라고 말하지는 않습니다.
Ferruccio

3
이 방법의 한 가지 단점은 CPUID를 사용하여 Intel 프로세서에서 HyperThreading을 감지하는 것입니다. 랩톱 에서이 문제가 발생했습니다. 컴퓨터에 넣은 CPU가 HyperThreading을 지원하지만 CPUID를 통해 수행한다고보고하지만 BIOS는 그렇지 않습니다. 따라서 단순히 CPUID 읽기에서 HT 기능을 사용하려고 시도해서는 안됩니다. HT 지원에 대해 BIOS에 쿼리 할 수 ​​없으므로 (내가 본 방법은 없음) 논리 프로세서 수를 얻기 위해 OS를 쿼리해야합니다.
척 R

32

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
}

같은데 HW_NCPUOS X 용에 사용되지 않습니다 소스

16

Linux에서는 / proc / cpuinfo 파일을 읽고 코어를 계산할 수 있습니다.


... 그 또한 카운트가 더 많은 코어와 같은 다른 SMT 솔루션을 하이퍼 스레드 또는 것을 제외
jakobengblom2

13
@Arafangion : 하이퍼 스레딩은 진정한 병렬 실행이 아니며 컨텍스트 전환 오버 헤드를 줄이는 기술입니다. 하이퍼 스레드 CPU는 한 번에 하나의 스레드 만 실행할 수 있지만 동시에 두 스레드의 아키텍처 상태 (값 등록 등)를 저장할 수 있습니다. 성능 특성은 두 개의 코어를 갖는 것과는 매우 다릅니다.
Wim Coenen

7
@Wim : 완전히 정확하지 않습니다. 하이퍼 스레딩이있는 CPU에는 일반적으로 여러 ALU가 있으며주기 당 여러 명령을 디스패치 할 수 있습니다. 데이터 종속성 및 중단으로 인해 하나의 스레드가 모든 ALU를 사용하지 않을 수있는 경우 해당 ALU는 대신 두 번째 하드웨어 스레드를 동시에 실행하는 데 사용됩니다.
Ben Voigt

11

"코어 수"는 특히 유용한 숫자가 아닐 수 있으므로 조금 더 한정해야 할 수도 있습니다. Intel HT, IBM Power5 및 Power6과 같은 멀티 스레드 CPU와 Sun의 Niagara / UltraSparc T1 및 T2를 가장 잘 계산하려면 어떻게 하시겠습니까? 더 흥미로운 점은 두 가지 수준의 하드웨어 스레딩 (감독자 및 사용자 수준)을 갖춘 MIPS 1004k입니다. 하드웨어에 수십 개의 CPU가 있지만 특정 OS가있는 하이퍼 바이저 지원 시스템으로 이동할 때 발생하는 상황은 말할 것도 없습니다. 몇 개만 봅니다.

로컬 OS 파티션에있는 논리 처리 장치 수를 알려주는 것이 가장 좋습니다. 하이퍼 바이저가 아닌 한 실제 머신을 보는 것을 잊어 버리십시오. 오늘날이 규칙에 대한 유일한 예외는 x86 육상이지만, 비가 상 머신의 끝은 빨라지고 있습니다 ...


7

하나 이상의 Windows 레시피 : 시스템 전체 환경 변수 사용 NUMBER_OF_PROCESSORS:

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

7

플랫폼 독립적 인 방식으로는 얻을 수 없을 것입니다. Windows에는 많은 프로세서가 있습니다.

Win32 시스템 정보


1
주의 : 하이퍼 스레딩 프로세서에는 두 가지가 있다고 말합니다. 따라서 프로세서가 하이퍼 스레드를 지원하는지 확인해야합니다.
Martin York

6

Windows (x64 및 Win32) 및 C ++ 11

단일 프로세서 코어를 공유하는 논리 프로세서 그룹 수입니다. (사용 GetLogicalProcessorInformationEx를 참조 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;
}

구현은 NumberOfPhysicalCores사소한 것과는 거리가 멀다 (즉, "사용 GetLogicalProcessorInformation또는 GetLogicalProcessorInformationEx"). 대신 MSDN 의 설명서 (명시 적으로 존재 GetLogicalProcessorInformation하고 암시 적으로 존재 함)를 읽는 것이 다소 미묘합니다 GetLogicalProcessorInformationEx.

논리 프로세서 수 ( 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);
}

두 방법 모두 C / C ++ 98 / C ++ 03으로 쉽게 변환 될 수 있습니다.


1
감사합니다! 내가 GetLogicalProcessorInformation사용한 다양한 버퍼 크기로 작동하지 않기 때문에 이것을 찾고있었습니다 . 만족 이상! ^^
KeyWeeUsr

@KeyWeeUsr 감사합니다 Windows 프로그래밍은 사소하고 논리적이 아닙니다. 한편, 약간 더 업데이트 된 C ++ 17 버전을 사용 하는데, 이는 일부 size_t캐스트 와 관련하여 정적 분석기 PVS-Studio에 따라 더 정확합니다 . (msvc ++는 W4에서 불평하지 않지만)
Matthias

5

OS X에 대한 추가 정보 : sysconf(_SC_NPROCESSORS_ONLN)10.4가 아닌> 10.5 버전에서만 사용 가능합니다.

대안은 HW_AVAILCPU/sysctl()BSD 코드이며> = 10.2 버전에서 사용할 수 있습니다.



4

C ++과 관련이 없지만 Linux에서는 보통 다음을 수행합니다.

grep processor /proc/cpuinfo | wc -l

bash / perl / python / ruby와 같은 스크립팅 언어에 편리합니다.


4
파이썬의 경우 :import multiprocessing print multiprocessing.cpu_count()
initzero

3
오랜 시간 grep-c지났지 만 항목을 세는 플래그가 있습니다!
Lapshin Dmitry

3

hwloc (http://www.open-mpi.org/projects/hwloc/)을 살펴볼 가치가 있습니다. 코드에 다른 라이브러리 통합이 필요하지만 프로세서에 대한 모든 정보 (코어 수, 토폴로지 등)를 제공 할 수 있습니다.


3

리눅스에서는 내가 아는 한 프로그래밍 방식이 가장 좋습니다.

sysconf(_SC_NPROCESSORS_CONF)

또는

sysconf(_SC_NPROCESSORS_ONLN)

이것들은 표준은 아니지만 Linux의 맨 페이지에 있습니다.


3

Linux에서는 _SC_NPROCESSORS_ONLNPOSIX 표준 및 sysconf 매뉴얼 상태에 포함 되지 않으므로 사용하기에 안전하지 않을 수 있습니다 . 따라서 존재 _SC_NPROCESSORS_ONLN하지 않을 가능성이 있습니다.

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

간단한 접근법은 그것들 을 읽 /proc/stat거나 /proc/cpuinfo세는 것입니다.

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

사용 /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을 사용하는 쉘에서 동일한 접근법 :

grep -c ^processor /proc/cpuinfo

또는

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

2

OS X 대안 : [[NSProcessInfo processInfo] processorCount]를 기반으로 앞에서 설명한 솔루션은 문서에 따라 OS X 10.5.0에서만 사용할 수 있습니다. 이전 버전의 OS X의 경우 Carbon 함수 MPProcessors ()를 사용하십시오.

코코아 프로그래머라면 이것이 카본이라는 사실에 놀라지 마십시오. Xcode 프로젝트에 Carbon 프레임 워크를 추가하기 만하면 MPProcessors ()를 사용할 수 있습니다.



-2

.net에서도 WMI를 사용할 수 있지만 wmi 서비스 실행 등에 의존합니다. 때로는 로컬에서 작동하지만 서버에서 동일한 코드가 실행될 때 실패합니다. 값을 읽는 "이름"과 관련된 네임 스페이스 문제라고 생각합니다.


-3

Linux에서는 다음과 같이 dmesg를 체크 아웃하고 ACPI가 CPU를 초기화하는 라인을 필터링 할 수 있습니다.

dmesg | grep 'ACPI: Processor'

다른 가능성은 dmidecode를 사용하여 프로세서 정보를 필터링하는 것입니다.

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.