2016-04-08 10 views
1

Cuda'da yeni ve bir küre üzerinde rastgele noktalar oluşturması gereken küçük bir kod yazmaya çalışıyorum. İşte kod. vektörlerde eleman sayısı daha az 4000 isecudaErrorIllegalAdress on cudaMemcpy

__global__ 
    void setup_kernel(curandStateMRG32k3a *state) 
    { 
     int id = threadIdx.x + blockIdx.x * blockDim.x; 
     curand_init(0, id, 0, &state[id]); 
    } 

    __global__ 
    void computeRandomVectors(float* x, float* y, float* z, unsigned int numberOfElements,curandStateMRG32k3a *state) 
    { 
     float a,b; 
     unsigned int i = blockDim.x * blockIdx.x + threadIdx.x; 
     curandStateMRG32k3a localState = state[i]; 
     if(i < numberOfElements) 
     { 
      a = curand_uniform(&localState); 
      b = curand_uniform(&localState); 
      while(a * a + b * b > 1.0f) 
     { 
      a = curand_uniform(&localState) * 2.0f - 1.0f; 
      b = curand_uniform(&localState) * 2.0f - 1.0f; 
     } 
      x[i] = 2.0f * a * sqrtf(1.0f - a * a - b * b); 
      y[i] = 2.0f * b * sqrtf(1.0f - a * a - b * b); 
      z[i] = 1.0f - 2.0f * (a * a + b * b); 
     } 
    } 

    void generatePointsOnASphere(thrust::host_vector<float>& h_x,  thrust::host_vector<float>& h_y, thrust::host_vector<float>& h_z) 
    { 
     if(h_x.size() != h_y.size() && h_x.size() != h_z.size()) 
     { 
      std::cout << "The three component vectors have unmatching size()" << std::endl; 
      return; 
     } 

     size_t size = h_x.size() * sizeof(float); 

     float* h_p_x = (float*) calloc(h_x.size(),sizeof(float)); 
     float* h_p_y = (float*) calloc(h_x.size(),sizeof(float)); 
     float* h_p_z = (float*) calloc(h_x.size(),sizeof(float)); 
     if(h_p_x==NULL || h_p_y==NULL || h_p_z==NULL) 
     { 
      std::cout << "Host memory allocation failure" << std::endl; 
      return; 
     } 

     float* d_p_x; 
     float* d_p_y; 
     float* d_p_z; 

    if(cudaMalloc((void **)&d_p_x,size) != cudaSuccess || 
    cudaMalloc((void **)&d_p_y,size) != cudaSuccess || 
    cudaMalloc((void **)&d_p_z,size) != cudaSuccess) 
    { 
     std::string errorString(cudaGetErrorName(cudaGetLastError())); 
     std::cout << errorString << std::endl; 
     std::cout << "Device memory allocation failure" << std::endl; 
     return; 
    } 
    curandStateMRG32k3a *devStates; 
    if(cudaMalloc((void **)&devStates, h_x.size() * sizeof(curandStateMRG32k3a)) != cudaSuccess) 
    { 
     std::string errorString(cudaGetErrorName(cudaGetLastError())); 
     std::cout << errorString << std::endl; 
     std::cout << "Random generator states memory allocation failure" << std::endl; 
     return; 
    } 

    int threads = 256; 
    dim3 grid = size/threads; 
    setup_kernel<<<grid,threads>>>(devStates); 

    if(cudaMemcpy(d_p_x,h_p_x,size,cudaMemcpyHostToDevice) != cudaSuccess || 
    cudaMemcpy(d_p_y,h_p_y,size,cudaMemcpyHostToDevice) != cudaSuccess || 
    cudaMemcpy(d_p_z,h_p_z,size,cudaMemcpyHostToDevice) != cudaSuccess) 
    { 
     std::string errorString(cudaGetErrorName(cudaGetLastError())); 
     std::cout << errorString << std::endl; 
     std::cout << "Host to Device memory copy failure" << std::endl; 
    } 

    computeRandomVectors<<< grid, threads >>>(d_p_x,d_p_y,d_p_z,size/sizeof(float), devStates); 

    if(cudaMemcpy(h_p_x,d_p_x,size,cudaMemcpyDeviceToHost) != cudaSuccess || 
    cudaMemcpy(h_p_y,d_p_y,size,cudaMemcpyDeviceToHost) != cudaSuccess || 
    cudaMemcpy(h_p_z,d_p_z,size,cudaMemcpyDeviceToHost) != cudaSuccess) 
    { 
     std::string errorString(cudaGetErrorName(cudaGetLastError())); 
     std::cout << errorString << std::endl;  
     std::cout << "Device to Host memory copy failure" << std::endl; 
    } 
    for(size_t i = 0; i < h_x.size(); ++i) 
    { 
     h_x[i] = h_p_x[i]; 
     h_y[i] = h_p_y[i]; 
     h_z[i] = h_p_z[i]; 
    } 

    free (h_p_x); 
    free (h_p_y); 
    free (h_p_z); 
    cudaFree (devStates); 
    cudaFree (d_p_x); 
    cudaFree (d_p_y); 
    cudaFree (d_p_z); 
    cudaDeviceReset(); 
} 

