스레드 스케줄링과 멀티코어
운영체제가 여러 작업을 효율적으로 처리할 수 있도록 지원하기 위해, 스레드의 실행 순서를 결정하는 작업을 스레드 스케줄링이라고 부른다. 특히 멀티코어 환경에서 스레드 스케줄링은 더욱 중요하다.
경쟁 범위: PCS와 SCS
스레드 스케줄링의 개념을 제대로 이해하려면, 먼저 경쟁 범위(contention scope)를 이해해야 한다. 이는 CPU의 실행 권한을 얻기 위한 경쟁이 벌어지는 범위를 뜻한다.
PCS(Process-Contention Scope) 이는 같은 프로세스 내부의 사용자 수준 스레드 간 경쟁이다. PCS는 스레드 라이브러리가 직접 관리하며, 가장 우선순위가 높은 사용자 스레드가 먼저 실행된다.
SCS(System-Contention Scope) 시스템 전역에서 모든 스레드가 경쟁하는 방식으로, 운영체제가 직접 관리한다. 커널 스레드를 직접 물리적 CPU 코어에 배치한다. Windows와 Linux는 보통 SCS만을 사용한다.
Pthreads에서는 다음 두 가지로 이를 명시적으로 지정할 수 있다.
PTHREAD_SCOPE_PROCESS
(PCS)PTHREAD_SCOPE_SYSTEM
(SCS)
다중 처리기 스케줄링
멀티코어 CPU의 등장으로, 운영체제는 여러 코어 간에 스레드를 효과적으로 배분해야 하는 과제를 안게 되었다. 멀티코어 환경에서는 다음과 같은 주요 스케줄링 이슈가 발생한다.
부하 균등화
부하 균등화(Load Balancing)는 멀티코어 시스템에서 매우 중요하다. 프로세서 간 작업 부하를 균등하게 나누지 않으면, 일부 코어는 유휴 상태가 되고, 다른 코어는 과부하 상태가 된다.
일반적으로 아래 두 가지의 부하 균등화를 위한 방법이 있다. 이 두 방법은 동시에 사용될 수도 있다.
- Push Migration: 과부하인 프로세서에서 덜 바쁜 프로세서로 스레드를 이동한다.
- Pull Migration: 한가한 프로세서가 바쁜 프로세서에서 스레드를 가져온다.
처리기 선호도
스레드는 특정 프로세서에서 실행되던 메모리 데이터를 캐시에 저장한다. 만약 스레드가 다른 프로세서로 이동하면 캐시 데이터를 다시 불러오는 작업이 필요해 성능이 저하된다. 이를 방지하기 위해 운영체제는 가능한 한 스레드를 동일 프로세서에서 실행시키려 하는데, 이것을 처리기 선호도(Processor Affinity) 라고 한다.
처리기 선호도는 soft와 hard로 나뉜다.
- 약한 선호도(soft affinity): 같은 프로세서에서 수행되도록 노력하지만, 이주도 허용된다.
- 강한 선호도(hard affinity): 특정 프로세서에서만 실행되도록 제한한다.
NUMA와 멀티코어
최근 멀티코어 시스템은 NUMA(non-uniform memory access) 구조를 활용한다. 이는 각 CPU가 가까운 메모리에 빠르게 접근할 수 있지만, 멀리 떨어진 메모리는 느리게 접근할 수 있다는 구조다. 따라서, 스케줄러가 NUMA를 잘 활용하면 프로세서와 메모리 간 접근 속도를 최적화할 수 있다.
하지만 부하 균등화와 처리기 선호도는 종종 상충 관계를 갖는다. 즉, 선호도를 유지하면 캐시 효율은 좋아지지만 부하 균등화가 힘들어지고, 반대로 부하를 균등하게 맞추려 하면 캐시 효율이 떨어지는 문제가 생긴다.
최신 운영체제의 멀티코어 스케줄링 사례
Linux의 CFS 스케줄러
Linux는 CFS(Completely Fair Scheduler)를 사용하여 스레드 간 CPU 시간 분배를 공정하게 유지한다. CFS는 스레드마다 가상 실행 시간(vruntime)을 관리하여 가장 작은 vruntime을 가진 스레드를 우선 실행한다. 또한 NUMA를 고려하여 메모리 접근 시간과 캐시 효율을 균형 있게 맞춘다.
Windows의 우선순위 스케줄링
Windows는 우선순위 기반의 선점형 스케줄링을 사용한다. 32단계의 우선순위를 가지며, 스레드는 우선순위에 따라 실행 순서가 정해진다. 또한 멀티코어 환경에서는 각 스레드가 가능한 한 동일 코어에서 실행되도록 노력하며, SMT(동시 멀티스레딩)를 지원하는 하드웨어에서는 같은 물리적 코어 내 하드웨어 스레드를 활용하여 성능을 최적화한다.