2011-12-30 6 views
24

소량의 전체 메모리 (20M 미만)를 할당하는 CUDA 프로그램을 실행할 때 "메모리 부족"오류가 발생합니다. (다른 사람들의 게시물에서이 문제는 메모리 단편화와 관련이 있다고 생각합니다.)이 문제를 이해하려고 노력하며 CUDA 메모리 관리와 관련된 몇 가지 질문이 있다는 것을 알고 있습니다.CUDA 메모리는 어떻게 관리됩니까?

  1. CUDA에는 가상 메모리 개념이 있습니까?

  2. 하나의 커널 만 CUDA에서 동시에 실행할 수있는 경우 종료 후 사용 중이거나 할당 된 모든 메모리가 해제됩니까? 그렇지 않다면,이 메모리가 무료로 출시되었을 때?

  3. CUDA에서 둘 이상의 커널을 실행할 수 있다면, 그들이 사용하는 메모리가 겹치지 않는 것을 어떻게 확인할 수 있습니까?

누구나 내가이 질문에 답할 수 있도록 도와 줄 수 있습니까? 감사합니다

편집 1 : 운영 체제 : x86_64에 GNU/리눅스 CUDA 버전 : 4.0 장치 : 지포스 200, 그것은 기계에 부착 된 GPU를 하나이며, 나는 그것이 디스플레이 장치라고 생각하지 않습니다.

편집 2 다음은 몇 가지 조사를 한 후에 얻은 것입니다. 저를 시정 해주십시오.

  1. CUDA는 각 호스트 스레드에 대해 하나의 컨텍스트를 생성합니다. 이 컨텍스트는 다른 응용 프로그램이이 응용 프로그램에 쓸 수 없도록이 응용 프로그램에 예약 된 메모리 (사전 할당 메모리 또는 동적 할당 메모리)와 같은 정보를 유지합니다. 이 응용 프로그램이 종료되면 (커널 아님)이 메모리 부분이 해제됩니다.

  2. CUDA 메모리는 링크 목록에 의해 유지됩니다. 응용 프로그램에서 메모리를 할당해야하는 경우이 링크 목록을 통해 할당 할 수있는 연속적인 메모리 청크가 있는지 확인합니다. 이러한 청크를 찾지 못하면 사용 가능한 총 메모리 크기가 요청 된 메모리보다 큰 경우에도 "메모리 부족"오류가 사용자에게보고됩니다. 이것이 메모리 단편화와 관련된 문제입니다.

  3. cuMemGetInfo는 얼마나 많은 메모리가 비어 있는지 알려주지 만, 메모리 조각화로 인해 최대 할당량에 할당 할 수있는 메모리 양은 아닙니다.

  4. Vista 플랫폼 (WDDM)에서 GPU 메모리 가상화가 가능합니다. 즉, 여러 응용 프로그램이 거의 모든 GPU 메모리를 할당 할 수 있으며 WDDM이 스왑 데이터를 주 메모리로 다시 관리합니다.

새로운 질문 : 응용 프로그램이 종료 된 후 상황에 예약 된 메모리가 완전히 해제 될 경우 1., 메모리 단편화가 존재하지 않아야합니다. 메모리에 어떤 종류의 데이터가 남아 있어야합니다. 2. GPU 메모리를 재구성 할 수있는 방법이 있습니까?

+0

질문을 편집하여 사용중인 운영 체제, GPU 및 cuda 버전, GPU가 디스플레이 장치인지 비 표시 장치인지를 포함 할 수 있습니까? 그것은 당신의 질문에 대한 정답에 관계 될 것입니다. – talonmies

+0

추가 질문에 대답하려면 - 사용자가 관찰 할 수있는 조각화가 컨텍스트 내에서 발생합니다 *. GPU 내에서 메모리 매핑을 변경하는 방법이 없으며 모두 호스트 드라이버에서 처리합니다. – talonmies

+0

설명대로 컨텍스트 할당은 컨텍스트 정적 할당, 컨텍스트 사용자 할당 및 CUDA 컨텍스트 런타임 힙으로 구성됩니다. 컨텍스트 정적 할당 및 컨텍스트 사용자 할당의 크기가 미리 결정된 것 같습니다. 따라서 메모리 조각화의 유일한 원인은 Fermi 아키텍처에만있는 컨텍스트 런타임 힙 (heap)이라고 생각합니다. 그 맞습니까? 나는 시스템이 컨텍스트 런타임 힙 (heap)을위한 메모리 덩어리를 미리 할당하여 커널 내부 동적 메모리 할당을 가능하게 할 것으로 생각한다. – xhe8

답변

24

런타임에 코드를 사용할 수있는 장치 메모리가 기본적으로

Free memory = total memory 
       - display driver reservations 
       - CUDA driver reservations 
       - CUDA context static allocations (local memory, constant memory, device code) 
       - CUDA context runtime heap (in kernel allocations, recursive call stack, printf buffer, only on Fermi and newer GPUs) 
       - CUDA context user allocations (global memory, textures) 

