2016-04-19 58 views
2

我寫了一個測試來說明我的問題,該代碼嘗試16個字節複製到無 - 4字節對齊的存儲空間,但DEST自動修改CUDA內存拷貝力對準

#include <cuda.h> 
#include <cuda_runtime.h> 
#include <stdio.h> 

__global__ 
void Copy128(char *dest,const char *src) 
{ 
    ((int*)dest)[0]=((int*)src)[0]; 
    ((int*)dest)[1]=((int*)src)[1]; 
    ((int*)dest)[2]=((int*)src)[2]; 
    ((int*)dest)[3]=((int*)src)[3]; 
} 
__global__ 
void fill_src(char *src) 
{ 
    for(int i=0; i<16; i++) 
     src[i] = i+1; // starts from 1 
} 

int main() 
{ 
    char* dest; 
    cudaMalloc(&dest, 17); 

    char* src; 
    cudaMalloc(&src, 16); 

    fill_src<<<1, 1>>>((char*)src); // fill some value for debugging 

    // copy to dest+1 which is not aligned to 4 
    Copy128<<<1, 1>>>(dest + 1, src); 

    getchar(); 
} 

在VS2013中調試代碼,如圖所示,目標內存爲0x40A8000 ,但實際上它複製到0x40A8000 。 enter image description here

問題是dest如果它沒有對齊到4字節會自動修改。它被無聲地修改,我花了幾個小時找到這個bug。我知道最好是使用良好對齊的內存,但我正在寫一些rar解壓縮程序,解壓縮一些字節,然後連接一些字節,它不能總是對齊。

我想我會使用uint64像Copy256一樣的功能。這是正常行爲,內存是力量對齊?任何可以關閉此功能的編譯標誌?或者我應該一個接一個地複製字節?

環境:CUDA 6.5,Win7-32​​bit,VS2013

+5

當我運行您的示例代碼時,由於未對齊的內存訪問,在Copy128內核中出現非法寫入錯誤,這正是應該發生的情況。我不明白你在這裏試圖做什麼 – talonmies

+4

除了x86 CPU之外,GPU上的所有內存訪問必須自然對齊,即與訪問的大小對齊,例如, 4字節訪問必須與4字節邊界對齊。所以在GPU上,內存訪問的這種對齊對於*功能正確性*是必要的,而不僅僅是在x86上的性能。這在CUDA文檔中提到。對於未對齊的副本,您無需逐個字節地複製較大的對象,只需對最終案例使用較窄的訪問權限,並將大量副本用於大部分傳輸。 – njuffa

回答

4

- 這是正常的行爲,該內存的力對齊? 是:引自here,「駐留在全局內存中或由驅動程序或運行時API的內存分配例程之一返回的變量的任何地址總是對齊至少256個字節」。

任何可以關閉此功能的編譯標誌? 我想不會,這可能是與硬件相關的

還是應該由一個複製字節一個? 如果你處理(非常)未對齊的內存,這是你唯一的選擇,以避免錯位的商店(如上面評論)。 但是,您應該嘗試在編譯時或運行時檢測內存操作是否對齊,然後使用手頭最寬的加載/存儲(int4會導致ldg指令,這會提供更好的方法帶寬)