IT이야기

프로그래밍 방식으로 시스템의 코어 수 찾기

cyworld 2022. 4. 24. 09:40
반응형

프로그래밍 방식으로 시스템의 코어 수 찾기

플랫폼에 독립적인 방식으로 C/C++에서 얼마나 많은 코어를 가지고 있는지 판단할 수 있는 방법이 있는가?만약 그러한 것이 존재하지 않는다면, 플랫폼별 (Windows/*nix/Mac)을 결정하는 것은 어떨까?

C++11

#include <thread>

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

참조: std::thread::하드웨어_concurrency


C++11 이전의 C++에서는 휴대할 수 있는 방법이 없다.중할 것이다( 대승다지의 보호).#ifdef선:

  • 윈32년

    SYSTEM_INFO sysinfo;
    GetSystemInfo(&sysinfo);
    int numCPU = sysinfo.dwNumberOfProcessors;
    
  • Linux, Solaris, AIX 및 Mac OS X >=10.4(즉,타이거 앞으로)

    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;
    }
    
  • 휴푸스

    int numCPU = mpctl(MPC_GETNUMSPUS, NULL, NULL);
    
  • 아이릭스

    int numCPU = sysconf(_SC_NPROC_ONLN);
    
  • 목표-C (Mac OS X >=10.5 또는 iOS)

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

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

#include <thread>

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

나이든 컴파일러의 경우 부스트를 사용할 수 있다.스레드 라이브러리.

#include <boost/thread.hpp>

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

둘 중 어느 경우에도hardware_concurrency()CPU 코어 수와 하이퍼 스레드 단위를 기반으로 하드웨어가 동시에 실행할 수 있는 스레드 수를 반환한다.

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

int omp_get_num_procs();

호출 시 사용할 수 있는 프로세서/프로세서 수를 반환하는 기능.

(대부분) 플랫폼 독립 기능(c-code)

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

어셈블리 언어 액세스 권한이 있는 경우 CPUID 명령을 사용하여 CPU에 대한 모든 종류의 정보를 얻을 수 있다.운영 체제 간 이동 가능하지만, 코어 수를 찾는 방법을 결정하려면 제조업체별 정보를 사용해야 한다.여기 인텔 칩에서 그것을 하는 방법을 설명하는 문서가 있는데, 이 문서의 11페이지에는 AMD 사양이 설명되어 있다.

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

의 구현에 유의하십시오.NumberOfPhysicalCoresIMHO는 사소한 것(즉, "사용")과는 거리가 멀다.GetLogicalProcessorInformation또는GetLogicalProcessorInformationEx". 대신 문서를 읽는 것은 다소 미묘하다. (명백하게 다음에 대해 제시).GetLogicalProcessorInformation을 위해 암묵적으로 존재하는.GetLogicalProcessorInformationExMSDN에서 입니다.

논리 프로세서 수. (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으로 쉽게 변환할 수 있다는 점에 유의하십시오.

C++와는 무관하지만 Linux에서는 대개 다음과 같이 한다.

grep processor /proc/cpuinfo | wc -l

bash/perl/python/ruby와 같은 스크립팅 언어에 유용하다.

Linux에서는 /proc/cpuinfo 파일을 읽고 코어를 셀 수 있다.

한 가지 더 많은 Windows 레시피: 시스템 전체 환경 변수 사용NUMBER_OF_PROCESSORS:

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

"코어의 수"는 특별히 유용한 숫자가 아닐 수 있으므로, 좀 더 많은 자격을 부여해야 할 수 있다는 점에 유의하십시오.Intel HT, IBM Power5 및 Power6와 같은 다중 스레드 CPU를 어떻게 계산하시겠습니까? 그리고 가장 유명한 Sun의 Niagara/UltraSparc T1 및 T2를 선택하십시오.또는 더욱 흥미로운 것은 두 가지 수준의 하드웨어 스레딩(감독자 AND 사용자 수준)을 갖춘 MIPS 1004k...하이퍼바이저 지원 시스템으로 이동하면 하드웨어에 CPU가 수십 개 있을 수 있지만 특정 OS에는 몇 개만 표시되는 경우는 말할 것도 없다.

로컬 OS 파티션에 있는 논리 처리 단위의 개수를 알려 주는 것이 가장 좋은 방법은 로컬 OS 파티션에 있는 논리 처리 단위의 개수를 알려 주는 것이다.하이퍼바이저가 아닌 이상 실제 시스템을 볼 필요가 없다.오늘날 이 규칙의 유일한 예외는 x86 땅이지만, 비가상 시스템의 종말이 빠르게 다가오고 있다...

내가 아는 한 리눅스 에서 가장 프로그램적인 방법은

sysconf(_SC_NPROCESSORS_CONF)

또는

sysconf(_SC_NPROCESSORS_ONLN)

이것은 표준은 아니지만 Linux를 위한 man 페이지에 있다.

OS X에 대한 자세한 정보:sysconf(_SC_NPROCESSORS_ONLN)10.4가 아닌 >= 10.5 버전만 사용할 수 있다.

.HW_AVAILCPU/sysctl()버전 >= 10.2에서 사용할 수 있는 BSD 코드.

Win32의 경우:

GetSystemInfo()가 논리 프로세서 수를 얻는 반면 GetLogicalProcessorInformationEx()를 사용하여 물리적 프로세서 수를 얻으십시오.

OS X 대안:[[NSProcess]를 기반으로 앞에서 설명한 솔루션정보 프로세스Info] processorCount]는 문서에 따라 OS X 10.5.0에서만 사용할 수 있다.이전 버전의 OS X의 경우 Carbon 함수 MPProcessor()를 사용하십시오.

만약 당신이 코코아 프로그래머라면, 이것이 탄소라는 사실에 놀라지 마라.Xcode 프로젝트에 탄소 프레임워크를 추가하기만 하면 MPProcessor()를 사용할 수 있다.

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

아마 플랫폼 독립적으로 구할 수 없을 겁니다.Windows(윈도우)

Win32 시스템 정보

Windows Server 2003 이상에서는 GetLogicalProcessorInformation 기능을 활용할 수 있음

http://msdn.microsoft.com/en-us/library/ms683194.aspx

#include <stdint.h>

#if defined(__APPLE__) || defined(__FreeBSD__)
#include <sys/sysctl.h>

uint32_t num_physical_cores(void)
{
    uint32_t num_cores      = 0;
    size_t num_cores_len    = sizeof(num_cores);

    sysctlbyname("hw.physicalcpu", &num_cores, &num_cores_len, 0, 0);

    return num_cores;
}
#elif defined(__linux__)
#include <unistd.h>
#include <stdio.h>
uint32_t num_physical_cores(void)
{
    uint32_t lcores = 0, tsibs = 0;

    char buff[32];
    char path[64];

    for (lcores = 0;;lcores++) {
        FILE *cpu;

        snprintf(path, sizeof(path), "/sys/devices/system/cpu/cpu%u/topology/thread_siblings_list", lcores);

        cpu = fopen(path, "r");
        if (!cpu) break;

        while (fscanf(cpu, "%[0-9]", buff)) {
            tsibs++;
            if (fgetc(cpu) != ',') break;
        }

        fclose(cpu);
    }

    return lcores / (tsibs / lcores);
}
#else
#error Unrecognized operating system
#endif

이렇게 하면 시스템의 물리적 코어 수가 반환된다.이는 대부분의 답변이 제공하는 논리 코어 수와 다르다.차단 I/O를 수행하지 않고 절전 모드로 전환되지 않는 스레드 풀의 크기를 확인하려면 논리적(하이퍼 스레딩) 코어 수가 아니라 물리적 코어 수를 사용하십시오.

이 대답은 리눅스 및 BSD에 대한 구현만 제공한다.

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

.net에서도 WMI를 사용할 수 있지만, wmi 서비스 실행 등에 의존하게 된다.때로는 로컬에서 작동하지만 동일한 코드가 서버에서 실행될 때 실패하기도 한다.네임스페이스 문제인 것 같은데, 네임스페이스의 가치를 읽는 "이름"과 관련된 문제인 것 같아.

참조URL: https://stackoverflow.com/questions/150355/programmatically-find-the-number-of-cores-on-a-machine

반응형