개요
컴퓨터 시스템에서 물리적 CPU 코어 수를 정확히 파악하는 것은 소프트웨어 개발, 시스템 최적화, 성능 벤치마킹에 중요한 요소이다. 이 글에서는 Windows와 Linux/POSIX 시스템에서 물리적 CPU 코어 수를 확인하는 C 코드 구현 방법을 상세히 분석한다.
설명
물리적 CPU 코어 수는 컴퓨팅 작업의 병렬 처리 능력을 결정하는 주요 요소로, 소프트웨어 개발자가 멀티스레딩 구현과 리소스 할당을 최적화할 때 필수적인 정보이다. 하이퍼스레딩 기술로 인해 논리적 프로세서 수와 물리적 코어 수는 다를 수 있어, 정확한 물리적 코어 수 확인 방법이 필요하다. 운영체제별로 상이한 API를 통해 이 정보에 접근할 수 있으며, 크로스 플랫폼 애플리케이션 개발 시 이러한 차이를 고려해야 한다.
특징
Windows 시스템에서의 구현
Windows 시스템에서는 Windows API의 GetLogicalProcessorInformation 함수를 활용하여 물리적 CPU 코어 수를 확인한다. 이 접근법의 주요 특징은 다음과 같다:
- Windows.h 헤더 파일을 포함하여 필요한 API에 접근
- GetLogicalProcessorInformation 함수로 프로세서 정보 수집
- RelationProcessorCore 관계를 가진 정보만 필터링하여 물리적 코어 수 계산
- 비트 연산을 통해 프로세서 마스크 분석
Linux/POSIX 시스템에서의 구현
Linux 및 기타 POSIX 시스템에서는 sysconf 함수를 사용하여 간단하게 프로세서 정보를 획득한다:
- unistd.h 헤더 파일을 포함
- sysconf(_SC_NPROCESSORS_CONF) 함수 호출로 구성된 프로세서 수 확인
- Windows 구현에 비해 상대적으로 단순한 코드 구조
크로스 플랫폼 지원
제시된 코드는 전처리기 지시문(#if defined(_WIN32))을 사용하여 컴파일 시점에 적절한 구현을 선택함으로써 크로스 플랫폼 지원을 제공한다. 이는 단일 코드베이스로 여러 운영체제를 지원할 수 있게 한다.
예제
아래 코드는 Windows와 Linux/POSIX 시스템에서 물리적 CPU 코어 수를 확인하는 완전한 구현 예시이다:
#include
#if defined(_WIN32)
#include
#else
#include
#endif
#if defined(_WIN32)
static int getPhysicalCpuCores()
{
PSYSTEM_LOGICAL_PROCESSOR_INFORMATION buffer = NULL;
DWORD bufferSize = 0;
DWORD byteOffset = 0;
DWORD logicalProcessorCount = 0;
DWORD physicalProcessorCount = 0;
// 필요한 버퍼 크기 얻기
GetLogicalProcessorInformation(NULL, &bufferSize);
buffer = (PSYSTEM_LOGICAL_PROCESSOR_INFORMATION)malloc(bufferSize);
if (buffer == NULL)
{
perror("Memory allocation error");
return -1;
}
// 프로세서 정보 얻기
if (!GetLogicalProcessorInformation(buffer, &bufferSize))
{
perror("GetLogicalProcessorInformation error");
free(buffer);
return -1;
}
while (byteOffset < bufferSize)
{
if (buffer[byteOffset / sizeof(SYSTEM_LOGICAL_PROCESSOR_INFORMATION)].Relationship == RelationProcessorCore)
{
logicalProcessorCount += CountSetBits(buffer[byteOffset / sizeof(SYSTEM_LOGICAL_PROCESSOR_INFORMATION)].ProcessorMask);
physicalProcessorCount++;
}
byteOffset += sizeof(SYSTEM_LOGICAL_PROCESSOR_INFORMATION);
}
free(buffer);
return physicalProcessorCount;
}
static DWORD CountSetBits(ULONG_PTR bitMask) {
DWORD LSHIFT = sizeof(ULONG_PTR) * 8 - 1;
DWORD bitSetCount = 0;
ULONG_PTR bitTest = (ULONG_PTR)1 << LSHIFT;
DWORD i;
for (i = 0; i <= LSHIFT; ++i) {
bitSetCount += ((bitMask & bitTest) ? 1 : 0);
bitTest /= 2;
}
return bitSetCount;
}
#endif
int get_number_of_cpu_core(void)
{
int number_of_cpu_core = 0;
#if defined(_WIN32)
number_of_cpu_core = getPhysicalCpuCores();
#else
/*
Specified <https://man7.org/linux/man-pages/man3/sysconf.3.html>
- _SC_NPROCESSORS_CONF
The number of processors configured. See also
get_nprocs_conf(3).
*/
number_of_cpu_core = (int)sysconf(_SC_NPROCESSORS_CONF);
#endif
return number_of_cpu_core;
}
int main(void)
{
printf("Number of CPU core : %d", get_number_of_cpu_core());
return 0;
}
Windows 구현 상세 분석
Windows 시스템에서의 물리적 CPU 코어 수 계산 과정은 다음과 같다:
- GetLogicalProcessorInformation 함수를 먼저 NULL 포인터로 호출하여 필요한 버퍼 크기를 확인한다.
- 필요한 크기만큼 메모리를 할당한다.
- 할당된 버퍼로 다시 GetLogicalProcessorInformation 함수를 호출하여 프로세서 정보를 가져온다.
- 버퍼를 순회하며 Relationship 멤버가 RelationProcessorCore인 항목을 찾아 물리적 코어 수를 계산한다.
- ProcessorMask에 설정된 비트 수를 통해 논리적 프로세서 수도 계산할 수 있다.
- 메모리를 해제하고 물리적 코어 수를 반환한다.
Linux/POSIX 구현 상세 분석
Linux 및 POSIX 시스템에서는 sysconf 함수를 사용하여 간단하게 구성된 프로세서 수를 얻는다:
- _SC_NPROCESSORS_CONF 상수를 인자로 sysconf 함수를 호출한다.
- 반환된 값을 정수형으로 변환하여 사용한다.
실행 결과는 간단하게 물리적 CPU 코어 수를 출력한다:
Number of CPU core : 4
결론
물리적 CPU 코어 수 확인은 운영체제에 따라 상이한 방법을 요구하지만, 전처리기 지시문을 활용하여 크로스 플랫폼 코드로 구현할 수 있다. Windows 시스템에서는 보다 복잡한 API 호출과 처리 과정이 필요한 반면, Linux/POSIX 시스템에서는 상대적으로 간단한 함수 호출로 정보를 얻을 수 있다. 이러한 시스템 정보 확인 방법은 성능 최적화, 리소스 관리, 병렬 처리 구현 등 다양한 소프트웨어 개발 상황에서 활용될 수 있다.
참고문헌
- Windows API - GetLogicalProcessorInformation: https://docs.microsoft.com/en-us/windows/win32/api/sysinfoapi/nf-sysinfoapi-getlogicalprocessorinformation
- Linux Man Pages - sysconf: https://man7.org/linux/man-pages/man3/sysconf.3.html
- Understanding CPU Core Counts: https://www.intel.com/content/www/us/en/developer/articles/guide/processor-specific-performance-analysis-papers.html
'Programming > C' 카테고리의 다른 글
C언어로 Windows 시스템 레지스트리에 값 저장하기 (0) | 2025.04.17 |
---|---|
C언어에서 Linux/Windows 시스템의 hostname 확인 방법 분석 (0) | 2025.04.16 |
C언어 문자열 연결 함수: strcat, strncat의 이해와 활용 (2) | 2025.04.14 |
C/C++에서의 콤마(,) 연산자의 의미 (0) | 2025.04.11 |
printf의 출력 방식: %.*s 형식 지정자 활용하기 (0) | 2025.04.10 |