공유 메모리 환경 (예 : OpenMP, Pthreads 또는 TBB를 통해 스레드)에서 메모리 대역폭 제한 계산을 수행 할 때 각 스레드가 대부분의 메모리에 액세스 하도록 메모리가 실제 메모리에 올바르게 분산되도록하는 방법에는 딜레마가 있습니다. "로컬"메모리 버스. 인터페이스는 이식성이 없지만 대부분의 운영 체제에는 스레드 선호도를 설정하는 방법이 있습니다 (예 : pthread_setaffinity_np()많은 POSIX 시스템, sched_setaffinity()Linux, SetThreadAffinityMask()Windows). 메모리 계층을 결정하기위한 hwloc 과 같은 라이브러리도 있지만 불행히도 대부분의 운영 체제는 아직 NUMA 메모리 정책을 설정하는 방법을 제공하지 않습니다. libnuma 와 함께 Linux는 주목할만한 예외입니다 .응용 프로그램이 페이지 단위로 메모리 정책 및 페이지 마이그레이션을 조작 할 수 있도록합니다 (2004 년 이후의 주요 내용). 다른 운영 체제에서는 사용자가 암시적인 "첫 번째 터치"정책을 준수해야합니다.
"first touch"정책으로 작업한다는 것은 호출자가 새로 할당 된 메모리에 처음 쓸 때 나중에 사용하려는 선호도를 가진 스레드를 작성하고 분배해야 함을 의미합니다. ( malloc()실제로 페이지를 찾도록 구성되는 시스템은 거의 없으며 , 실제로는 다른 스레드에 의해 오류가 발생했을 때 해당 페이지를 찾도록 약속합니다.) 이는 사용 calloc()후 할당을 사용 하거나 즉시 메모리를 초기화 하는 할당 memset()은 결함이 있기 때문에 해롭다는 것을 의미합니다 할당 스레드를 실행하는 코어의 메모리 버스에있는 모든 메모리로 인해 여러 스레드에서 메모리에 액세스 할 때 최악의 메모리 대역폭이 발생합니다. new많은 새로운 할당을 초기화 해야하는 C ++ 연산자 에도 동일하게 적용됩니다 (예 :std::complex). 이 환경에 대한 몇 가지 관찰 :
- 할당은 "스레드 집합"으로 만들 수 있지만, 이제는 스레딩 모델에 할당이 혼합되어 다른 스레딩 모델을 사용하여 클라이언트와 상호 작용해야하는 라이브러리에는 바람직하지 않습니다 (각각 자체 스레드 풀이 있음).
- RAII는 관용적 C ++의 중요한 부분으로 여겨지지만 NUMA 환경에서 메모리 성능에 적극적으로 유해한 것 같습니다. 배치
new는를 통해 할당 된 메모리malloc()또는에서 루틴 과 함께 사용할 수libnuma있지만 할당 프로세스가 변경됩니다 (필요하다고 생각합니다). - 편집 : 연산자
new에 대한 내 이전 진술 이 잘못되었습니다. 여러 인수를 지원할 수 있습니다. Chetan의 답변을 참조하십시오. 라이브러리 또는 STL 컨테이너가 지정된 선호도를 사용하도록하는 데 여전히 우려가 있다고 생각합니다. 여러 필드가 압축 될 수 있으며, 예를 들어std::vector올바른 컨텍스트 관리자가 활성화 된 상태 에서 재 할당 되는 것이 불편할 수 있습니다 . - 각 스레드는 자체 개인 메모리를 할당하고 오류를 일으킬 수 있지만 인접 영역으로 인덱싱하는 것이 더 복잡합니다. (희소 행렬 - 벡터 제품 고려 매트릭스 및 벡터의 로우 격벽과;의 소유되지 않은 부분의 색인 더 복잡한 데이터 구조를 필요로하는 경우 가상 메모리에서 연속이 아니다.)
NUMA 할당 / 초기화에 대한 솔루션이 관용어로 간주됩니까? 다른 중요한 문제를 배제 했습니까?
(저는 C ++ 예제가 그 언어에 중점을 두는 것을 의미하지는 않지만 C ++ 언어 는 C와 같은 언어가 아닌 메모리 관리에 대한 일부 결정을 인코딩하므로 C ++ 프로그래머가 그렇게 할 것을 제안 할 때 더 많은 저항이있는 경향이 있습니다 상황이 다릅니다.)