2013-08-27 5 views
1

저는 몇 달 동안 JCuda를 사용 해왔고 장치 메모리에서 호스트 메모리로 다차원 배열을 복사 할 수 없습니다. 재미있는 점은 반대 방향으로는 아무런 문제가 없다는 것입니다 (다차원 배열로 커널을 호출 할 수 있고 모든 것이 올바른 값으로 작동 함).JCuda : 장치에서 호스트로 다차원 배열을 복사하십시오.

몇 마디로 말해, 커널의 결과를 2 차원 배열의 단락에 넣었습니다.이 배열의 첫 번째 차원은 스레드의 수로, 서로 다른 위치에 쓸 수 있습니다. 여기

예 : 내가 잘못 뭐하는 거지

CUdeviceptr pointer_dev = new CUdeviceptr(); 
cuMemAlloc(pointer_dev, Sizeof.POINTER); // in this case, as an example, it's an array with one element (one thread), but it doesn't matter 

// Invoke kernel with pointer_dev as parameter. Now it should contain some results 

CUdeviceptr[] arrayPtr = new CUdeviceptr[1]; // It will point to the result 
arrayPtr[0] = new CUdeviceptr(); 
short[] resultArray = new short[3]; // an array of 3 shorts was allocated in the kernel 

cuMemAlloc(arrayPtr[0], 3 * Sizeof.SHORT); 
cuMemcpyDtoH(Pointer.to(arrayPtr), pointer_dev, Sizeof.POINTER); // Its seems, using the debugger, that the value of arrayPtr[0] isn't changed here! 
cuMemcpyDtoH(Pointer.to(resultArray), arrayPtr[0], 3 * Sizeof.SHORT); // Not the expected values in resultArray, probably because of the previous instruction 

?

편집 : link

하나를 : 분명히

이에 명시된 (그리고 더 많은) 스레드로 장치에 할당 된 메모리가 다시 호스트로 복사 할 수 없습니다 몇 가지 제한 사항이 있습니다 해결 방법은 무엇입니까? 나는 CUDA Toolkit v5.0을 사용하고 있습니다.

+0

호스트 장치로부터 출력 전송

IV)는 적어도 2 개의 가능한 문제점이있다. 'malloc' 또는'new'와 같은 장치 기능을 사용하여 할당 된 메모리는 호스트에 직접 복사 될 수 없다고 진술 한 것이 하나 있습니다. 동적으로 할당 된 데이터를 복사하는 것과 관련된 여러 가지 문제가 있으며 동적으로 할당 된 다른 데이터에 대한 포인터가 포함되어 있습니다. 그 외에도 많은 문제가 있습니다. 불행히도이 문제를 해결하는 방법을 정확하게 알려주려면 Java 또는 JCUDA 구문에 익숙하지 않습니다. –

+0

게시하는 편집 질문에 대한 가능한 해결책은 호스트에 다시 복사하기 전에 장치 코드에서 장치 할당 영역의 데이터를 장치 코드의 호스트 할당 영역으로 복사하는 것입니다. –

+0

고마워, 그게 내가 한 짓이야. 하지만 문제는 지속됩니다. 호스트 할당 영역의 크기는 커널 계산 전에 고정되어 있으며 결과물의 크기를 미리 결정할 방법이 없습니다. 현재로서는 대부분의 경우 작동 할만큼 충분히 큰 고정 된 크기를 만들기로 결정했으나 좋은 해결책은 아닙니다. – Rorrim

답변

2

여기서 우리는 장치에서 호스트로 int의 2 차원 배열을 복사하고 있습니다.

I) 먼저 다른 차원 배열의 크기와 동일한 [여기서는 blockSizeX] 크기의 단일 차원 배열을 만듭니다.

 CUdeviceptr hostDevicePointers[] = new CUdeviceptr[blockSizeX]; 
     for (int i = 0; i < blockSizeX; i++) { 
      hostDevicePointers[i] = new CUdeviceptr(); 
      cuMemAlloc(hostDevicePointers[i], size * Sizeof.INT); 
     } 

II) 상기 다른 배열 가리킨 호스트로부터 디바이스 배열 포인터를 복사 포인터들의 어레이에 대해 디바이스 메모리를 할당한다.

 CUdeviceptr hostDevicePointersArray = new CUdeviceptr(); 
     cuMemAlloc(hostDevicePointersArray, blockSizeX * Sizeof.POINTER); 
     cuMemcpyHtoD(hostDevicePointersArray, Pointer.to(hostDevicePointers),blockSizeX * Sizeof.POINTER); 

III) 시작 커널

kernelLauncher.call (........ hostDevicePointersArray);

  int hostOutputData[] = new int[ numberofelementsInArray * blockSizeX]; 
      cuMemcpyDtoH(Pointer.to(hostOutputData), hostDevicePointers[i], numberofelementsInArray * blockSizeX * Sizeof.INT); 
      for (int j = 0; j < size; j++) { 
       sum = sum + hostOutputData[j]; 
      }