22. NUMA 아키텍처와 메모리 지역성: 원격 접근 비용·first-touch·스레드/메모리 어피니티
난이도 상내 답안
모범답안
난이도: 상
1) NUMA 란
- UMA(대칭 다중처리)는 모든 코어가 하나의 메모리 컨트롤러/버스를 공유해 어떤 주소든 접근 비용이 같다. 코어·소켓이 늘면 그 공유 버스가 병목이 된다.
- NUMA 는 메모리를 여러 노드(node) 로 나눠 각 노드를 특정 소켓(코어 묶음)에 붙인다. 코어는 자기 노드의 로컬 메모리를 빠르게, 다른 노드의 원격 메모리를 인터커넥트를 거쳐 느리게 접근한다.
- NUMA distance/비용: 노드 쌍마다 상대적 접근 비용이 정의된다(로컬=기준, 원격은 그 배수). 소켓이 많을수록 메모리 대역폭을 노드별로 분산해 확장성을 얻기 위해 이 구조가 필요하다.
2) 원격 접근 비용
- 원격 노드 메모리 접근은 로컬 대비 지연이 크고(대략 1.5~2배+) 대역폭이 낮다. 접근이 인터커넥트 (Intel UPI/QPI, AMD Infinity Fabric)를 건너야 하기 때문이다.
- 캐시 일관성 트래픽: 여러 노드가 같은 캐시 라인을 공유하면 무효화/소유권 이전 메시지가 인터커넥트로 오가며, 원격 접근과 일관성 트래픽이 겹쳐 병목이 심해진다. 인터커넥트 대역폭이 전체 성능의 상한이 될 수 있다.
3) first-touch 정책
- 리눅스 기본은 first-touch:
malloc/new는 가상 주소만 예약하고 물리 페이지는 처음 그 페이지를 건드리는(쓰는) 순간 할당된다. 이때 페이지는 접근한 스레드가 도는 노드의 로컬 메모리에서 잡힌다. - 그래서 "누가 할당했나" 가 아니라 "누가 처음 만졌나" 가 페이지의 노드를 결정한다.
- 함정: 초기화 루프를 한 스레드(예: 메인 스레드)가 전부 돌면 큰 버퍼가 통째로 한 노드에 배치된다. 이후 여러 노드의 워커가 그 데이터를 나눠 쓰면 대부분이 원격 접근이 되어 대역폭이 한 노드에 몰리고 성능이 급락한다. 해결: 각 워커가 자신이 쓸 영역을 자기 스레드에서 초기화(병렬 first-touch)해 데이터가 사용할 노드에 배치되게 한다.
4) 스레드·메모리 어피니티
- 스레드를 특정 노드/코어에 고정(pinning/affinity) 하고 그 스레드가 쓸 메모리를 같은 노드에 배치하면, 접근이 로컬로 유지되어 지연↓·대역폭↑ 이고 인터커넥트 트래픽·일관성 비용이 준다. 캐시 지역성도 좋아진다.
- 게임 서버 설계: 워커 스레드와 그 워커가 담당하는 존/샤드 데이터를 노드별로 묶으면(존 A→노드 0, 존 B→노드 1) 대부분의 접근이 로컬이 된다.
- 위험: (1) 부하 불균형 — 특정 노드의 존이 붐비면 그 노드만 포화되고 다른 노드는 논다. (2) 노드 간 이동 — 플레이어가 존을 넘나들면 데이터가 원격이 되거나 재배치 비용이 든다. (3) OS 스케줄러가 스레드를 다른 노드로 옮기면(마이그레이션) 지역성이 깨진다 → 명시적 pinning 필요. 균형을 위해 노드 간 작업 재분배(work-stealing)와 지역성 사이의 트레이드오프를 조율해야 한다.
5) 실무 함정·도구
- 증상: 코어를 늘려도 성능이 안 오르거나 떨어짐, 특정 노드 메모리 대역폭 포화, 원격 접근·인터커넥트 사용률 급증. 프로파일러에서 원격 메모리 접근/스톨 비중이 높게 나온다.
- false sharing 과의 차이: false sharing 은 같은 캐시 라인을 여러 코어가 갱신해 라인이 튕겨 다니는 문제(캐시 라인 정렬/패딩으로 해결). NUMA 원격 접근은 데이터가 다른 노드에 있어 느린 문제(배치/어피니티로 해결)다. 둘 다 인터커넥트 트래픽을 늘리지만 원인·처방이 다르다.
- 제어 수단:
numactl --cpunodebind=0 --membind=0 ./server: 프로세스의 CPU·메모리를 특정 노드로 묶어 실행.numastat,/proc/<pid>/numa_maps,numactl -H: 노드별 할당·히트/미스, 토폴로지 진단.- 프로그램 차원:
mbind()/set_mempolicy()/sched_setaffinity(),libnuma(numa_alloc_onnode), 병렬 first-touch 초기화. - 대형 페이지와 상호작용: 대형 페이지는 TLB 커버리지를 늘리지만, 큰 페이지는 노드에 크게 뭉쳐 잡히므로 NUMA 배치를 더 신경 써야 한다(잘못 배치하면 큰 덩어리가 통째로 원격이 됨).
면접 포인트
- 로컬 vs 원격 접근 비용과 인터커넥트/캐시 일관성의 관계.
- first-touch 의 의미와 "병렬 초기화로 데이터를 사용할 노드에 배치" 하는 이유.
- 스레드/메모리 어피니티의 이득과 부하 불균형·노드 간 이동이라는 위험, 그리고 NUMA≠false sharing 구분.