2014-01-03 6 views
-2

Я использую atomicAdd(), чтобы добавить 1 к каждому из элементов массива с = {0,0,0,0,0} с использованием двух различных схемCUDA atomicAdd() дает неправильные результаты

  1. c [i] = c [i] + 1;

результат - с = {1,1,1,1,1}

  1. с [I] = atomicAdd (& (с [I]), 1);

результат с = {0,0,0,0,0}

Я совершенно невежественный, почему я получаю такие результаты, вот небольшой код, я использую для получить результаты.

#include "cuda_runtime.h" 
#include "device_launch_parameters.h" 

#include <stdio.h> 
#include<windows.h> 

void addWithCuda(int *c, int size); 

__global__ void addKernel(int *c, int size) 
{ 
    int i = threadIdx.x; 
    if (i < size) 
    c[i] = c[i] + 1; 
    //c[i] = atomicAdd(&(c[i]),(int)1); 
} 

int main() 
{ 
    const int arraySize = 5; 

    int c[arraySize] = {0,0,0,0,0}; 

    // Add vectors in parallel. 
    addWithCuda(c, arraySize); 

    Sleep(3000); 
    printf("result = {%d,%d,%d,%d,%d}\n", 
     c[0], c[1], c[2], c[3], c[4]); 
    return 0; 
} 

// Helper function for using CUDA to add vectors in parallel. 
void addWithCuda(int *c, int size) 
{ 

    int *dev_c = 0; 
    cudaError_t cudaStatus; 

    // Choose which GPU to run on, change this on a multi-GPU system. 
    cudaStatus = cudaSetDevice(0); 
    if (cudaStatus != cudaSuccess) { 
     fprintf(stderr, "cudaSetDevice failed! Do you have a CUDA-capable GPU   installed?"); 

    } 

    // Allocate GPU buffers for three vectors (two input, one output) . 
    cudaStatus = cudaMalloc((void**)&dev_c, size * sizeof(int)); 
    if (cudaStatus != cudaSuccess) { 
     fprintf(stderr, "cudaMalloc failed!"); 

    } 

     cudaStatus = cudaMemcpy(dev_c, c, size * sizeof(int), cudaMemcpyHostToDevice); 
    if (cudaStatus != cudaSuccess) { 
     fprintf(stderr, "cudaMemcpy failed!"); 

    } 

    // Launch a kernel on the GPU with one thread for each element. 
    addKernel<<<1, size>>>(dev_c, size); 


    // cudaDeviceSynchronize waits for the kernel to finish, and returns 
    // any errors encountered during the launch. 
    cudaStatus = cudaDeviceSynchronize(); 
    if (cudaStatus != cudaSuccess) { 
     fprintf(stderr, "cudaDeviceSynchronize returned error code %d after launching addKernel!\n", cudaStatus); 

    } 

    // Copy output vector from GPU buffer to host memory. 
    cudaStatus = cudaMemcpy(c, dev_c, size * sizeof(int), cudaMemcpyDeviceToHost); 
    if (cudaStatus != cudaSuccess) { 
     fprintf(stderr, "cudaMemcpy failed!"); 

    } 
} 
+5

Есть ли причина, по которой вы отказываетесь читать документацию для 'atomicAdd' и понимаете, что она возвращает? –

+0

Этот код нет * маленький *. –

+2

Это не дает неправильных результатов, он делает именно то, что вы просили! – Tom

ответ

4
c[i] = atomicAdd(&(c[i]),(int)1); 

должно быть

atomicAdd(&(c[i]),(int)1); 

В основном & (с [I]), ссылка вызова используется для добавления +1 непосредственно в массиве. атомныйAdd возвращает 0; и вы помещаете нуль внутри массива.

+0

Спасибо, Том, отлично сработал. – user3158261

Смежные вопросы