Introduction

UMA에서 살펴본 것처럼, 공유 버스 기반의 균일 메모리 접근 아키텍처는 프로세서 수가 8~16개를 넘어서면 버스 포화로 확장성의 벽에 부딪힙니다. 이 한계를 돌파하기 위해 등장한 것이 NUMA(Non-Unified Memory Access, 불균일 메모리 접근)입니다. NUMA는 프로세서와 메모리를 노드 단위로 묶어, 같은 노드 안의 메모리 접근(로컬 접근)은 빠르고 다른 노드의 메모리 접근(원격 접근)은 느린 비대칭 구조를 허용합니다. 이 글에서는 NUMA의 구조, 인터커넥트 기술, 리눅스 커널의 NUMA 지원, 그리고 실전 최적화 전략까지 포괄적으로 다룹니다.

NUMA란 무엇인가

NUMA(Non-Unified Memory Access)는 멀티프로세서 시스템에서 메모리 접근 지연이 프로세서와 메모리의 물리적 위치 관계에 따라 달라지는 메모리 아키텍처를 말한다. UMA와 달리, 어떤 프로세서가 어떤 메모리에 접근하느냐에 따라 지연 시간이 다르다.

  pi,pjP,    aA:Taccess(pi,a)Taccess(pj,a)\exists\; p_i, p_j \in P,\;\exists\; a \in A:\quad T_{\text{access}}(p_i, a) \neq T_{\text{access}}(p_j, a)

이 불균일성은 의도적인 설계 결정이다. 모든 프로세서가 하나의 버스를 공유하는 대신, 프로세서와 메모리를 노드(node)라는 단위로 묶고 노드 내부에서는 빠른 로컬 접근을, 노드 간에는 인터커넥트를 통한 원격 접근을 제공한다. 대역폭 병목을 분산시키는 대가로 접근 지연의 균일성을 포기하는 트레이드오프다.

하드웨어 구조

노드의 구성

NUMA 시스템의 기본 단위는 노드다. 각 노드는 하나 이상의 프로세서(소켓)와 해당 프로세서에 물리적으로 가까운 로컬 메모리로 구성된다. 노드 내부의 프로세서는 로컬 메모리에 직접 연결된 메모리 컨트롤러를 통해 접근하므로, 추가 홉(hop) 없이 낮은 지연으로 데이터를 읽고 쓸 수 있다.

그림 1. 4노드 NUMA 시스템의 구조. 실선은 로컬 접근, 점선은 인터커넥트를 경유하는 원격 접근을 나타낸다.

로컬 접근과 원격 접근

NUMA에서 메모리 접근은 두 가지로 나뉜다.

로컬 접근local access

프로세서가 자신이 속한 노드의 메모리에 접근하는 경우. 프로세서 내장 메모리 컨트롤러를 통해 직접 DRAM에 도달하므로 지연이 짧다.

원격 접근remote access

프로세서가 다른 노드의 메모리에 접근하는 경우. 인터커넥트를 거쳐 원격 노드의 메모리 컨트롤러에 요청을 전달해야 하므로 추가 지연이 발생한다.

로컬 접근과 원격 접근의 지연 비율을 NUMA 비율(NUMA ratio) 또는 NUMA 팩터(NUMA factor)라 하며, 이 값이 클수록 데이터 배치가 성능에 미치는 영향이 커진다.

NUMA Ratio=TremoteTlocal\text{NUMA Ratio} = \frac{T_{\text{remote}}}{T_{\text{local}}}

현대 서버에서 이 비율은 대략 1.2~2.0 범위에 있다. 예를 들어 로컬 접근이 80ns, 원격 접근이 130ns라면 NUMA 비율은 약 1.6이다. 2홉 이상을 거쳐야 하는 대규모 시스템에서는 이 비율이 더 커질 수 있다.

접근 유형대략적 지연경로
로컬 접근약 70~100nsCPU → 로컬 메모리 컨트롤러 → DRAM
원격 접근 (1홉)약 120~180nsCPU → 인터커넥트 → 원격 메모리 컨트롤러 → DRAM
원격 접근 (2홉)약 180~300nsCPU → 인터커넥트 → 중간 노드 → 인터커넥트 → 원격 DRAM

인터커넥트 기술