Bu kod çalışır (I 1K, 2K, 3K ve 4K çalıştı). Bu bana ilk cudaMemcpy cuda Hata Yasadışı Adresi verir. Hafızam tükendi sanmıyorum, ben gtx 980 (4GB global bellek) ile çalışıyorum. Bunu düzeltmek için bir fikrin var mı?


DÜZENLEME: Ben olsun düşünüyorum

__global__ 
void setup_kernel(curandStateMRG32k3a *state, unsigned int numberOfElements) 
{ 
    int id = threadIdx.x + blockIdx.x * blockDim.x; 
    if(id < numberOfElements) curand_init(0, id, 0, &state[id]); 
} 

__global__ 
void computeRandomVectors(float* x, float* y, float* z, unsigned int numberOfElements,curandStateMRG32k3a *state) 
{ 
    float a,b; 
    unsigned int i = blockDim.x * blockIdx.x + threadIdx.x; 
    curandStateMRG32k3a localState = state[i]; 
    if(i < numberOfElements) 
    { 
     a = curand_uniform(&localState); 
     b = curand_uniform(&localState); 
     while(a * a + b * b > 1.0f) 
    { 
     a = curand_uniform(&localState) * 2.0f - 1.0f; 
     b = curand_uniform(&localState) * 2.0f - 1.0f; 
    } 
     x[i] = 2.0f * a * sqrtf(1.0f - a * a - b * b); 
     y[i] = 2.0f * b * sqrtf(1.0f - a * a - b * b); 
     z[i] = 1.0f - 2.0f * (a * a + b * b); 
    } 
} 

void generatePointsOnASphere(thrust::host_vector<float>& h_x, thrust::host_vector<float>& h_y, thrust::host_vector<float>& h_z) 
{ 
    if(h_x.size() != h_y.size() && h_x.size() != h_z.size()) 
    { 
     std::cout << "The three component vectors have unmatching size()" << std::endl; 
     return; 
    } 

    size_t size = h_x.size() * sizeof(float); 

    float* h_p_x = (float*) calloc(h_x.size(),sizeof(float)); 
    float* h_p_y = (float*) calloc(h_x.size(),sizeof(float)); 
    float* h_p_z = (float*) calloc(h_x.size(),sizeof(float)); 
    if(h_p_x==NULL || h_p_y==NULL || h_p_z==NULL) 
    { 
     std::cout << "Host memory allocation failure" << std::endl; 
     return; 
    } 

    float* d_p_x; 
    float* d_p_y; 
    float* d_p_z; 

    if(cudaMalloc((void **)&d_p_x,size) != cudaSuccess || 
cudaMalloc((void **)&d_p_y,size) != cudaSuccess || 
cudaMalloc((void **)&d_p_z,size) != cudaSuccess) 
    { 
     std::string errorString(cudaGetErrorName(cudaGetLastError())); 
     std::cout << errorString << std::endl; 
     std::cout << "Device memory allocation failure" << std::endl; 
     return; 
    } 
    curandStateMRG32k3a *devStates; 
    if(cudaMalloc((void **)&devStates, h_x.size() * sizeof(curandStateMRG32k3a)) != cudaSuccess) 
    { 
     std::string errorString(cudaGetErrorName(cudaGetLastError())); 
     std::cout << errorString << std::endl; 
     std::cout << "Random generator states memory allocation failure" << std::endl; 
     return; 
    } 

    if(cudaMemcpy(d_p_x,h_p_x,size,cudaMemcpyHostToDevice) != cudaSuccess || 
cudaMemcpy(d_p_y,h_p_y,size,cudaMemcpyHostToDevice) != cudaSuccess || 
cudaMemcpy(d_p_z,h_p_z,size,cudaMemcpyHostToDevice) != cudaSuccess) 
    { 
     std::string errorString(cudaGetErrorName(cudaGetLastError())); 
     std::cout << errorString << std::endl; 
     std::cout << "Host to Device memory copy failure" << std::endl; 
    } 

    int threads = 512; 
    dim3 grid = (h_x.size() + threads - 1)/threads; 
    setup_kernel<<<grid,threads>>>(devStates, size/sizeof(float)); 
    computeRandomVectors<<< grid, threads >>>(d_p_x,d_p_y,d_p_z,size/sizeof(float), devStates); 
    cudaDeviceSynchronize(); 
    if(cudaMemcpy(h_p_x,d_p_x,size,cudaMemcpyDeviceToHost) != cudaSuccess || 
cudaMemcpy(h_p_y,d_p_y,size,cudaMemcpyDeviceToHost) != cudaSuccess || 
cudaMemcpy(h_p_z,d_p_z,size,cudaMemcpyDeviceToHost) != cudaSuccess) 
    { 
     std::string errorString(cudaGetErrorName(cudaGetLastError())); 
     std::cout << errorString << std::endl;  
     std::cout << "Device to Host memory copy failure" << std::endl; 
    } 
    for(size_t i = 0; i < h_x.size(); ++i) 
    { 
     h_x[i] = h_p_x[i]; 
     h_y[i] = h_p_y[i]; 
     h_z[i] = h_p_z[i]; 
    } 

    free (h_p_x); 
    free (h_p_y); 
    free (h_p_z); 
    cudaFree (devStates); 
    cudaFree (d_p_x); 
    cudaFree (d_p_y); 
    cudaFree (d_p_z); 
    cudaDeviceReset(); 
} 

