我寫了一個測試來說明我的問題,該代碼嘗試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 。
問題是dest如果它沒有對齊到4字節會自動修改。它被無聲地修改,我花了幾個小時找到這個bug。我知道最好是使用良好對齊的內存,但我正在寫一些rar解壓縮程序,解壓縮一些字節,然後連接一些字節,它不能總是對齊。
我想我會使用uint64像Copy256一樣的功能。這是正常行爲,內存是力量對齊?任何可以關閉此功能的編譯標誌?或者我應該一個接一個地複製字節?
環境:CUDA 6.5,Win7-32bit,VS2013
當我運行您的示例代碼時,由於未對齊的內存訪問,在Copy128內核中出現非法寫入錯誤,這正是應該發生的情況。我不明白你在這裏試圖做什麼 – talonmies
除了x86 CPU之外,GPU上的所有內存訪問必須自然對齊,即與訪問的大小對齊,例如, 4字節訪問必須與4字節邊界對齊。所以在GPU上,內存訪問的這種對齊對於*功能正確性*是必要的,而不僅僅是在x86上的性能。這在CUDA文檔中提到。對於未對齊的副本,您無需逐個字節地複製較大的對象,只需對最終案例使用較窄的訪問權限,並將大量副本用於大部分傳輸。 – njuffa