UMA의 공유 버스와 달리, NUMA 시스템은 노드 간에 포인트-투-포인트(point-to-point) 인터커넥트를 사용한다. 각 노드가 전용 링크로 직접 연결되므로, 한 노드 쌍의 통신이 다른 노드 쌍의 대역폭을 소비하지 않는다. 이것이 NUMA가 UMA의 버스 병목을 해소하는 핵심 메커니즘이다.

주요 인터커넥트 기술은 다음과 같다.

Intel QPI(QuickPath Interconnect)1

2008년 Intel Nehalem 아키텍처와 함께 도입된 포인트-투-포인트 인터커넥트. 기존의 공유 FSB(Front Side Bus)를 대체하면서 Intel 플랫폼이 본격적으로 NUMA 구조로 전환했다. 대역폭은 링크당 단방향 12.8~25.6GB/s.

Intel UPI(Ultra Path Interconnect)2

QPI의 후속으로, Skylake-SP(2017) 이후 서버 프로세서에 사용된다. 링크당 단방향 최대 20.8GT/s(약 41.6GB/s), 지연이 QPI 대비 개선되었다.

AMD Infinity Fabric3

AMD의 Zen 아키텍처(2017~) 이후 모든 Ryzen/EPYC 프로세서에 사용되는 인터커넥트. 특히 EPYC 서버 프로세서에서는 다이 내부의 CCD(Core Complex Die) 간 연결과 소켓 간 연결 모두를 Infinity Fabric이 담당하며, 다이 내부에서도 NUMA 토폴로지4가 발생할 수 있다.

캐시 일관성: 디렉터리 프로토콜

UMA에서 사용하던 스누핑 프로토콜은 모든 트랜잭션을 공유 버스에 브로드캐스트하는 방식이므로, 포인트-투-포인트 인터커넥트로 연결된 NUMA 시스템에는 적합하지 않다. NUMA에서는 디렉터리 기반(directory-based) 캐시 일관성 프로토콜을 사용한다.

디렉터리 프로토콜의 핵심 아이디어는 각 메모리 블록에 대해 어떤 캐시가 해당 블록의 사본을 보유하고 있는지를 기록하는 디렉터리를 유지하는 것이다. 캐시 미스나 쓰기가 발생하면, 브로드캐스트 대신 디렉터리를 참조하여 관련된 캐시에만 무효화 또는 갱신 메시지를 보낸다.

그림 2. 디렉터리 기반 캐시 일관성 프로토콜의 쓰기 동작 흐름.

이 방식은 스누핑에 비해 일관성 트래픽을 크게 줄인다. 스누핑은 O(N)O(N)개의 노드 모두에 브로드캐스트하지만, 디렉터리 프로토콜은 실제 사본을 보유한 노드에만 메시지를 전송하므로 트래픽이 사본 수에 비례한다. 이 차이가 NUMA의 확장성을 가능하게 하는 근본 요인이다.

리눅스의 NUMA 지원

리눅스 커널은 NUMA 토폴로지를 인식하고, 메모리 할당과 프로세스 배치를 NUMA에 맞추어 최적화하는 다양한 메커니즘을 제공한다.

NUMA 토폴로지 확인

시스템의 NUMA 구조는 커널이 부팅 시점에 ACPI SRAT(System Resource Affinity Table)5 테이블을 파싱하여 파악한다. 사용자 공간에서는 numactl --hardware 명령으로 노드 구성과 노드 간 거리를 확인할 수 있다.

available: 2 nodes (0-1)
node 0 cpus: 0 1 2 3 4 5 6 7
node 0 size: 32768 MB
node 1 cpus: 8 9 10 11 12 13 14 15
node 1 size: 32768 MB
node distances:
node   0   1
  0:  10  21
  1:  21  10

node distances 행렬은 SLIT(System Locality Information Table)에서 가져온 상대 거리 값으로, 로컬 접근이 10, 원격 접근이 21이면 NUMA 비율이 약 2.1임을 의미한다.

메모리 할당 정책

리눅스는 프로세스 단위로 NUMA 메모리 할당 정책을 설정할 수 있다. set_mempolicy() 시스템 호출이나 numactl 명령줄 도구를 통해 제어하며, 커널 v6.19 기준 include/uapi/linux/mempolicy.h에 정의된 정책은 다음과 같다.

MPOL_DEFAULT

프로세스를 실행하고 있는 프로세서가 속한 노드에서 우선 메모리를 할당받는다. 별도 설정이 없을 때의 기본 동작이며, 대부분의 워크로드에서 합리적인 선택이다.

