2014-01-27 4 views
0

많은 데이터를 처리하는 CUDA 커널이 있습니다. 모든 데이터를 한꺼번에 전송할 수 없으므로 데이터를 청크로 분할하여 청크로 처리하고 GPU에서 출력을 업데이트해야합니다. 파일에서 입력 데이터를 구문 분석하고 있습니다. 호스트와 GPU에서 두 개의 버퍼를 사용하여 청크의 메모리 전송을 오버랩 할 수 있다고 생각했습니다. 하나의 척을 처리하는 동안 다른 것을 읽고 GPU로 전송하고 커널을 같은 스트림으로 시작할 수있었습니다. 내 문제는 커널의 실행 시간이 데이터를 구문 분석하고 GPU로 전송하는 것보다 느리다는 것입니다. 어떻게하면 memcpys가 memcpys가 블로킹이되지 않는다는 사실에 따라 커널이 사용하는 데이터를 덮어 쓰지 않게 할 수 있습니까?cuda에서 메모리 계산 중복 문제

//e.g. Pseudocode 
//for every chunk 
    //parse data 
    //cudaMemcpyAsync (dev, host, size, H2D) 
    //launch kernel 
    //switch_buffer 
//copy result from device to host 

감사합니다.

+1

언제든지 동일한 메모리를 재사용하지 않고 버퍼를 전환하지 않으려면이 [웹 세미나] (http://on-demand.gputechconf.com/gtc- Express/2011/프레젠테이션/StreamsAndConcurrencyWebinar.pdf). 가능성은 부식에 대응하는 memcpy와 커널 출시 쌍마다 서로 다른 스트림을 사용하는 것입니다. 또한 고정 된 메모리를 사용해야합니다! 의사 코드에서 사용 된 cuda 스트림은'cudaMemcpyAsync'에도 없습니다. – hubs

답변

0

커널 시작 후 명시적인 동기 점을 cudaDeviceSynchronize()으로 삽입하십시오.

그런 식으로 본질적으로 메모리 전송을 시작하고 동시에 커널을 시작합니다. 전송은 하나의 버퍼로 가고 커널은 다른 버퍼에서 작동합니다. cudaDeviceSynchronize()는 두 가지 작업이 완료 될 때까지 기다렸다가 버퍼를 교체하고 반복합니다.

물론 루프 내의 장치에서 호스트로 결과를 복사하고 커널이 처리 할 데이터가 없을 때 첫 번째 반복을 처리하는 논리를 추가해야하며 마지막 반복이 필요합니다. 더 이상 복사 할 데이터는 없지만 하나의 버퍼가 처리됩니다. 루프의 논리를 사용하거나 루프의 일부를 풀어 첫 번째 및 마지막 반복을 구체적으로 코딩 할 수 있습니다.

편집 :

그냥 읽고 구문 분석 cudaMemcpyAsync() 전에 파일 후 동기화 지점을 이동함으로써, 당신은 (커널이 충분히 실행하는 경우) 커널은 또한 처리의 일부를 중복 할 수 있도록 .

+0

나는 이것을 cudaDeviceSynchronize로 구현했지만, 시간이 걸리므로 그것을 피하고 싶었다. 그럼에도 불구하고 나는 내가 원하는 것을 보장 할 수있는 다른 방법을 찾을 수 없다. 고맙습니다. – user2117698

+0

@ user2117698, Roger가 설명하는대로 이중 버퍼링하면 시간이 많이 걸리지 않습니다. 잠재적 인 속도 향상은 작업 부하가 전송과 계산 사이에 균등하게 분산되는 방식으로 제한됩니다. 두 개의 버퍼가 충분히 크다면, 커널 시작과 memcpy를 숨기는 오버 헤드가 숨겨 질 것이고, 성능은 자연스럽게 전송/처리 제한 범위에 달할 것입니다. – ArchaeaSoftware

관련 문제