2012-06-14 2 views
4

제목에서 알 수 있듯이 실제로 두 개의 OpenCL 버퍼를 효과적으로 교환하는 방법을 찾고 있습니다. 커널은 두 개의 gloabl 버퍼를 사용하는데 하나는 입력으로, 다른 하나는 출력으로 사용됩니다. 그러나 커널 인자를 설정할 때마다 같은 NDRange를 사용하여 for 루프에서 커널을 호출하고 커널을 대기열에 넣으며 이전 출력 버퍼가 다음 반복의 입력 버퍼 시드가 될 것이기 때문에 버퍼를 교체합니다.OpenCL 메모리 버퍼를 효과적으로 바꾸는 방법은 무엇입니까?

여기서 두 가지 버퍼를 바꾸려면 적절한 방법은 무엇입니까? 이미 버퍼를 호스트에 복사하여 이미 malloc 된 배열 중 하나에 복사하고 clEnqueueWriteBuffer()clEnqueueReadBuffer()을 사용하여 다음 입력 버퍼에 복사하는 것이 비효율적 인 방법이라고 생각합니다. 그렇지 않으면 임시 교환변수를 사용하고 있습니다.

답변

10

커널을 다시 대기열에 넣기 전에 올바른 커널 인수를 clSetKernelArg으로 설정하기 만하면됩니다 (clEnqueueNDRangeKernel 사용). 버퍼는 장치에 남고 아무 것도 호스트로 다시 복사되지 않습니다.

이 경우 물론 버퍼는 CL_MEM_READ_WRITE으로 만들어야합니다.

+0

글쎄, 나는 그것에 대해 생각했다. 하지만 모든 반복을 입력 및 출력 커널 args 대체해야 할 것이라고 보인다? – voxeloctree

+2

예 - 가능합니다. 스왑하고 각 반복마다 설정하십시오. 이것은 핑퐁 (ping-ponging)입니다. (http://www.mathematik.uni-dortmund.de/~goeddeke/gpgpu/tutorial.html#feedback2) – Ani

+0

글쎄, 나는 그것에 대해 확실히 생각했다. 하지만 미안, 내 질문에 명확하게하지 않았다면. "두 번째 시간"은 두 번 의미합니다. 수백만이 아닙니다. 그렇지 않으면 방대한 병렬 처리의 요점은 무엇입니까? 둘 다 감사합니다. – voxeloctree

1

이전 대답 : 아니요, 버퍼를 전혀 교환 할 필요가 없습니다.

그러나 제안 된 답변에 동의하지 않습니다. clSetKernelArg()은이 아니며 이며 스레드 루프가 아니며 작업 루프에서 호출하도록 설계되지 않았습니다.

적절한 해결책은 동일한 프로그램과 소스로 생성 된 2 개의 커널을 만드는 것입니다. 이 접근 방식은 OpenCL 프로그래밍 철학 "하나의 작업에 대해 하나의 커널"과 더욱 일치합니다. 동일한 코드이지만 다른 인수를 가진 많은 커널을 갖는 것이 갈 길이 있습니다.

kernel1 = clCreateKernel(program, "mykernel", NULL); 
clSetKernelArg(kernel1, 0, &buff1); 
clSetKernelArg(kernel1, 1, &buff2); 

을 그리고 다른 하나는 다음과 같습니다 :

첫 번째 커널은있을 것이다

kernel2 = clCreateKernel(program, "mykernel", NULL); 
clSetKernelArg(kernel2, 0, &buff2); 
clSetKernelArg(kernel2, 1, &buff1); 

이 방법, 당신은 실행 각 반복을 중지 할 필요가 없습니다. 다음과 같이 간단하게 실행할 수 있습니다 :

for(int it=0; it<iter; it++){ 
    clEnqueueNDRangeKernel(it%2 ? kernel1 : kernel2, ....); 
} 
clFinish(command); 

이 방법은 커널 인수를 변경하는 것보다 효율적이며 적은 API 호출을 변경하는 것보다 낫습니다. 또한 일부 시스템에서는 API 구현이 잘못되어 clSetKernelArgs()이 차단 호출 일 수 있습니다. 따라서 가능한 한 많이 피하는 것이 좋습니다.

+1

내가 동의하는 동안 clSetKernelArg는 thread 세이프가 아니므로, "이전에 완료하지 않고 다음 반복을 실행하지 못하게합니다"라는 문장은 올바르지 않습니다. 일단 clEnqueueNDRangeKernel을 호출하면 모든 매개 변수가 복사되므로 모든 항목을 즉시 설정할 수 있습니다. 커널을 큐에 넣은 직후에. – alariq

+0

답변을 업데이트했습니다.맞습니다. 99 %의 사용 가능한 플랫폼이 블로킹하지 않고 오래된 드라이버 만 사용하거나 잘못 구현 된 클 래스는'clSetKernelArgs()'를 블로킹합니다. – DarkZeros

관련 문제