在我的程序中,我必須生成大量的隨機數。因此,我嘗試重用cuRAND狀態,這樣我就只需要初始化它們一次。不幸的是,執行初始化的代碼會產生奇怪的內存訪問錯誤。我花了很多時間調試它,並且只有當我將'curand_init()'的參數'sequence'設置爲一個很大的值(例如30000)或者當參數'seed'變得太大時,錯誤纔會發生。 用下面的代碼我能夠重現錯誤:curand_init()產生內存訪問錯誤
#include <conio.h>
#include <stdio.h>
#include <curand.h>
#include <curand_kernel.h>
#include "cuda_runtime.h"
#include "device_launch_parameters.h"
__global__ void initRnd(unsigned long long seed, curandState* states, int size)
{
int id = blockIdx.x * blockDim.x + threadIdx.x;
if (id < size) {
curand_init(seed, id, 0, &states[id]);
}
}
void handleError(cudaError_t code)
{
if (code != cudaSuccess) {
printf("ERROR: %s (Code: %d) %s %d\n", cudaGetErrorString(code), code, __FILE__, __LINE__);
exit(code);
}
}
int main()
{
const int size = 3000000;
cudaError_t code = cudaSetDevice(0);
handleError(code);
curandState *data;
code = cudaMalloc((void**)&data, size * sizeof(curandState));
handleError(code);
const int blockSize = 256;
int numOfBlocks = (size + blockSize - 1)/blockSize;
dim3 dimGrid(numOfBlocks);
dim3 dimBlock(blockSize);
initRnd << <dimGrid, dimBlock >> > (time(0), data, size);
code = cudaDeviceSynchronize();
handleError(code);
code = cudaDeviceReset();
handleError(code);
printf("\nPress any key...\n");
_getch();
}
當我運行這個使用CUDA-MEMCHECK它提供unpredictible結果,有時我的計算機崩潰。
的誤差消失當我設置curand_init的序列參數爲0:
curand_init(seed, 0, 0, &states[id]);
由於其導致具有在所有的線程相同的序列我試圖線程ID添加到種子值:
curand_init(seed+id, 0, 0, &states[id]);
但是當「身份證」包含高值的錯誤再次出現。
我對cuda編程頗爲陌生,如果我做錯了什麼,或者如果這是cuRAND中的一個錯誤,我應該向NVidia申請,我不確定。
任何人都可以幫忙嗎?
更新:
要檢查這是否是我的程序中的錯誤或某處CUDA中我使用第3.6章的第一個例子。 (「設備API示例」,參見cuRAND Programming Guide)。它也會在cuda-memcheck中產生內存訪問衝突。所以我猜想它可能是cuRAND或內存檢查器中的錯誤。有人可以驗證這一點嗎?有人能夠毫無錯誤地運行cuda-memcheck的例子嗎?
btw:即使使用其他cuRAND生成器(如curandStatePhilox4_32_10_t或curandStateMRG32k3a)也存在此問題。
更新2
這不是CUDA-MEMCHECK,報告虛假錯誤。這是Nsights開啓了memcheck選項。它似乎與cuRAND無關。即使在一些簡單的cuda示例中,Nsight也會報告內存訪問錯誤。對不起,上面的文字中有誤導性的信息。
看來你是在窗戶上。這可能只是用於大尺寸內核網格的WDDM TDR。 –
沒錯。我在窗戶上。但TDR在我的機器上關閉。 –
我在linux/CUDA8/K20x上運行你的代碼。它運行良好,有或沒有'cuda-memcheck'。但是,使用'cuda-memcheck'需要非常長的時間才能運行。 –