MPOL_PREFERRED

선호 노드를 하나 설정하되, 해당 노드에 여유 메모리가 없으면 다른 노드에서 할당을 허용한다. bind보다 유연하면서도 데이터 지역성을 유지하려는 의도를 표현한다.

MPOL_BIND

지정한 노드 집합에서만 메모리를 할당받도록 강제한다. 로컬 메모리가 부족해도 다른 노드에서 빌려오지 않으므로, 메모리 부족 시 OOM(Out-of-Memory) 상황이 발생할 수 있다.

MPOL_INTERLEAVE

여러 노드에서 라운드 로빈 방식으로 페이지를 할당한다. 특정 노드에 메모리가 편중되는 것을 방지하며, 모든 노드의 대역폭을 고르게 활용하고 싶을 때 유용하다. 공유 데이터 구조나 모든 노드가 균등하게 접근하는 버퍼에 적합하다.

MPOL_LOCAL

할당 시점에 현재 CPU가 속한 노드에서 메모리를 할당한다. MPOL_DEFAULT와 유사하지만, mbind()로 VMA 단위에 적용할 수 있다는 점이 다르다.

MPOL_PREFERRED_MANY (Linux 5.12+)

MPOL_PREFERRED의 확장으로, 선호 노드를 하나가 아닌 노드 집합으로 지정한다. 집합 내 노드에서 우선 할당을 시도하되 모두 부족하면 다른 노드에서 할당을 허용한다. CXL 메모리 티어링처럼 여러 노드를 동등한 선호 대상으로 묶어야 하는 경우에 유용하다.

MPOL_WEIGHTED_INTERLEAVE (Linux 6.9+)6

MPOL_INTERLEAVE의 확장으로, 노드별 가중치에 따라 인터리브 비율을 조절한다. 예를 들어 DRAM 노드에 가중치 4, CXL 메모리 노드에 가중치 1을 부여하면 DRAM에서 4페이지를 할당할 때마다 CXL에서 1페이지를 할당한다. 대역폭이 상이한 메모리 티어가 혼재하는 환경에서 각 티어의 대역폭에 비례한 할당이 가능하다.

numactl을 통한 사용 예시는 다음과 같다.

# 노드 0에서만 메모리를 할당받도록 강제 (bind)
numactl --membind=0 ./my_application

# 노드 1의 CPU에서만 실행되도록 설정
numactl --cpunodebind=1 ./my_application

# 특정 CPU 코어에 고정
numactl --physcpubind=0,1,2,3 ./my_application

# 노드 0과 1에 걸쳐 인터리브 할당
numactl --interleave=0,1 ./my_application

프로세스별 현재 NUMA 메모리 할당 상태는 /proc/<pid>/numa_maps에서 확인할 수 있다.

Zone과 메모리 회수

리눅스 커널은 물리 메모리를 (zone) 단위로 관리한다. 각 NUMA 노드는 독립적인 존 집합(ZONE_DMA, ZONE_DMA32, ZONE_NORMAL, ZONE_MOVABLE 등)을 갖는다. 존 정보는 /proc/buddyinfo에서 확인할 수 있다.

NUMA 환경에서 특히 중요한 커널 파라미터가 vm.zone_reclaim_mode다. 이 파라미터는 로컬 노드의 존에 여유 메모리가 부족할 때 어떻게 대응할지를 결정한다.

vm.zone_reclaim_mode = 0 (비활성)

로컬 존에서 회수를 시도하지 않고, 다른 노드에서 메모리를 가져와 사용한다. 파일 캐시를 최대한 유지하는 전략이므로, 파일 I/O가 많은 워크로드에 유리하다.

vm.zone_reclaim_mode = 1 (활성)

다른 노드에서 가져오기 전에 로컬 존 안에서 먼저 페이지 캐시를 회수하여 재할당한다. 메모리 지역성을 극대화하지만, 캐시 히트율이 떨어질 수 있다.

이 파라미터는 원래 DMA 존 관리를 위한 것이었지만, NUMA 아키텍처 도입 이후 로컬 메모리 보존과 원격 할당 사이의 트레이드오프를 제어하는 핵심 튜닝 포인트가 되었다. 데이터베이스처럼 메모리 지역성이 극히 중요한 워크로드에서는 활성화가 유리하고, 파일 서버처럼 캐시가 중요한 환경에서는 비활성이 낫다.

Automatic NUMA Balancing

