-
Linux NUMA 아키텍처 정리커널(Kernel) 2022. 12. 5. 19:22
환경 정보
OS: ubuntu18.04
NUMA 아키텍처
NUMA는 Non-Uniform Memory Access의 약자로 불균형 메모리 접근을 의미한다.
불균형 메모리 접근이란 멀티 프로세서 환경에서 동시에 메모리 접근이 가능한 것을 말한다.
예를 들어, 0번 소켓 CPU에서 로컬 메모리에 접근, 1번 소켓 CPU에서 로컬 메모리에 접근이 동시에 일어날 수 있다.
NUMA가 있기 전의 UMA 아키텍처의 경우 버스를 공유해서 사용했기 때문에 메모리에 동시 접근이 불가능했다.
참고
1. 노드(Node) - CPU와 CPU에 연결된 메모리를 노드라 한다.
2. 로컬 액세스(Local access) - 자신의 노드 안에서 메모리 접근을 로컬 액세스라 한다.
3. 리모트 엑세스(Remote Access) - 다른 노드에 있는 메모리 접근을 리모트 액세스라 한다. 다른 노드에 있는 메모리에 접근할 경우, 메모리 지역성이 떨어지므로 성능이 저하된다.
어떤 노드의 메모리를 사용할지는 NUMA에서 사용하는 정책에 따라 결정된다.
NUMA 정책은 다음과 같이 확인할 수 있다.
우선 위 이미지에서는 기본 정책이 default인것을 알 수 있다.
그리고 default 정책 이외에도 다음과 같은 정책들이 있다.
1. default
프로세스가 포함된 노드에서 메모리를 가져다가 사용하는 방식
2. bind
특정 프로세스를 특정 노드에서만 사용하도록 바인딩 시킨다.
membind, cpunodebind, physcpubind 등이 있다.
3. preferred
특정 노드를 선호하도록 설정한다.
바인딩과 유사하지만 가능한 설정한 노드로부터 메모리를 할당 받는다.
4. interleaved
round robin 방식으로 한 번씩 돌아가면서 메모리를 할당 받는다.
이러한 정책들은 numactl 유틸리티를 통해서 변경할 수 있다.
사용중인 노드는 다음과 같이 확인할 수 있다.
현재는 1개의 노드만 사용 중인 상태로 다음과 같은 정보를 확인할 수 있다.
- 0번 노드에 붙어 있는 CPU는 8 core다.
- 0번 노드에서 사용 중인 로컬 메모리는 16GB다.
- node distance는 각 노드의 메모리에 접근하는 데 걸리는 시간으로 0번 노드에서 0번 노드로의 메모리 엑세스 시간을 10이라고 했을 때 다른 노드로의 접근 시간을 나타낸다. 현재는 노드가 1개이기 때문에 구체적으로 확인하기가 좀 어렵다.
NUMA 환경에서 각 노드에 할당된 메모리 상태 확인하기
이 유틸리티를 사용하면, NUMA 아키텍처에서 노드에 걸쳐 메모리 불균형을 확인할 수 있다.
만약 한쪽 노드에서만 메모리를 많이 사용하게 되면,
swap영역을 사용하게 되어 시스템 성능 저하를 일으킬 수 있기 때문에 이를 확인하는 것은 중요하다.
프로세스에서 어떤 NUMA 메모리 할당 정책을 사용했는지 확인하기
현재 프로세스에서는 default 정책을 사용 중인 것을 알 수 있다.
프로세스에서 사용 중인 Node 메모리 확인하기
현재는 node가 하나밖에 없지만 default 정책이므로 할당된 노드에서만 메모리를 할당받는다.
참고로 taskset 유틸리티를 이용하면, 프로세스가 할당된 노드를 변경할 수 있다.
numad를 이용해서 메모리 할당 관리하기
numactl을 이용해서 정책을 수동으로 설정할 수 있지만, numad를 이용하면 자동으로 메모리 지역성을 높일 수 있다.
프로세스가 필요로 하는 메모리 크기가 여러 노드에 걸쳐 존재해야 하는 경우, numad가 도움이 될 수 있다.
numad는 사용자가 신경 쓰지 않아도 메모리 할당 문제를 해결해주긴 하지만 항상 그렇듯이 성능에 좋지 않은 영향을 끼칠 수도 있다.
따라서 무조건 사용하는 것보다는 시스템의 워크로드에 따라서 판단해서 사용해야 한다.
커널 파라미터 - vm.zone_reclaim_mode
커널은 메모리를 사용 용도에 따라 zone이라는 영역으로 구분하여 관리한다.
zone은 버디 시스템 정보와 함께 확인할 수 있는데 다음과 같이 노드명에 따른 zone을 확인할 수 있다.
(현재는 노드가 하나밖에 없지만 만약 노드가 하나 더 있다면 Node 1, zone Normal를 확인할 수 있을 것이다)
우선 Normal 영역은 커널, 프로세스 등이 메모리를 필요로 할 때 사용하는 영역이다.
그리고 vm.zone_reclaim_mode 커널 파라미터는 zone 들 사이의 메모리가 부족할 경우,
다른 영역의 메모리를 할당할 수 있게 해 준다.
예를 들어, 노드 0의 Normal 영역에서 메모리가 부족하여 노드 1의 Normal 영역 메모리를 사용하는 경우 이 파라미터가 개입한다.
vm.zone_reclaim_mode 파라미터는 4가지 케이스의 값을 가질 수 있지만, 여기서는 2가지 값만 알아본다
1) vm.zone_reclaim_mode = 0 일 때
disable로 zone안에서 재할당하지 않겠다는 의미로 다른 zone에서 가져와서 사용하겠다는 의미다.
0으로 설정하는 경우, 로컬 액세스를 통해서 얻는 이점보다는 페이지 캐시 등과 같은 재할당 대상 메모리들이 반환되지 않고, 다른 노드에 있는 메모리를 할당받아 쓸 수 있으므로 좋다.
2) vm.zone_reclaim_mode = 1 일 때
1은 enable로 zone안에서 재할당을 시도 후, 실패하면 리모트 엑세스를 통해서 메모리를 사용하겠다는 의미다.
1로 설정하는 경우, 로컬 액세스를 통해서 얻을 수 있는 이점이 더 클 때 사용하는 것이 좋다.
워크로드에 따른 NUMA 아키텍처 메모리 할당 정책
워크로드에 따라 효율적인 NUMA 아키텍처의 정책을 정할 수 있다.
워크로드는 메모리의 크기와 프로세스의 스레드 수에 따라 나눌 수 있을 것이다.
1. 싱글 스레드 사용, 메모리가 노드 하나의 크기를 넘지 않는 경우
애초에 이러한 워크로드는 2 소켓 이상 시스템을 사용할 필요가 없다.
1 소켓의 UMA 아키텍처를 사용하는 것이 성능 최적화에 좋으며
만약 NUMA를 사용한다면, cpu bind 정책을 이용해서 특정 cpu에 바인딩하는 것이 좋다.
또한 vm.zone_reclaim_mod =1로 설정하여 로컬 액세스를 늘리는 것이 좋다.
2. 멀티 스레드 사용, 메모리가 노드 하나의 크기를 넘지 않는 경우
해당 워크로드는 cpu node bind 정책을 이용해서 여러 개의 코어에 프로세스를 바인딩시키고,
해당 노드에서만 메모리를 할당받아서 사용하게 하면 된다.
vm.zone_reclaim_mod =1로 설정하여 로컬 액세스를 늘리는 것이 좋다.
3. 싱글 스레드 사용, 메모리가 노드 하나의 크기를 넘는 경우
이 경우는 리모트 액세스가 발생할 수밖에 없다. 따라서 리모트 액세스를 최소화하는 게 가장 중요하다.
cpunodebind 정책을 이용하여 cpu cache 사용을 최적화하고 vm.zone_reclaim_mod=0로 설정하여 메모리를 처음부터 다수의 노드에서 메모리 할당을 받게끔 한다.
4. 멀티 스레드 사용, 메모리가 노드 하나의 크기를 넘는 경우
해당 워크로드가 가장 흔한 경우로 볼 수 있다.
3번과 마찬가지로 마찬가지로 리모트 액세스가 발생할 수밖에 없으며, interleaved 정책을 사용하는 게 최적의 성능을 낼 수 있다.
커널 파라미터 또한 마찬가지로 vm.zone_reclaim_mod=0로 설정하여 메모리를 처음부터 다수의 노드에서 메모리 할당을 받게끔 한다.
Reference
Devops와 SE를 위한 리눅스 커널 이야기
반응형'커널(Kernel)' 카테고리의 다른 글
Linux TCP Keepalive 정리 (0) 2022.12.11 Linux TIME_WAIT 소켓 정리 (0) 2022.12.11 Linux Swap 영역 정리 (0) 2022.12.04 Linux 메모리 정리(buffer, cache, Active/Inactive, slab) (0) 2022.11.28 Linux Load Average로 부하 확인하기 (0) 2022.11.27