핵심 인사이트 (3줄 요약)
- 본질: NUMA-인식 스레드 스케줄링 (NUMA Thread Scheduling)은 프로세스와 스레드의 생성·실행·협력에서 핵심 흐름을 결정하는 개념으로, 시스템이 무엇을 먼저 관리하고 어떤 순서로 제어할지를 분명하게 만든다.
- 가치: 이 개념을 이해하면 자원 효율, 응답 시간, 안정성 사이의 균형을 더 정확하게 설명할 수 있고, 실시간 프로세스 (Real-time Process)로 이어지는 이유도 자연스럽게 파악된다.
- 판단 포인트: CPU 친화성 (CPU Affinity)과의 관계를 함께 봐야 NUMA-인식 스레드 스케줄링 (NUMA Thread Scheduling)을 단순 정의가 아니라 실제 설계·운영 판단 기준으로 사용할 수 있다.
Ⅰ. 개요 및 필요성
1. NUMA (Non-Uniform Memory Access)
NUMA는 다중 프로세서 시스템에서 각 CPU가 로컬 메모리를 가지며, 다른 CPU의 메모리(원격 메모리)에 접근할 때 더 큰 지연이 발생하는 아키텍처다. 대규모 서버 시스템(4소켓 이상)의 표준 구조다.
비유: 각 방에 자기 책상(로컬 메모리)이 있지만, 옆방 책상(원격 메모리)에서 물건을 가져올 때는 더 오래 걸리는 기숙사와 같다.
┌──────────── NUMA 아키텍처 개요 ────────────┐
│ │
│ NUMA Node 0 NUMA Node 1 │
│ ┌──────────────┐ ┌──────────────┐ │
│ │ Local Mem 0 │ │ Local Mem 1 │ │
│ │ (16GB) │ │ (16GB) │ │
│ └──────┬───────┘ └──────┬───────┘ │
│ │ │ │
│ ┌──────┴───────┐ ┌──────┴───────┐ │
│ │ P0 P1 P2 P3│ │ P4 P5 P6 P7│ │
│ └──────────────┘ └──────────────┘ │
│ │ │ │
│ └──Interconnect──┘ │
│ (QPI/UPI/HyperTransport) │
│ │
│ 로컬 접근: ~80ns │
│ 원격 접근: ~150~200ns (2~3배 느림) │
│ │
└───────────────────────────────────────────────┘
2. 로컬 메모리 vs 원격 메모리
| 구분 | 설명 | 지연 시간 | 대역폭 |
|---|---|---|---|
| 로컬 메모리 | 동일 NUMA 노드의 메모리 | 낮음 (~80ns) | 높음 |
| 원격 메모리 | 다른 NUMA 노드의 메모리 | 높음 (~150ns+) | 낮음 |
┌────────── 로컬 vs 원격 메모리 접근 ──────────┐
│ │
│ CPU(P0)의 메모리 요청: │
│ │
│ [로컬 접근] │
│ P0 ──> Local Mem 0: 80ns ──> 데이터 획득 │
│ ★ 빠름, 대역폭 충분 │
│ │
│ [원격 접근] │
│ P0 ──> Interconnect ──> Remote Mem 1 │
│ 150~200ns + 대역폭 경합 ──> 데이터 │
│ ▲ 느림, 인터커넥트 병목 가능 │
│ │
└────────────────────────────────────────────────┘
- 📢 섹션 요약 비유: 복잡한 창고에서 필요한 물건을 찾기 위해 먼저 구역과 표지판을 세우는 것과 같다.
Ⅱ. 아키텍처 및 핵심 원리
1. 스케줄링 원칙
NUMA 인식 스케줄링의 핵심은 스레드를 해당 스레드가 사용하는 메모리와 동일한 NUMA 노드에서 실행하도록 배치하는 것이다.
┌────────── NUMA 인식 스케줄링 최적화 ─────────┐
│ │
│ 최적 배치 (NUMA-aware): │
│ Node 0: Thread-A + Mem-A (동일 노드) │
│ Node 1: Thread-B + Mem-B (동일 노드) │
│ │
│ ┌──────────┐ ┌──────────┐ │
│ │ Th-A+Mem │ │ Th-B+Mem │ │
│ │ (Node 0) │ │ (Node 1) │ │
│ └──────────┘ └──────────┘ │
│ │
│ 비최적 배치 (NUMA-unaware): │
│ Node 0: Thread-A 실행 │
│ Node 0의 Thread-A가 Node 1의 Mem-B 접근 │
│ -> 인터커넥트를 통한 원격 접근 발생 │
│ │
└───────────────────────────────────────────────┘
2. 메모리 정책 설정
| 정책 | API/명령어 | 설명 |
|---|---|---|
| 기본 (Local) | set_mempolicy(MPOL_DEFAULT) | 로컬 노드 메모리 우선 할당 |
| 바인드 (Bind) | set_mempolicy(MPOL_BIND) | 지정 노드에서만 할당 |
| 선호 (Preferred) | set_mempolicy(MPOL_PREFERRED) | 지정 노드 선호, 부족 시 타 노드 |
| 인터리브 (Interleave) | set_mempolicy(MPOL_INTERLEAVE) | 여러 노드에 번갈아 할당 |
| mbind | mbind() | 특정 메모리 영역에 정책 적용 |
#include <numaif.h>
#include <numa.h>
// 전체 프로세스 메모리를 Node 0에 바인딩
unsigned long nodemask = 1UL << 0; // Node 0
set_mempolicy(MPOL_BIND, &nodemask, MAXNODES);
// 특정 메모리 영역을 Node 0, 1에 인터리브
unsigned long nodemask2 = (1UL << 0) | (1UL << 1);
mbind(ptr, size, MPOL_INTERLEAVE, &nodemask2, MAXNODES, 0);
- 📢 섹션 요약 비유: 공장 컨베이어벨트가 어떤 순서로 부품을 받아 가공하고 내보내는지 설계도를 펼쳐 보는 것과 같다.
Ⅲ. 비교 및 연결
1. numactl 명령어
┌────────────── numactl 사용법 ──────────────┐
│ │
│ # 하드웨어 NUMA 정보 확인 │
│ numactl --hardware │
│ │
│ # 특정 노드에서 프로세스 실행 │
│ numactl --cpunodebind=0 --membind=0 ./app │
│ │
│ # 선호 노드 지정 │
│ numactl --preferred=0 ./app │
│ │
│ # 인터리브 정책 │
│ numactl --interleave=0,1 ./app │
│ │
│ # 현재 프로세스의 NUMA 정보 확인 │
│ numastat -p <PID> │
│ │
└───────────────────────────────────────────────┘
2. AutoNUMA 자동 균형
리눅스 커널의 AutoNUMA 기능은 자동으로 메모리 페이지를 자주 접근하는 노드로 마이그레이션한다.
┌────────────── AutoNUMA 동작 원리 ──────────────┐
│ │
│ 1. 초기 상태: │
│ Thread-X (Node 0) ──> Mem-P (Node 1) 원격 │
│ │
│ 2. 커널이 원격 접근 빈도 모니터링 │
│ PFN (Page Frame Number) 당 접근 통계 수집 │
│ │
│ 3. 임계치 초과 시 자동 마이그레이션: │
│ Mem-P를 Node 1에서 Node 0으로 이동 │
│ Thread-X (Node 0) ──> Mem-P (Node 0) 로컬 │
│ │
│ 4. 설정: │
│ /proc/sys/kernel/numa_balancing = 1 (활성화) │
│ /proc/sys/kernel/numa_balancing_scan_period │
│ │
└───────────────────────────────────────────────────┘
비유: AutoNUMA는 도서관에서 자주 쓰는 책을 멀리 있는 서가에서 내 자리 옆으로 자동으로 옮겨주는 도서관 사서와 같다.
- 📢 섹션 요약 비유: 비슷해 보이는 공구를 나란히 놓고 언제 망치를 쓰고 언제 드라이버를 써야 하는지 구분하는 것과 같다.
Ⅳ. 실무 적용 및 기술사 판단
1. 메모리 집약적 워크로드의 영향
┌───────── 성능 비교: NUMA-aware vs Unaware ──────┐
│ │
│ 워크로드: 대규모 인메모리 데이터베이스 │
│ (256GB 메모리, 4 NUMA 노드, 64코어) │
│ │
│ ┌─────────────────────────────────────────┐ │
│ │ throughput (ops/sec) │ │
│ │ │ │
│ │ NUMA-aware ████████████████████ 100% │ │
│ │ NUMA-blind ████████ 55% │ │
│ │ AutoNUMA ████████████████ 85% │ │
│ │ │ │
│ └─────────────────────────────────────────┘ │
│ │
│ 원격 메모리 접근: 2~3배 지연 │
│ 대규모 시스템에서는 1.5~3배 성능 차이 │
│ │
└────────────────────────────────────────────────────┘
2. 성능 영향 요인
| 요인 | 영향 정도 | 설명 |
|---|---|---|
| 메모리 접근 패턴 | 매우 큼 | 순차적 vs 랜덤 접근 |
| 데이터 크기 | 큼 | L3 캐시를 초과하는 경우 영향 극대화 |
| 스레드 수 | 중간 | 노드당 스레드 밸런스 |
| 인터커넥트 대역폭 | 큼 | QPI/UPI 대역폭에 따라 원격 접근 비용 변동 |
- 📢 섹션 요약 비유: 운전자가 도로 상황에 따라 기어와 브레이크를 다르게 선택하는 것처럼 조건별 판단이 중요하다.
Ⅴ. 기대효과 및 결론
NUMA-인식 스레드 스케줄링
├── NUMA 아키텍처
│ ├── Non-Uniform Memory Access
│ ├── 다중 노드, 각 노드에 로컬 메모리
│ ├── 로컬 접근 (~80ns) vs 원격 접근 (~150ns+)
│ └── 인터커넥트 (QPI/UPI)로 노드 간 통신
├── NUMA 인식 스케줄링 기법
│ ├── 스레드와 메모리를 동일 노드에 배치
│ ├── first-touch 정책 (초기 접근 노드에 할당)
│ └── 페이지 마이그레이션 (동적 재배치)
├── 메모리 정책
│ ├── set_mempolicy() (프로세스 전체)
│ ├── mbind() (특정 메모리 영역)
│ ├── MPOL_BIND, MPOL_PREFERRED, MPOL_INTERLEAVE
│ └── numactl 명령행 도구
├── AutoNUMA 자동 균형
│ ├── 커널이 원격 접근 통계 자동 수집
│ ├── 빈번한 원격 페이지를 로컬로 마이그레이션
│ └── numa_balancing 커널 파라미터
├── 성능 영향
│ ├── 메모리 집약적 워크로드: 2~3배 차이
│ ├── 대규모 데이터베이스, HPC에 중요
│ └── 인터커넥트 대역폭이 병목
└── 최적화 전략
├── numactl로 수동 노드 바인딩
├── first-touch 초기화 패턴 사용
└── AutoNUMA 활성화 + 모니터링
| 약어 | Full Name |
|---|---|
| NUMA | Non-Uniform Memory Access |
| QPI | QuickPath Interconnect |
| UPI | Ultra Path Interconnect |
| HPC | High-Performance Computing |
| PFN | Page Frame Number |
| MPOL | Memory Policy |
컴퓨터가 아주 커져서 여러 그룹으로 나뉘면, 각 그룹마다 자기 메모리를 가집니다. 가까운 메모리를 쓰면 빠르지만 멀리 있는 메모리를 쓰면 느려요. 그래서 일꾼과 메모리를 같은 그룹에 배치하면 2~3배나 빨라집니다.
- 📢 섹션 요약 비유: 도구의 장점만 외우는 것이 아니라 어디까지 믿고 어디서 보완해야 하는지 기억하는 정리 노트와 같다.
📌 관련 개념 맵
| 개념 | 연결 포인트 |
|---|---|
| 컨텍스트 스위칭 최소화를 위한 스레드 고정 (Thread Affinity/Pinning) | 현재 개념으로 들어오기 전에 함께 이해하면 경계가 선명해지는 기반 개념이다. |
| CPU 친화성 (CPU Affinity) | 현재 개념이 등장하게 만든 직접적인 선행 흐름이다. |
| 실시간 프로세스 (Real-time Process) | 현재 개념이 구현·세분화될 때 바로 연결되는 후속 개념이다. |
| 스레드 안전 (Thread-safe) 함수 및 라이브러리 | 확장 학습이나 심화 비교로 이어지는 다음 단계의 키워드다. |
📈 관련 키워드 및 발전 흐름도
[CPU 친화성 (CPU Affinity)]
│
▼
[NUMA-인식 스레드 스케줄링 (NUMA Thread Scheduling)]
│
├──▶ [실시간 프로세스 (Real-time Process)]
└──▶ [스레드 안전 (Thread-safe) 함수 및 라이브러리]
이 흐름도는 선행 개념에서 현재 개념으로 넘어온 뒤, 구현 세분화와 후속 확장으로 이어지는 학습 순서를 압축해 보여준다.
👶 어린이를 위한 3줄 비유 설명
- NUMA-인식 스레드 스케줄링 (NUMA Thread Scheduling)은 컴퓨터가 여러 일을 나눠서 처리하고 서로 기다리게 하는 약속이에요.
- 먼저 CPU 친화성 (CPU Affinity)을 이해하면 NUMA-인식 스레드 스케줄링 (NUMA Thread Scheduling)이 왜 필요한지 더 쉽게 보여요.
- 그래서 NUMA-인식 스레드 스케줄링 (NUMA Thread Scheduling)을 잘 알면 나중에 실시간 프로세스 (Real-time Process)도 훨씬 쉽게 배울 수 있어요.