리눅스 3.8 이후에는 Automatic NUMA Balancing7이 도입되어, 커널이 자동으로 프로세스의 메모리 접근 패턴을 추적하고 페이지를 적절한 노드로 마이그레이션한다.

동작 원리는 다음과 같다. 커널이 주기적으로 프로세스의 페이지 테이블 엔트리에서 접근 비트를 제거하고 NUMA 힌팅 폴트(NUMA hinting fault)를 유발한다. Page Fault가 발생하면 커널은 어떤 CPU가 해당 페이지에 접근했는지를 기록하고, 페이지가 접근하는 CPU의 로컬 노드가 아닌 곳에 있으면 해당 노드로 마이그레이션을 고려한다. 이를 통해 프로그래머가 numactl이나 mbind()로 명시적으로 메모리 배치를 제어하지 않아도, 커널이 자동으로 데이터 지역성을 개선한다.

Linux 6.1부터는 메모리 티어링 모드(NUMA_BALANCING_MEMORY_TIERING)가 추가되었다. CXL 메모리처럼 지연이 서로 다른 메모리 티어가 혼재하는 환경에서, 자주 접근되는 "핫" 페이지는 빠른 티어(DRAM)로 승격하고, 접근 빈도가 낮은 "콜드" 페이지는 느린 티어(CXL 메모리)로 강등하는 동작이다. 커널의 migrate_misplaced_folio() 함수가 MR_NUMA_MISPLACED 사유로 페이지를 이동시키며, 각 VMA의 접근 통계(vma_numab_state)를 기반으로 마이그레이션 결정을 내린다. /proc/sys/kernel/numa_balancing 값을 2로 설정하면 이 티어링 모드가 활성화된다.

NUMA와 운영체제의 상호작용

스케줄링

NUMA 인식 스케줄러는 태스크를 배치할 때 메모리 지역성을 고려한다. 리눅스의 스케줄러는 스케줄링 도메인(scheduling domain) 계층을 NUMA 토폴로지에 맞추어 구성하며, 태스크가 자신의 메모리가 할당된 노드의 CPU에서 실행되도록 선호한다. 로드 밸런싱으로 태스크를 다른 노드로 이동시키는 것은 비용이 크므로, 노드 간 마이그레이션 임계값이 노드 내 코어 간 마이그레이션보다 높게 설정된다.

메모리 할당자

커널의 페이지 할당자(buddy allocator)와 슬랩 할당자(slab allocator)는 NUMA를 인식한다. kmalloc()이나 alloc_pages()는 기본적으로 현재 CPU가 속한 노드에서 메모리를 할당하며, kmalloc_node()alloc_pages_node()를 사용하면 특정 노드를 지정할 수 있다.

kswapd 데몬도 NUMA 노드별로 하나씩 실행된다(kswapd0, kswapd1, …). 각 kswapd 인스턴스는 자신이 담당하는 노드의 메모리 워터마크를 모니터링하며, 여유 메모리가 pages_low 아래로 떨어지면 백그라운드 페이지 회수를 시작한다.

fork()와 NUMA

fork()의 리눅스 구현을 추적하면, kernel_clone()copy_process() 호출 경로에서 NUMA 노드가 전달된다. copy_process()int node 매개변수를 받아 자식 프로세스의 선호 NUMA 노드를 지정할 수 있도록 설계되어 있지만, kernel_clone()은 이 값으로 항상 NUMA_NO_NODE를 전달한다8. 즉, 일반적인 fork() 경로에서는 특정 노드를 명시적으로 지정하지 않는다. copy_process()int node 인자는 커널 내부에서 워커 스레드를 특정 노드에 생성하는 경우(kthread_create_on_node() 등)를 위해 존재한다.

자식 프로세스는 부모의 NUMA 메모리 정책(mempolicy)을 상속하며, fork()의 Copy-on-Write 메커니즘과 결합하여 초기에는 부모와 같은 노드의 메모리를 공유하다가 쓰기가 발생하면 현재 실행 중인 CPU가 속한 노드에서 새 페이지를 할당받는다.

NUMA 최적화 전략

NUMA 시스템에서 최적의 성능을 얻으려면 데이터와 그 데이터를 처리하는 CPU를 같은 노드에 배치하는 것이 핵심이다. 이를 위한 실전 전략을 정리한다.

CPU 어피니티와 메모리 바인딩의 결합

