최신 서버는 CPU 코어 수가 수십 개에서 수백 개에 이르며, 메모리 용량도 수백 GB에서 수 TB까지 확장됩니다. 이러한 대규모 시스템에서는 모든 CPU가 하나의 메모리에 동일한 속도로 접근하는 구조보다 CPU와 메모리를 여러 개의 노드(Node)로 나누는 방식이 훨씬 효율적입니다.
이러한 구조를 NUMA(Non-Uniform Memory Access) 라고 합니다.
NUMA는 데이터베이스, 가상화, Kubernetes, AI 서버, HPC(고성능 컴퓨팅) 환경에서 매우 중요한 개념이며, NUMA 구조를 이해하면 메모리 접근 지연을 줄이고 시스템 성능을 크게 향상시킬 수 있습니다.
이번 글에서는 NUMA의 개념과 구조, 동작 방식, 실무에서 확인하는 방법까지 자세히 알아보겠습니다.
NUMA란?
NUMA는 CPU마다 가까운 메모리(Local Memory)를 가지고 있으며, 다른 CPU의 메모리(Remote Memory)에도 접근할 수 있는 메모리 구조입니다.
즉, 모든 메모리의 접근 속도가 동일하지 않기 때문에 Non-Uniform(비균일) 이라는 이름이 붙었습니다.
간단한 구조는 다음과 같습니다.
NUMA Node 0
CPU0 ─── Local Memory0
│
└─────────────┐
│
NUMA Node 1 │
CPU1 ─── Local Memory1
▲
│
Remote Memory Access
자신의 Local Memory는 매우 빠르게 접근할 수 있지만, 다른 Node의 메모리에 접근하면 지연 시간이 증가합니다.
UMA와 NUMA의 차이
과거 시스템은 UMA(Uniform Memory Access) 구조를 사용했습니다.
| 항목 | UMA | NUMA |
|---|---|---|
| 메모리 접근 속도 | 동일 | 노드마다 다름 |
| 확장성 | 낮음 | 높음 |
| CPU 수 | 적음 | 많음 |
| 대형 서버 적합성 | 낮음 | 매우 높음 |
현재 대부분의 서버용 CPU는 NUMA 구조를 사용합니다.
NUMA Node란?
NUMA에서는 CPU와 메모리가 하나의 묶음(Node)으로 구성됩니다.
예를 들어 2소켓 서버는 다음과 같이 구성될 수 있습니다.
NUMA Node 0
CPU 0
Memory 0
↓
NUMA Node 1
CPU 1
Memory 1
각 CPU는 자신의 메모리를 우선적으로 사용합니다.
Local Memory와 Remote Memory
NUMA의 핵심은 메모리 접근 거리입니다.
Local Memory
현재 CPU와 같은 Node에 있는 메모리입니다.
- 접근 속도 빠름
- 지연 시간 낮음
- 대역폭 높음
Remote Memory
다른 NUMA Node의 메모리입니다.
- 접근 속도 느림
- 지연 시간 증가
- CPU 간 인터커넥트 사용
실무에서는 Local Memory 사용 비율을 높이는 것이 중요합니다.
NUMA가 필요한 이유
CPU 수가 많아질수록 하나의 메모리 컨트롤러만 사용하는 구조는 병목이 발생합니다.
NUMA는 메모리 컨트롤러를 CPU마다 분산하여 다음과 같은 장점을 제공합니다.
- 메모리 병목 감소
- CPU 확장성 향상
- 높은 메모리 대역폭
- 멀티소켓 서버 지원
따라서 대규모 서버 환경에서 필수적인 구조입니다.
현재 NUMA 구조 확인
현재 시스템의 NUMA 구성을 확인하려면 다음 명령을 사용합니다.
lscpu
예시
NUMA node(s): 2
NUMA node0 CPU(s): 0-15
NUMA node1 CPU(s): 16-31
현재 서버에 NUMA Node가 몇 개인지 확인할 수 있습니다.
numactl 사용
보다 자세한 정보는 numactl 명령으로 확인합니다.
numactl --hardware
예시
available: 2 nodes
node 0 cpus: 0-15
node 1 cpus: 16-31
node 0 size: 128 GB
node 1 size: 128 GB
각 Node의 CPU와 메모리 크기를 확인할 수 있습니다.
NUMA 정책
Linux에서는 메모리 할당 정책을 지정할 수 있습니다.
대표적인 정책은 다음과 같습니다.
- Default
- Preferred
- Bind
- Interleave
예를 들어 특정 Node의 메모리만 사용하도록 실행할 수 있습니다.
numactl --cpunodebind=0 --membind=0 ./app
이 명령은 CPU와 메모리를 모두 NUMA Node 0에 고정합니다.
NUMA 성능 확인
NUMA 상태를 확인하는 명령입니다.
메모리 정보
numastat
NUMA 하드웨어
numactl --hardware
CPU 정보
lscpu
메모리 사용량
free -h
실무 사례
예를 들어 데이터베이스 서버에서 응답 속도가 느려졌다면 NUMA도 원인일 수 있습니다.
다음 순서로 확인합니다.
lscpu로 NUMA Node 개수 확인numactl --hardware로 메모리 구성 확인numastat으로 Remote Memory 사용량 확인- 데이터베이스 프로세스의 CPU Affinity 확인
- 필요 시
numactl로 CPU와 메모리를 동일한 Node에 고정
이 과정을 통해 불필요한 Remote Memory 접근을 줄여 성능을 향상시킬 수 있습니다.
실무에서 자주 사용하는 명령어
NUMA 정보 확인
lscpu
하드웨어 정보
numactl --hardware
NUMA 통계
numastat
메모리 사용량
free -h
CPU 정보
cat /proc/cpuinfo
프로세스 NUMA 정책 확인
numactl --show
자주 묻는 질문
모든 Linux 서버가 NUMA를 사용하나요?
아닙니다. 단일 CPU나 소규모 시스템은 UMA 구조를 사용하는 경우가 많습니다. NUMA는 주로 멀티소켓 서버나 고성능 서버에서 사용됩니다.
NUMA가 항상 성능을 향상시키나요?
NUMA 자체는 확장성을 높여주지만, Remote Memory 접근이 많아지면 오히려 성능이 저하될 수 있습니다. 따라서 CPU와 메모리를 같은 Node에 배치하는 것이 중요합니다.
NUMA를 비활성화할 수 있나요?
일부 시스템에서는 BIOS나 커널 부팅 옵션을 통해 NUMA를 비활성화할 수 있지만, 대규모 서버에서는 일반적으로 권장되지 않습니다.
마무리
NUMA는 현대 Linux 서버에서 메모리 접근 성능을 최적화하기 위한 핵심 구조입니다. CPU마다 Local Memory를 우선 사용하고, 필요할 때만 Remote Memory에 접근함으로써 높은 확장성과 성능을 제공합니다. lscpu, numactl, numastat 명령을 활용하면 NUMA 구성을 쉽게 확인하고, 데이터베이스나 가상화 환경에서 발생하는 메모리 병목을 효과적으로 분석할 수 있습니다.