NAME

set_mempolicy - 스레드와 그 자식들에 기본 NUMA 메모리 정책 설정하기

SYNOPSIS

#include <numaif.h>

long set_mempolicy(int mode, const unsigned long *nodemask,
                   unsigned long maxnode);

-lnuma로 링크.

DESCRIPTION

set_mempolicy()는 호출 스레드의 NUMA 메모리 정책을 설정한다. 정책은 정책 모드와 0개 이상의 노드들로 이뤄지며 이를 mode, nodemask, maxnode 인자로 지정한 값들로 설정한다.

NUMA 머신에는 CPU들과 거리가 다른 여러 개의 메모리 컨트롤러가 있다. 메모리 정책은 스레드를 위한 메모리를 어느 노드에서 할당할지 규정한다.

이 시스템 호출은 스레드의 기본 정책을 지정한다. mbind(2)로 설정한 더 구체적인 정책의 통제를 받는 메모리 범위들 외의 프로세스 주소 공간에서 스레드 정책이 페이지 할당을 제어한다. 스레드 기본 정책은 또한 mmap(2) 호출을 MAP_PRIVATE 플래그로 사용해 맵 해서 그 스레드에서만 읽는(적재하는) 메모리 맵 파일과 접근 방식과 무관하게 mmap(2) 호출을 MAP_SHARED 플래그로 사용해 맵 한 메모리 맵 파일의 페이지 할당을 제어한다. 스레드를 위해 새 페이지를 할당할 때에만 정책이 적용된다. 익명 메모리에서는 스레드가 페이지를 처음 건드릴 때이다.

mode 인자에는 MPOL_DEFAULT, MPOL_BIND, MPOL_INTERLEAVE, MPOL_PREFERRED, MPOL_LOCAL (아래에서 자세히 설명함) 중 하나를 지정해야 한다. MPOL_DEFAULT를 제외한 모든 모드에서 호출자가 nodemask 인자를 통해 모드를 적용할 노드를 지정해야 한다.

mode 인자에 선택적으로 모드 플래그가 포함될 수 있다. 지원하는 모드 플래그는 다음과 같다.

MPOL_F_STATIC_NODES (리눅스 2.6.26부터)
비어 있지 않은 nodemask가 물리적 노드 ID들을 나타낸다. 프로세스가 다른 cpuset 문맥으로 이동하거나 프로세스의 현재 cpuset 문맥이 허용하는 노드 집합이 바뀔 때 리눅스에서 nodemask를 재사상 하지 않는다.
MPOL_F_RELATIVE_NODES (리눅스 2.6.26부터)
비어 있지 않은 nodemask가 프로세스의 현재 cpuset이 허용하는 노드 ID 집합에 대한 상대적인 노드 ID들을 나타낸다.

nodemask는 노드 ID들의 비트 마스크를 가리키며 그 비트 마스크에는 최대 maxnode 개까지의 비트가 담겨 있다. 비트 마스크 크기를 sizeof(unsigned long)의 다음 배수로 올림 하지만 커널에서는 maxnode 개까지의 비트만 사용한다. nodemask 값이 NULL이거나 maxnode 값이 0이면 빈 노드 집합을 나타낸다. maxnode의 값이 0이면 nodemask 인자를 무시한다.

nodemask가 필수인 경우에 그 인자는 온라인이고, (MPOL_F_STATIC_NODES 모드 플래그를 지정하지 않았으면) 프로세스의 현재 cpuset 문맥이 허용하고, 메모리를 담고 있는 노드를 적어도 한 개는 포함해야 한다. modeMPOL_F_STATIC_NODES가 설정돼 있고 필수인 nodemask에 프로세스의 현재 cpuset 문맥이 허용하는 노드가 하나도 담겨 있지 않으면 메모리 정책이 지역 할당으로 되돌아간다. 즉 프로세스의 cpuset 문맥이 nodemask에 지정한 노드를 하나 이상 포함하게 될 때까지는 실질적으로 지정한 정책을 무시한다.

mode 인자에 다음 값들 중 하나가 포함돼야 한다.