CPU 어피니티만 설정하고 메모리 바인딩을 하지 않으면, 프로세스가 특정 노드의 CPU에서 실행되더라도 메모리가 다른 노드에 할당될 수 있다. 반대로 메모리 바인딩만 하면 스케줄러가 프로세스를 다른 노드의 CPU로 이동시킬 수 있다. 최적의 지역성을 위해서는 두 가지를 함께 설정해야 한다.

# CPU와 메모리를 동일 노드에 고정
numactl --cpunodebind=0 --membind=0 ./latency_sensitive_app

인터리브 전략

모든 워크로드가 데이터 지역성의 이점을 누리는 것은 아니다. 모든 노드의 CPU가 균등하게 접근하는 공유 데이터 구조(예: 해시 테이블, 락 테이블)는 특정 노드에 편중되면 오히려 해당 노드의 메모리 컨트롤러가 병목이 된다. 이런 경우 인터리브 정책으로 대역폭을 분산시키는 것이 효과적이다.

모니터링

numastat 명령은 노드별 메모리 히트/미스 통계를 제공하여, 원격 접근이 얼마나 발생하는지를 파악하는 데 유용하다.

# 시스템 전체 NUMA 통계
numastat

# 특정 프로세스의 NUMA 메모리 분포
numastat -p <pid>

numa_miss 값이 높다면 해당 프로세스의 메모리가 실행 CPU와 다른 노드에 할당되고 있다는 뜻이므로, CPU 어피니티나 메모리 정책 조정이 필요하다.

numad 데몬은 시스템의 NUMA 토폴로지와 리소스 사용 현황을 모니터링하면서, 프로세스를 최적의 노드에 자동 배치하는 사용자 공간 데몬이다.

현대 시스템에서의 NUMA

단일 소켓 내부의 NUMA

현대 프로세서에서는 단일 소켓 내부에서도 NUMA 토폴로지가 존재할 수 있다. AMD EPYC은 하나의 패키지 안에 여러 CCD(Core Complex Die)가 I/O 다이를 통해 연결되며, CCD마다 가까운 메모리 채널이 다르므로 NPS(NUMA nodes Per Socket) 설정에 따라 하나의 소켓이 여러 NUMA 노드로 나뉠 수 있다4. Intel의 SNC(Sub-NUMA Clustering)9도 유사하게 하나의 소켓 내부를 2~4개의 NUMA 도메인으로 분할한다.

이러한 추세는 NUMA가 더 이상 "멀티소켓 서버만의 문제"가 아님을 의미한다. 현대의 고성능 워크스테이션이나 단일 소켓 서버에서도 NUMA 최적화가 성능에 영향을 미칠 수 있다.

CXL과 메모리 확장

CXL(Compute Express Link)10은 PCIe 물리 계층 위에 캐시 일관성 프로토콜을 구현한 차세대 인터커넥트 표준이다. CXL을 통해 연결된 외부 메모리 장치도 CPU의 주소 공간에 매핑되어 NUMA 노드로 인식될 수 있다. 기존 DRAM 노드보다 지연이 크지만 용량 확장이 용이하여, 메모리 집약적 워크로드에서 비용 효율적인 메모리 티어링(memory tiering) 구성이 가능해진다. 리눅스 커널은 6.1부터 CXL 메모리를 별도의 NUMA 노드로 자동 등록하는 기능을 지원한다.


출처

  • Hennessy, J. L. and Patterson, D. A. (2019) Computer Architecture: A Quantitative Approach. 6th ed. Cambridge, MA: Morgan Kaufmann. Chapters 5–6.
  • Silberschatz, A., Galvin, P. B., and Gagne, G. (2018) Operating System Concepts. 10th ed. Hoboken, NJ: Wiley. §1.3.2, §6.
  • Culler, D. E., Singh, J. P., and Gupta, A. (1999) Parallel Computer Architecture: A Hardware/Software Approach. San Francisco, CA: Morgan Kaufmann.
  • Drepper, U. (2007) "What Every Programmer Should Know About Memory." Red Hat, Inc.
  • Bovet, D. P. and Cesati, M. (2008) Understanding the Linux Kernel. 3rd ed. Sebastopol, CA: O'Reilly.
  • Love, R. (2010) Linux Kernel Development. 3rd ed. Upper Saddle River, NJ: Addison-Wesley.
  • Linux kernel documentation — Documentation/admin-guide/mm/numa_memory_policy.rst, Documentation/admin-guide/sysctl/vm.rst.
  • Linux kernel source v6.19 — include/uapi/linux/mempolicy.h, mm/mempolicy.c, mm/memory-tiers.c, mm/migrate.c, kernel/fork.c, kernel/sched/topology.c.

