0x0102
DevOps - NUMA, 메모리 관리 새로운 세계 본문
1. NUMA 아키텍처
NUMA (Non-Uniform Memory Access) : 불균형 메모리 접근. 멀티 프로세서 환경에서 적용되는 메모리 접근 방식
0번 CPU가 자신의 로컬 메모리에 접근하는 동안 1번 CPU도 자신의 로컬 메모리에 접근할 수 있어 성능이 향상된다.
그러나 로컬 메모리의 양이 모자라면 다른 CPU 메모리에 접근이 필요하게 되고, 이때 메모리 접근에 시간이 소요되어 성능 저하가 발생할 수 있다.
따라서 로컬 메모리에서 메모리 접근이 얼마나 많이 일어나느냐가 성능 향상의 KEY-Point 이다.
+ Local Access : 각 CPU마다 별도의 메모리에 접근하는 방식
+ node : CPU + 메모리
+ Remote Access : NUMA에서 자신의 메모리가 아닌 다른 노드에 있는 메모리에도 접근할 수 있는 것
<-> UMA(Uniform Memory Access) : 초창기 아키텍쳐로 모든 프로세서가 공용 BUS를 이용하여 메모리 접근하기 때문에 BUS의 동시 사용이 불가능함.
2. 리눅스에서의 NUMA 확인
numactl : NUMA와 관련된 정책을 확인하거나 설정할 때 사용
기본 정책이 default로 설정되어있는 것을 알 수 있다.
NUMA의 메모리 할당 정책은 4가지가 있다.
1) default : 별도의 설정을 하지 않은 모든 프로세스에 적용. 현재 사용 중인 프로세스가 포함된 노드에서 메모리를 먼저 할당 받아 사용
2) bind : 특정 프로세스를 특정 노드에 바인딩시키는 방식 ex) 0번 노드에 할당 시 0번 노드에서만 메모리 할당
3) preferred : bind와 비슷하지만 선호하는 노드를 설정하여 그 노드로부터 메모리 할당
4) interleaved : 다수의 노드에서 거의 동일한 비율로 메모리 할당 (Round-Robin 방식)
available : 1 nodes // 노드가 1개로 구성됨
node 0 cpus : 0 1 // 노드에 해당하는 cpu 번호와 할당된 메모리의 크기
node distances // 각 노드의 메모리에 접근하는 데 걸리는 시간
numastat: NUMA 환경에서 현재 시스템에 할당된 메모리의 상태를 확인할 때 사용하는 명령어
numastat이 중요한 이유는 NUMA 아키텍쳐에서 메모리 불균형 상태를 확인할 수 있기 때문이다.
어느 한쪽 노드의 메모리 사용률이 높으면 메모리 할당 정책에 따라 swap을 사용하는 경우가 생기고 이런 상태를 확인 가능하다.
+) /proc/<pid>/numa_maps에 프로세스의 메모리 할당 정책과 관련된 정보가 기록된다.
3. 메모리 할당 정책별 특징
1) default 정책
프로세스가 동작 중인 CPU 노드에 따라 메모리를 할당한다.
ex) A라는 프로세스가 0번 노드에 있는 CPU를 할당받아 동작하다가 1번 노드에 있는 CPU를 할당받아 동작하게 되면
기존 0번 노드에서 확보한 메모리는 로컬메모리가 아닌 원격 메모리가 되고, 이후 접근은 로컬 액세스가 아닌 리모트 액세스가 된다.
그래서 메모리 접근에 시간이 많이 소요되며 지역성이 떨어진다.
2) bind 정책
numactl로 할 수 있는 bind 정책은 membind, cpunodebind, physcpubind 3가지가 있다.
membind - 메모리의 지역성을 전혀 살리지 못하고 성능저하가 일어나므로 권장 x
cpunodebind - BIND 중에서도 특정 노드에 있는 CPU에서만 프로세스가 돌아가도록 설정. 지역성을 높이기에 membind보다 선호되지만 멀티 스레드로 동작하는 경우 CPU를 절반만 사용할 수 있기 때문에 CPU 리소스가 낭비됨
physcpubind - cpunodebind와 유사하지만 CPU 번호를 매핑한 개념
3) preferred 정책
BIND와 유사하지만 가능한 한 특정 노드에서 메모리를 할당받도록 하는 정책
설정한 노드 이상의 메모리를 사용하게 되면 OOM이 발생해서 프로세스가 중지되는 membind 정책과 달리 설정한 노드에서 메모리가 부족해지면 다른 노드로부터 메모리를 할당 받기 때문에 OOM이 발생되지 않는다.
4) interleaved 정책
다수의 노드로부터 공평하게 메모리 할당을 받는 정책
4. numad를 이용한 메모리 할당 관리
리눅스에서는 numad를 통해 NUMA 메모리 할당 정책을 직접 설정하지 않고도 메모리 지역성을 높이는 방법을 제공한다.
numad : 백그라운드 데몬과 같은 형태로 시스템에 상주하면서 프로세스들의 메모리 할당 과정을 주기적으로 살피고 프로세스들을 최적화하는 작업을 담당
그러나 interleave 정책으로 실행되는 경우 numad가 지역성을 너무 높여버리면 메모리 불균형이 발생하는 단점도 존재한다.
따라서 워크로드에 따라 numad 사용을 잘 판단하여 적용해야한다.
5. vm.zone_reclaim_mode 커널 파라미터
vm.zone_reclaim_mode 는 numad에 비해 영향은 작지만 메모리 할당에 영향을 주는 커널 파라미터이다.
이는 NUMA 아키텍처를 위해 만들어진 파라미터가 아님에도 영역별 할당 여부에 영향을 주는 역할 때문에 NUMA 아키텍처 도입 후 중요성이 증대했다.
해당 파라미터는 4개의 값을 가질 수 있다.
0 : disable zone안에서 재할당 x ( 파일 서버와 같이 다수의 I/O가 발생하는 서버의 경우 설정)
1: enable zone 안에서 재할당 o ( page cache 확보보다 메모리에 대한 로컬 액세스 방식이 더 유리할 때 설정)
6. NUMA 아키텍처의 메모리 할당 정책과 워크로드
그렇다면 NUMA 메모리 할당 정책을 어떻게 사용해야 성능을 최적화 할 수 있을까?
고려사항 1 : 메모리의 크기와 프로세스 스레드 개수 고려
1) 메모리가 노드 하나의 크기를 넘지 않음 / 싱글 스레드
이런 워크로드라면 NUMA 아키텍처를 사용하는 2소켓 이상의 시스템을 사용할 필요가 없으나.
만약 꼭 사용해야하는 경우 BIND 정책으로 특정 CPU에 바인딩하는 것이 도움이 된다.
싱글 스레드임으로 1개 이상의 CPU가 필요하지도 않고 바인딩으로 CPU 캐시도 최대로 활용 가능하기 때문이다.
추가로 vm.zone_reclaim_mode는 1로 켜두는 것이 메모리 로컬 액세스가 늘어나 성능 향상에 좋다.
2) 메모리가 노드 하나의 크기를 넘지 않음 / 멀티 스레드
cpunodebind 모드로 여러 코어에 프로세스를 바인딩시키고 해당 노드에서만 메모리를 할당 받아 사용하게 되면 가장 좋다.
그러나 cpu 리소스가 모자랄 수 있으므로 모니터링해야한다.
추가로 vm.zone_reclaim_mode는 1로 켜두는 것이 메모리 로컬 액세스가 늘어나 성능 향상에 좋다.
+ numad가 가장 효과적으로 동작할 수 있는 워크로드이다.
3) 메모리가 노드 하나의 크기를 넘음 / 싱글 스레드
메모리의 지역성을 최대로 올릴 수 있는 방법을 사용해야하고 싱글 스레드로 동작하기 때문에 리모트 액세스가 발생하는 경우이다.
이런 경우 리모트 액세스를 최소화 하는 것이 성능 최적화의 핵심이다.
싱글스레드임으로 cpu cache 사용을 최적화 해야하기에, 첫번째 케이스와 마찬가지로 cpunodebind 정책이 가장 유리하다.
추가로 vm.zone_reclaim_mode는 0으로 켜두는 것이 어차피 메모리가 한 개 이상의 노드를 필요로 하기 때문에 처음부터 다수의 노드로부터 메모리를 할당 받을 수 있으므로 성능 향상에 좋다.
4) 메모리가 노드 하나의 크기를 넘음 / 멀티 스레드
가장 흔한 경우로 이 또한 메모리가 노드 하나의 크기를 넘으므로 리모트 액세스가 필연적으로 발생한다.
게다가 멀티 스레드 환경이므로 이 경우 interleave 모드가 최적의 성능을 낼 수 있다.
어떤 cpu에 어떤 스레드가 바인딩될지 모르기 때문에 가능한 한 메모리 할당을 여러 영역에 넓게 펼치는 것이 유리하기 때문이다.
추가로 vm.zone_reclaim_mode는 0으로 켜두는 것이 어차피 메모리가 한 개 이상의 노드를 필요로 하기 때문에 처음부터 다수의 노드로부터 메모리를 할당 받을 수 있으므로 성능 향상에 좋다.
'Study > DevOps' 카테고리의 다른 글
DevOps - TCP Keepalive를 이용한 세션 유지 (0) | 2024.02.01 |
---|---|
DevOps - TIME_WAIT 소켓이 서비스에 미치는 영향 (0) | 2024.01.29 |
DevOps - swap, 메모리 증설의 포인트 (0) | 2024.01.23 |
DevOps - free 명령이 숨기고 있는 것들 (1) | 2024.01.22 |
DevOps - Load Average와 시스템 부하 (0) | 2024.01.19 |