MPOL_DEFAULT
이 모드는 기본과 다른 스레드 메모리 정책을 모두 제거해서 메모리 정책을 시스템 기본 정책으로 "후퇴"시키게 한다. 시스템 기본 정책은 "지역 할당"이다. 즉 할당을 촉발한 CPU의 노드에서 메모리를 할당한다. nodemask를 NULL로 지정해야 한다. "지역 노드"에 유휴 메모리가 없으면 "인근" 노드에서 메모리를 할당하려 시도하게 된다.
MPOL_BIND
이 모드는 메모리 할당을 nodemask에 지정한 노드들로 제약하는 엄격한 정책을 지정한다. nodemask에 노드가 여러 개 있으면 노드 ID의 숫자 값이 가장 낮은 노드에서 페이지 할당을 한다. 그 노드에 유휴 메모리가 없어지면 nodemask에 지정한 다음으로 낮은 ID의 노드에서 할당을 하고, 그런 식으로 지정한 노드들 어디에도 유휴 메모리가 없을 때까지 진행한다. nodemask에 지정하지 않은 어떤 노드에서도 페이지를 할당하지 않는다.
MPOL_INTERLEAVE
이 모드에서는 nodemask에 지정한 노드들 내에서 노드 ID 순서에 따라 교대로 페이지 할당을 한다. 페이지들과 그에 대한 메모리 접근을 여러 노드로 분산시킴으로써 지연보다는 대역폭을 최적화 한다. 하지만 단일 페이지에 대한 접근은 여전히 단일 노드 메모리 대역폭으로 제한된다.
MPOL_PREFERRED
이 모드는 할당 선호 노드를 설정한다. 커널이 먼저 그 노드에서 페이지를 할당하려고 시도하지만 그 선호 노드에 유휴 메모리가 부족하면 "인근" 노드로 후퇴한다. nodemask에 노드 ID를 여러 개 지정하면 마스크의 첫 번째 노드를 선호 노드로 선택하게 된다. nodemaskmaxnode 인자가 빈 집합을 나타내는 경우에는 이 정책이 (위에 설명한 시스템 기본 정책 같은) "지역 할당"을 지정한다.
MPOL_LOCAL (리눅스 3.8부터)
이 모드는 "지역 할당"을 나타낸다. 즉 할당을 촉발한 CPU의 노드("지역 노드")에서 메모리를 할당한다. nodemaskmaxnode 인자가 빈 집합을 나타내야 한다. "지역 노드"에 유휴 메모리가 부족한 경우 커널은 다른 노드에서 메모리 할당을 시도하게 된다. 사용 가능한 메모리가 있는 경우에는 커널이 항상 "지역 노드"에서 메모리를 할당하게 된다. 프로세스의 현재 cpuset 문맥이 "지역 노드"를 허용하지 않으면 커널이 다른 노드에서 메모리 할당을 시도하게 된다. 프로세스의 현재 cpuset 문맥에서 허용하게 되면 커널이 항상 "지역 노드"에서 메모리를 할당하게 된다.

execve(2)를 거치면서 스레드 메모리 정책이 유지되며, fork(2)clone(2)으로 생성한 자식이 정책을 물려받는다.

RETURN VALUE

성공 시 set_mempolicy()는 0을 반환한다. 오류 시 -1을 반환하며 오류를 나타내도록 errno를 설정한다.

ERRORS

EFAULT
nodemaskmaxnode로 지정한 메모리 범위의 일부 내지 전체가 접근 가능한 주소 공간 밖을 가리킨다.
EINVAL
mode가 유효하지 않다. 또는 modeMPOL_DEFAULT이고 nodemask가 비어 있지 않거나, modeMPOL_BINDMPOL_INTERLEAVE이고 nodemask가 비어 있다. 또는 maxnode가 나타내는 비트들이 한 페이지를 넘는다. 또는 지원하는 가장 큰 노드 ID보다 큰 노드 ID를 nodemask에 한 개 이상 지정했다. 또는 nodemask로 지정한 노드 ID들 중에서 온라인이고 프로세스의 현재 cpuset 문맥에서 허용되는 게 없거나, 지정한 노드들 중에서 메모리를 담고 있는 게 없다. 또는 mode 인자에 MPOL_F_STATIC_NODESMPOL_F_RELATIVE_NODES를 함께 지정했다.
ENOMEM
사용 가능한 커널 메모리가 충분하지 않다.

VERSIONS

리눅스 커널 버전 2.6.7에서 set_mempolicy() 시스템 호출이 추가되었다.

CONFORMING TO

이 시스템 호출은 리눅스 전용이다.

NOTES

페이지를 스왑으로 내보낼 때 메모리 정책을 기억해 두지 않는다. 그 페이지를 되돌릴 때는 페이지 할당 시점에 적용 중인 스레드 내지 메모리 범위 정책을 사용하게 된다.

라이브러리 지원에 대한 정보는 numa(7)를 보라.

SEE ALSO

get_mempolicy(2), getcpu(2), mbind(2), mmap(2), numa(3), cpuset(7), numa(7), numactl(8)


2020-12-21