2016-12-23 2 views
0

Я новичок в CUDA. Я пытался реализовать структуру данных trie на GPU, но это не сработало. Я заметил, что мой atomicAdd не работает, как я ожидал. Итак, я сделал некоторый эксперимент с atomicAdd. Я написал этот кусок кода:Почему я не вижу разные/уникальные выходные данные моего значения переменной после каждого атома?

#include <cstdio> 

//__device__ int *a; //I also tried the code with using this __device__ 
        //variable and allocating it inside kernel instead 
        //using cudaMalloc. Same Result 

__global__ void AtomicTestKernel (int*a) 
{ 
    *a = 0; 
    __syncthreads(); 
    for (int i = 0; i < 2; i++) 
    { 
     if (threadIdx.x % 2) 
     { 
      atomicAdd(a, 1); 
      printf("threadsIndex = %d\t&\ta : %d\n",threadIdx.x,*a); 
     } 
     else 
     { 
      atomicAdd(a, 1); 
      printf("threadsIndex = %d\t&\ta : %d\n", threadIdx.x, *a); 
     } 
    } 
} 

int main() 
{ 
    int * d_a; 
    cudaMalloc((void**)&d_a, sizeof(int)); 

    AtomicTestKernel << <1, 10 >> > (d_a); 

    cudaDeviceSynchronize(); 

    return 0; 
} 

исправить меня, где я неправильно в этом коде:

1 - в соответствии с руководством по программированию CUDA: (на атомных функций)

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

2 - int * d_a проживает в глобальной памяти и поэтому вводится в ядре: int * a потому, что его выделяется с помощью cudaMalloc (в соответствии с этим 3 минуты видео: Udacity CUDA - Global Memory), и поэтому все резьб видим тот же int * a и не каждый из них имеет собственный

3 - В коде, как и раньше, каждый printf есть atomicAdd, поэтому я ожидаю, что каждый из этих printf s имеет значение *a, отличное от предыдущего и поэтому уникальное.

НО в результате я получаю я вижу так много же переменной *a это результат я получаю:

threadsIndex = 0  &  a : 5 
threadsIndex = 2  &  a : 5 
threadsIndex = 4  &  a : 5 
threadsIndex = 6  &  a : 5 
threadsIndex = 8  &  a : 5 
threadsIndex = 1  &  a : 10 
threadsIndex = 3  &  a : 10 
threadsIndex = 5  &  a : 10 
threadsIndex = 7  &  a : 10 
threadsIndex = 9  &  a : 10 
threadsIndex = 0  &  a : 15 
threadsIndex = 2  &  a : 15 
threadsIndex = 4  &  a : 15 
threadsIndex = 6  &  a : 15 
threadsIndex = 8  &  a : 15 
threadsIndex = 1  &  a : 20 
threadsIndex = 3  &  a : 20 
threadsIndex = 5  &  a : 20 
threadsIndex = 7  &  a : 20 
threadsIndex = 9  &  a : 20 
Press any key to continue . . . 

ответ

3

Поскольку все инструкции выполняются в то же время в перекоса ваш код исполняющего все атомная инструкция THEN, выполняющая printf, как следствие, вы читаете результат всех ваших атомных операций.

Вот exexution инструкции в перекосе:

 
Instruction | threadId 1  | threadId 2  | *a   
____________________________________________________________ 
AtomicAdd | increasing value | waiting   | 1 
       waiting   | increasing value | 2 
---------------------------------------------- Warp finished instruction of all AtomicAdd 
reading *a | read value  | read value  | 2 

читать предыдущее значение атомарных операций проверить результат метода atomicAdd

int previousValue = atomicAdd(a, 1); 

вы можете иметь некоторую информацию здесь : https://docs.nvidia.com/cuda/cuda-c-programming-guide/index.html#atomicadd

+0

Спасибо! Да, я попробовал это, и я увидел уникальные ценности. – Ardeshir81

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