[英]CUDA cudaMemcpy, an illegal memory access was encountered
我對 cuda 還很陌生,我想使用常量 memory 的概念,但是在運行代碼時遇到了非法的 memory 訪問。
我的 kernel 看起來像這樣
__global__ void nonceKernel(int inLen, int shaTermLength, BYTE* outSha1, BYTE* outNonce, int nonceLen, int* finishedFlag, int *mutex, int size)
{
if(!*finishedFlag) return;
unsigned int tid = blockIdx.x * blockDim.x + threadIdx.x;
bool found = true;
BYTE tempNonce[2];
BYTE tempSha1[20];
tempNonce[1]=((tid+size) >> 8) & 0x000000FF;
tempNonce[0]=(tid+size) & 0x000000FF;
CUDA_SHA1 ctx;
cuda_sha1_init(&ctx); //init context
cuda_sha1_update(&ctx, device_input_data, inLen); // add input buffer
cuda_sha1_update(&ctx, tempNonce, nonceLen); //add nonce
cuda_sha1_final(&ctx, tempSha1); //compute sha1
for(int i=0; i<shaTermLength; i++) {
if(tempSha1[19 - i] != device_sha1_term[shaTermLength - 1 - i])
found=false;
}
if(found == true) {
lock(mutex);
memcpy(outSha1, tempSha1, 20); //20 bytes for sha1
memcpy(outNonce, tempNonce, nonceLen); //2 bytes for nonce
*finishedFlag = 0;
unlock(mutex);
}
}
我的中介 function 是這樣的:
cudaError_t nonceWithCuda(int intlen, int shaTermLength, BYTE* outSha1, BYTE* outNonce, int *finishFlag, int nonceLen, int size)
{
BYTE *gpuSha1Out;
BYTE *gpuNonceOut;
int *gpuFinishedFlag;
cudaError_t cudaStatus;
int *mutex;
cudaStatus= cudaSetDevice(0);
if(cudaStatus != cudaSuccess) {
fprintf(stderr, "cudaSetDevice failed! Do you have a cuda gpu installed?");
goto Error;
}
....
cudaStatus=cudaMalloc((void**)&gpuFinishedFlag, 1*sizeof(int));
if(cudaStatus != cudaSuccess) {
fprintf(stderr, "cudaMalloc for gpuFinishedFlag failed");
goto Error;
}
cudaStatus=cudaMemcpy(gpuFinishedFlag, finishFlag, sizeof(int), cudaMemcpyHostToDevice);
if(cudaStatus!=cudaSuccess) {
fprintf(stderr, "cudamemcpy 0 to gpuFinishedFlag failed!");
goto Error;
}
....
while(*finishFlag) {
nonceKernel<<<128, 1024>>>(intlen, shaTermLength, gpuSha1Out, gpuNonceOut, nonceLen, gpuFinishedFlag, mutex, size);
size++;
cudaStatus=cudaMemcpy(finishFlag, gpuFinishedFlag, sizeof(int), cudaMemcpyDeviceToHost);
if(cudaStatus!=cudaSuccess) {
fprintf(stderr, "cudaMemcpy from gpuFinishedFlag failed, with code: %s!", cudaGetErrorString(cudaStatus));
goto Error;
}
}
......
Error:
cudaFree(gpuSha1Out);
cudaFree(gpuNonceOut);
cudaFree(gpuFinishedFlag);
return cudaStatus;
}
我也這樣聲明常量變量:
__constant__ BYTE* device_input_data;
__constant__ BYTE* device_sha1_term;
其中 BYTE 定義為 unsigned char typedef unsigned char BYTE;
.
最后是主function。
int main(int argc, char** argv) {
size_t input_block_size=5; //bytes
int nonceLen=2;
int finishedFlag=1;
...
BYTE* inputData = (BYTE*) malloc(input_block_size * sizeof(BYTE)); //input byte buffer
inputData[0]=0x23; //#
inputData[1]=0x30; //0
inputData[2]=0x42; //B
inputData[3]=0x69; //i
inputData[4]=0x61; //a
BYTE* shaTerm = (BYTE*) malloc(nonceLen * sizeof(BYTE));
shaTerm[0]=0x7E;
shaTerm[1]=0x46;
int shaTermLength = sizeof(shaTerm)/sizeof(shaTerm[0]);//ouput sha buffer
cudaStatus=cudaMemcpyToSymbol(device_input_data, inputData, input_block_size * sizeof(BYTE), 0, cudaMemcpyHostToDevice);
fprintf(stderr, "MemcpyToSymbol: %s\n", cudaGetErrorString(cudaStatus));
cudaStatus=cudaMemcpyToSymbol(device_sha1_term, shaTerm, shaTermLength * sizeof(BYTE), 0, cudaMemcpyHostToDevice);
fprintf(stderr, "MemcpyToSymbol: %s\n", cudaGetErrorString(cudaStatus));
...
nonceWithCuda(input_block_size, shaTermLength, outputSha1Buffer, outputNonceBuffer, &finishedFlag, 2, size);
當我將值從 gpu 復制回主機時,從 nonceWithCuda function 中發生錯誤,我的意思是這段代碼:
cudaStatus=cudaMemcpy(finishFlag, gpuFinishedFlag, sizeof(int), cudaMemcpyDeviceToHost);
if(cudaStatus!=cudaSuccess) {
fprintf(stderr, "cudaMemcpy from gpuFinishedFlag failed, with code: %s!", cudaGetErrorString(cudaStatus));
goto Error;
}
output:
$ ./nonce_v3
MemcpyToSymbol: no error
MemcpyToSymbol: no error
cudaMemcpy from gpuFinishedFlag failed, with code: an illegal memory access was encountered!
請注意,當我沒有對這兩個變量使用常量並且無法理解原因時,相同的代碼可以正常工作。 有人可以指出我正確的方向嗎?
謝謝您的幫助!!!
我假設您想將inputData
的 5 個元素存儲在常量 memory 中。
__constant__ BYTE* device_input_data;
將保留常量 memory 以存儲單個指針。 它不會為 5 BYTE 值保留常量 memory。
然后,與
cudaMemcpyToSymbol(device_input_data, inputData, input_block_size * sizeof(BYTE), 0, cudaMemcpyHostToDevice);
該指針指向的 memory 地址設置為 inputData 的元素,即在傳輸后,指針的值可能為0x2330426961000000
。 這很可能不是設備 memory 的有效地址。 當嘗試訪問 kernel 中的此 memory 位置時,這會導致觀察到的 memory 錯誤。
要解決此問題,您需要將常量 memory 聲明為大小為 5 的 BYTE 數組。
__constant__ BYTE device_input_data[5];
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.