2013-08-27 29 views
1

我一直在JCuda工作幾個月,我無法將多維數組從設備內存複製到主機內存。有趣的是,我在相反的方向上沒有問題(我可以用多維數組調用我的內核,並且所有東西都可以使用正確的值)。JCuda:將多維數組從設備複製到主機

簡而言之,我把我的內核的結果放在一個二維短褲數組中,這樣的數組的第一個維度就是線程的數量,這樣每個人都可以在不同的位置寫入數據。

下面的例子:

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工具包v5.0

+0

至少有2點可能的問題。一個是你所說的,用'malloc'或'new'等設備函數分配的內存不能直接複製到主機。與複製包含指向其他動態分配數據的動態分配數據相關的各種挑戰也存在,並且圍繞SO也有許多問題。不幸的是,我對java或JCUDA語法不夠熟悉,爲的是告訴你如何解決這個問題。 –

+0

對於您發佈的編輯問題,可能的解決方法是將設備分配的區域中的數據複製回主機,然後將其複製到設備代碼中的主機分配區域。 –

+0

謝謝,那也是我所做的。但是問題依然存在:在內核計算之前,主機分配區域的大小是固定的,我無法預先確定輸出的維度。現在我已經決定建立一個足夠大的固定大小,以適應大多數情況,但我認爲這不是一個「好」的解決方案。 – Rorrim

回答

2

在這裏,我們正在複製從設備到主機的int二維數組。 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);

IV)從設備傳送輸出到主機

  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]; 
      } 
相關問題