NUMA
Non-Uniformed Memory Access
불균일 기억장치 접근
[image]
NUMA 개략도.
[image]
인텔 네할렘 CPU의 NUMA 구조도.
1. 개요
메모리에 접근하는 시간이 CPU와 메모리의 상대적인 위치에 따라 달라지는 컴퓨터 메모리 설계 방법. 각 CPU는 메모리의 일부를 자신의 지역 메모리(Local Memory)로 가지고 있으며 이 지역 메모리에 접근하는 속도는 원격 메모리(Remote Memory)에 접근하는 속도보다 훨씬 빠르다.
간단히 예를 들어 시스템에 CPU 소켓이 네 개 있고, 512GB의 메모리가 설치되어 있다면 물리 주소 0~128G-1번지까지의 메모리는 0번 소켓의, 128G~256G-1번지까지의 메모리는 1번 소켓의 지역 메모리가 되는 방식. 각 소켓에서 지역 메모리에 접근할 때에는 원격 메모리에 접근할 때보다 훨씬 빠르게 데이터를 읽고 쓸 수 있다. 하나의 CPU 소켓에 코어 여러개가 들어가 있을 수 있기에 같은 지역 메모리를 사용하는 CPU 코어들을 묶어서 하나의 NUMA 노드로 친다. 8코어 4소켓 CPU라면 (하이퍼스레딩을 가정하지 않을 때에) 0~7번 코어는 NUMA 노드 0번, 8~15번 코어는 NUMA 노드 1번과 같은 방식.
RAM 항목에 설명되어있듯이 본래 '임의 접근 메모리'는 메모리상의 어느 위치에든 제한없이 접근할 수 있다. 그런데 소켓 여러개에 CPU를 꽂거나 아예 CPU 하나에 연산 장치를 다수 박아 사용하면서 모든 메모리에 동일하게 접근하게 되면 한 번에 하나의 프로세서만이 메모리 버스를 점유할 수 있게 되어 다른 프로세서들은 그 동안 대기하여야 하는 현상이 발생한다. 만일 알고리즘을 잘 설계해서 각 CPU가 메모리의 서로 다른 위치에 접근하게 하고 CPU간에 간섭이 없이 각 메모리에 접근하여 병렬로 데이터를 처리한다면 그만큼의 성능 향상을 얻을 수 있게 된다.[1] 여기에서 각 CPU 전용 메모리라는 개념이 생기게 되었다.
그리고 CPU의 작동 속도가 빨라지면서 CPU와 메모리 사이의 '''물리적인''' 거리가 메모리 접근 속도에 영향을 끼치기 시작하였다. 2GHz로 작동하는 CPU라면 바로 코앞에 있는 메모리에 접근할 때보다 15cm 거리가 있는 메모리에 접근할 때 한 클럭을 더 낭비하게 된다.[2] 메인보드에 CPU 여러 개를 꽂을 수 있다면 CPU와 메모리 뱅크가 번갈아가며 배치되어 있는 것을 볼 수 있는데 이것이 각 CPU 소켓에 메모리를 최대한 가까이 설치하려는 설계이다.
1.1. ccNUMA
Cache-Coherent NUMA. NUMA이면서 캐시 일관성을 가지는 시스템. 프로그래머가 캐시를 직접 제어할 방법이 없다면 하드웨어가 무조건 ccNUMA여야 한다. 현대의 NUMA 하드웨어는 모두 ccNUMA이다.
1.2. vs 클러스터
지역 메모리와 원격 메모리의 구분이 있다는 점에서 작은 클러스터로 간주하기도 한다. 그런데 한 시스템 내부에서의 메모리 접근 속도 차이(보통 3~4배)는 어지간한 속도/최적화 덕후가 아니라면 무시하고 프로그래밍하는 경우도 많기 때문에 수백~수천배 이상의 접근 속도 차이를 보이는 클러스터 시스템과는 분명 차이가 있다.
2. 소프트웨어 지원
하드웨어에서 NUMA를 지원해도 소프트웨어에서 메모리를 주먹구구식으로 나누어 준다면 NUMA의 이점을 충분히 활용할 수 없게 된다. 서버용 운영체제와 대량의 자원을 소비하는 서버용 애플리케이션들은 대부분 NUMA에 대응해 메모리를 포함한 시스템 자원을 관리한다.
2.1. 리눅스
/proc/$pid/numa_maps에서 해당 프로세스에 할당해준 메모리 중 어느 논리 주소가 어느 NUMA 노드에 할당되어 있는지 모두 볼 수 있다. 리눅스 시스템 콜 중 일부는 특정 NUMA 노드에서 메모리를 할당하거나, 한 NUMA 노드에서 다른 NUMA 노드로 메모리를 이동시키는 기능을 제공한다.
2.2. Microsoft
Windows에서 NUMA API를 지원해준다. API 자체는 Windows XP SP2 부터 지원 되기는 했으나 Windows NT 커널의 스케쥴러가 NUMA 환경에서도 한 프로세스의 스레드를 리모드 노드에 스케쥴링 하는 등 UMA와 같은 방식으로 스케쥴링해 성능이 떨어지는 문제가 있었으나 Windows 10 19H2 (1909) 업데이트 부터 조금 나아졌다.
MS의 DBMS 제품인 MS-SQL에서는 하드웨어적인 NUMA 이외에도 소프트웨어적으로 NUMA를 흉내낼 수 있도록 해 주는데 일정 복잡도 이상의 설정은 레지스트리를 편집해야 한다.
2.3. 구글
구글에서는 자체적으로 tcmalloc이라는 고성능 메모리 관리자를 만들어 배포한다. 이것을 개조하여 NUMA에 대응해 메모리를 할당해주는 비공식 업그레이드가 있다.
2.4. 오라클
12 버전으로 넘어오면서 NUMA 지원이 대폭 강화되었다. DBA로 로그인해 SQL 명령 ALTER SYSTEM SET을 이용해 NUMA 지원을 켠 후 DBMS를 재시동하면 된다.
3. 관련 항목
[1] 세상 일이 그렇게 간단하지는 않다. 암달의 법칙 참고. 실제로 AMD의 쓰레드리퍼 2세대가 NUMA 병목으로 인한 성능 저하가 있어서 전용 최적화 프로그램이 개발되기도 했다.[2] 실제로는 메모리가 CPU보다 느리게 작동하기에 캐시 메모리가 아닌 메인 메모리에 접근할 때에는 보통 수십 클럭을 낭비한다.