Burada gönderme tutmak için üzülüyorum ama sanırım hatalarım şimdi ne anlayarak: Önerilen değişiklikler sonra kod şudur cuda'nın daha iyi anlaşılması. Yani, şimdi h_x.size() 20k olduğunda cudaMemcpy device-> host errorIllegalAdress alıyorum. Kodun küçük sayılar için nasıl çalıştığını hala anlamadım ama büyükler için değil.

+0

. Şimdi EDIT'iniz ile gösterdiğiniz şeylerin tam bir kodunu oluşturduğumda, herhangi bir hataya rastlamıyorum. Tamamen çalışmış örneğim [burada] (http://pastebin.com/uGy0cTcb). –

+0

@RobertCrovella: Görünüşe göre fark yarattı! Çok aptalca bir hatam, ama kodla karşılaştırdığın zaman gösterdi. İhtiyacım olan değerler aralığı için nihayet tamam ama merak için daha yüksek değerlere ulaşmaya çalıştım ve 100k'de bana Bellek kopyalama hatası vermesi için Cihaz veriyor. – Rebrado

cevap

2

sorun buradadır:

size_t size = h_x.size() * sizeof(float); 

    ... 
    int threads = 256; 
    dim3 grid = size/threads; 

Sizin size değişken bayt sayısına göre ölçeklenir. Yani bu, ızgara boyutu için kullanılacak doğru değişken değil. Şebeke boyutunu şu şekilde hesaplamanız gerekir:

dim3 grid = h_x.size()/threads; 

veya benzerleri. Ayrıca, bu yapının vektör uzunluğu (h_x.size()) threads yani 256 ile eşit olarak bölünmediği sürece tüm curand durumunu düzgün şekilde başlatmayacağını unutmayın. Bunu ele alma yöntemi, setup_kernel'unuzda, diğerinizdekine benzer bir iş parçacığı denetimi içermelidir. çekirdek:

__global__ 
void setup_kernel(curandStateMRG32k3a *state, int size) 
{ 
    int id = threadIdx.x + blockIdx.x * blockDim.x; 
    if (id < size) 
    curand_init(0, id, 0, &state[id]); 
} 

ve vektör boyutunu karşılamak için yeterli konuları başlatmak: tam bir kod sağlamadıysanız

dim3 grid = (h_x.size()+threads-1)/threads; 
+0

Önerilen değişiklik yaptım ve şimdi çok daha iyi çalışıyor. Ancak, 20k noktasına kadar çıksam sorun yine var. Yine de, çekirdek açılışlarında yaptığım hataların, ana bilgisayarı daha önce gerçekleşen aygıt memclosuna nasıl etkileyebileceğini anlamıyorum. – Rebrado

+0

Aygıtın memcpy sunucusundan **, 'setup_kernel' başlatıldıktan ** sonra. Bu çekirdekteki hatalar, 'setup_kernel' başlangıcından sonraki cudaMemcpy işlemlerinde eşzamansız olarak görünecektir. –

+0

İlk anasistemde aygıt memcpy'ına kadar hatalar görüyorsanız, bu hataların diğer tüm kodlardan kaynaklanmış olması da mümkündür (örn. GeneratePointsOnASphere() yöntemini çağırmadan önce). Tam bir kod göstermediğinizden, bu hataları keşfetmem mümkün olmaz. Pastebin bağlantısında sahip olduğum kodun tamamını çalıştırmayı deneyin. –