Пример cuda atomicAdd не может дать правильный вывод
Следующий код был написан с целью увеличения массива из 100 элементов с плавающей запятой в 1 десять раз. В выводе я ожидал массив из 100 элементов со значением 10.0f для каждого элемента. Вместо этого я получаю случайные значения. Можете ли вы указать мою ошибку здесь?
__global__ void testAdd(float *a)
{
float temp;
for (int i = 0; i < 100 ; i++)
{
a[i] = atomicAdd(&a[i], 1.0f);
}
}
void cuTestAtomicAdd(float *a)
{
testAdd<<<1, 10>>>(a);
}
Моя цель состоит в том, чтобы понять работу атомных операций, чтобы применить их в другом месте.
1 ответ
Это не так, как мы делаем atomicAdd
операция.
Просто сделайте это так:
atomicAdd(&a[i], 1.0f);
и рассматриваемая переменная (a[i]
) будет обновлено.
Возвращаемое значение из атомарной функции обычно является старым значением, которое было в переменной, до атомарного обновления.
Делая это:
a[i] = atomicAdd(&a[i], 1.0f);
обновит переменную a[i]
, а затем (не атомарно) назначить старое значение переменной a[i]
, Это почти наверняка не то, что вы хотите.
Прочитайте документацию:
Функция возвращает старую.
Следующий полный код демонстрирует правильное использование:
#include <iostream>
__global__ void testAdd(float *a)
{
for (int i = 0; i < 100 ; i++)
{
atomicAdd(&a[i], 1.0f);
}
}
void cuTestAtomicAdd(float *a)
{
testAdd<<<1, 10>>>(a);
}
int main(){
float *d_data, *h_data;
h_data=(float *) malloc(100*sizeof(float));
cudaMalloc((void **)&d_data, 100*sizeof(float));
cudaMemset(d_data, 0, 100*sizeof(float));
cuTestAtomicAdd(d_data);
cudaMemcpy(h_data, d_data, 100*sizeof(float), cudaMemcpyDeviceToHost);
for (int i = 0; i < 100; i++)
if (h_data[i] != 10.0f) {printf("mismatch at %d, was %f, should be %f\n", i, h_data[i], 10.0f); return 1;}
printf("Success\n");
return 0;
}