당신이 메모리 메시지의 출력을 얻는 경우로 계산, 그것은 가능성이 처음 세 항목 중 하나 이상이 사용자 코드가 GPU에서 메모리를 얻으려고하기 전에 대부분의 GPU 메모리를 소비합니다. 표시 한대로 디스플레이 GPU에서 실행하고 있지 않으면 컨텍스트 정적 할당이 문제의 가장 큰 원인 일 수 있습니다. CUDA는 컨텍스트가 디바이스에 설정 될 때 컨텍스트가 요구하는 모든 메모리를 사전 할당함으로써 작동합니다. 컨텍스트를 지원하기 위해 할당되는 많은 것들이 있지만 컨텍스트에서 가장 큰 단일 소비자는 로컬 메모리입니다. 이 장치의 각 다중 프로세스에 대해 각 다중 프로세서가 동시에 실행할 수있는 최대 스레드 수에 대해 컨텍스트의 커널이 소비하는 최대 로컬 메모리 양을 예약해야합니다. 멀티 프로세서가 많은 장치에 로컬 메모리 무거운 커널이로드되는 경우 수백 메가의 메모리로 실행될 수 있습니다.

무슨 일이 벌어지는지를 확인하는 가장 좋은 방법은 컨텍스트를 설정하고 cudaMemGetInfo을 호출하는 장치 코드가없는 호스트 프로그램을 작성하는 것입니다. 그러면 컨텍스트 오버 헤드를 최소화하면서 장치의 메모리 용량을 알 수 있습니다. 그런 다음 문제가되는 코드를 실행하고 cudaMemGetInfo 호출을 먼저 호출 한 후 cudaMalloc 호출을 호출하면 컨텍스트가 사용하는 메모리 양이 줄어 듭니다. 그러면 메모리가 어디로 향하는지를 처리 ​​할 수 ​​있습니다. 첫 번째 cudaMalloc 호출에서 오류가 발생하는 경우 조각화가 문제가되는 것은 거의 없습니다.

+0

귀하의 정보를 주셔서 감사합니다. 그것은 매우 도움이됩니다. 또 하나의 질문은 장치 메모리에 다중 컨텍스트가 존재할 가능성이 있습니까? – xhe8

+0

예, 가능하지만 특정 스레드는 주어진 장치에서 단일 컨텍스트를 보유 할 수만 있습니다. 일반적인 시나리오는 동일한 GPU에서 동시에 실행하려고하는 두 프로세스이거나 두 스레드로 두 개의 컨텍스트를 여는 다중 스레드 응용 프로그램입니다. 후자는 이전보다 CUDA 4에서 훨씬 더 어렵습니다. – talonmies

+0

그러면 다중 컨텍스트에 대해 메모리를 할당하는 데 어떤 메커니즘이 사용됩니까? 시스템이 다른 컨텍스트에 다른 부분의 메모리가 할당되도록하려면 어떻게해야합니까? – xhe8

4
  1. GPU 오프 - 칩 메모리는 글로벌, 로컬 및 상수 메모리로 분리되어 있습니다. 이 세 가지 메모리 유형은 가상 메모리 개념입니다. 전역 메모리는 모든 쓰레드에서 사용 가능하며, 로컬은 단지 하나의 쓰레드 (레지스터 누수에 주로 사용됨)이고 상수 메모리는 캐시 된 전역 메모리 (호스트 코드에서만 쓰기 가능)입니다. CUDA C 프로그래밍 가이드에서 5.3.2를보십시오.

  2. 편집 : 제거

  3. 메모리는 중복하지 않는 cudaMalloc를 통해 할당. 런타임 동안 커널이 할당하는 메모리는 충분한 메모리가 있어야합니다. 메모리가 부족하여 커널을 시작하려고하면 ("나만 추측합니다") "알 수없는 오류"라는 오류 메시지가 나타납니다. 드라이버가 커널을 시작 및/또는 실행할 수 없습니다.

+0

답장을 보내 주셔서 감사합니다. 그러나 나는 더 낮은 수준의 설명을 원한다고 생각한다. CUDA 메모리 관리에는 컨텍스트와 일부 데이터 구조를 다룰 수있는 뭔가가 있다는 것을 다른 게시물에서 알았지 만, 프로그램에서 메모리 문제를 파악할 수 있도록 더 많은 설명을하고 싶습니다. – xhe8

+0

두 번째 대답은 대부분 잘못되었습니다. 커널 스코프 메모리는 장치에 컨텍스트가 설정 될 때 미리 할당됩니다 *. 로컬 메모리의 내용은 커널 실행 기간 동안 만 유효하지만 메모리 자체는 컨텍스트가 설정 될 때 예약됩니다. 동적 메모리는 컨텍스트 설정 시간에 예약 된 런타임 힙에서 할당되며 커널이 아닌 컨텍스트의 수명 동안 액세스 가능하고 유효합니다. 필요한 경우 기본 크기에서 런타임시 힙 크기를 조작하기위한 API 호출이 있습니다. – talonmies

+0

@ talonmies 고쳐 주셔서 감사합니다 –

관련 문제