Footnotes

  1. QPI(QuickPath Interconnect)는 Intel이 2008년 Nehalem 아키텍처와 함께 도입한 포인트-투-포인트 인터커넥트다. 기존의 공유 FSB(Front Side Bus)를 대체하였으며, 각 링크가 20비트 폭의 단방향 채널 2개(전이중)로 구성된다. — Hennessy and Patterson (2019), §5.4.

  2. UPI(Ultra Path Interconnect)는 Intel Skylake-SP(2017) 이후 Xeon 서버 프로세서에 사용되는 QPI의 후속 인터커넥트다. 전송률이 QPI 대비 향상되었고, 3-hop 라우팅을 통해 8소켓 이상의 구성도 지원한다.

  3. Infinity Fabric은 AMD가 Zen 아키텍처(2017)와 함께 도입한 스케일러블 인터커넥트로, 데이터 패브릭과 스케일러블 컨트롤 패브릭으로 구성된다. 칩렛(chiplet) 설계의 핵심 기술로, 다이 내부 CCD 간 연결부터 소켓 간 연결, GPU-CPU 연결까지 단일 패브릭으로 통합한다.

  4. AMD EPYC 프로세서의 NPS(NUMA nodes Per Socket) 설정은 NPS1(소켓 전체가 1노드), NPS2(2노드), NPS4(4노드) 등을 지원한다. NPS4로 설정하면 하나의 소켓이 4개의 NUMA 노드로 분할되어 각 CCD가 가장 가까운 메모리 채널에 직접 접근할 수 있지만, 운영체제와 애플리케이션이 더 세분화된 NUMA 토폴로지를 인식해야 한다. 2

  5. SRAT(System Resource Affinity Table)는 ACPI 사양에 정의된 테이블로, 프로세서와 메모리가 어떤 근접 도메인(proximity domain)에 속하는지를 기술한다. SLIT(System Locality Information Table)는 근접 도메인 간의 상대 거리를 N×NN \times N 행렬로 제공한다. 리눅스 커널은 부팅 시 이 테이블들을 파싱하여 NUMA 토폴로지를 구축한다.

  6. MPOL_WEIGHTED_INTERLEAVE는 Linux 6.9에서 도입되었다(commit fa3bea4e). /sys/kernel/mm/mempolicy/weighted_interleave/아래 노드별 가중치를 설정하며, 커널의weighted_interleave_nodes()함수가 가중치에 따라 할당 노드를 결정한다. — Linux kernel documentation,Documentation/admin-guide/mm/numa_memory_policy.rst`.

  7. Automatic NUMA Balancing은 /proc/sys/kernel/numa_balancing으로 제어한다. 0(비활성), 1(NUMA 밸런싱만 활성), 2(메모리 티어링 모드 포함 활성)의 세 가지 값을 지원한다. 마이그레이션 비용이 접근 지연 감소의 이점보다 큰 경우에는 비활성(0)이 유리할 수 있다.

  8. kernel/fork.ckernel_clone() 함수는 copy_process(NULL, trace, NUMA_NO_NODE, args)를 호출한다. copy_process()의 세 번째 매개변수 int nodekthread_create_on_node() 등 커널 내부 경로에서 특정 NUMA 노드를 지정할 때 사용된다. — Linux v6.19 kernel/fork.c.

  9. SNC(Sub-NUMA Clustering)는 Intel Xeon Scalable 프로세서에서 LLC(Last Level Cache)와 메모리 컨트롤러를 2~4개의 클러스터로 분할하여, 하나의 소켓 내부에 여러 NUMA 도메인을 생성하는 BIOS 설정이다. LLC 히트 지연을 줄이는 효과가 있지만, 클러스터 간 접근은 추가 지연이 발생한다.

  10. CXL(Compute Express Link)은 PCIe 5.0/6.0 물리 계층 위에 CXL.io(I/O), CXL.cache(캐시 일관성), CXL.mem(메모리 접근)의 세 가지 프로토콜을 정의한다. CXL 3.0은 메모리 공유와 패브릭 연결까지 지원하여, NUMA 아키텍처를 소켓 경계 너머로 확장하는 방향으로 진화하고 있다.