Я пытаюсь реализовать классическое ядро точечного произведения для массивов двойной точности с атомарным вычислением окончательной суммы по различным блокам.Я использовал atomicAdd для двойной точности, как указано на странице 116 руководства по программированию. Возможно, я делаю что-то не так. Частичные суммы по потокам в каждом блоке вычисляются правильно, но после слов атомная операция, кажется, не работает должным образомтак как каждый раз, когда я запускаю свое ядро с одними и теми же данными, я получаю разные результаты.Буду признателен, если кто-то обнаружит ошибку или предложит альтернативное решение!Вот мое ядро:
__global__ void cuda_dot_kernel(int *n,double *a, double *b, double *dot_res)
{
__shared__ double cache[threadsPerBlock]; //thread shared memory
int global_tid=threadIdx.x + blockIdx.x * blockDim.x;
int i=0,cacheIndex=0;
double temp = 0;
cacheIndex = threadIdx.x;
while (global_tid < (*n)) {
temp += a[global_tid] * b[global_tid];
global_tid += blockDim.x * gridDim.x;
}
cache[cacheIndex] = temp;
__syncthreads();
for (i=blockDim.x/2; i>0; i>>=1) {
if (threadIdx.x < i) {
cache[threadIdx.x] += cache[threadIdx.x + i];
}
__syncthreads();
}
__syncthreads();
if (cacheIndex==0) {
*dot_res=cuda_atomicAdd(dot_res,cache[0]);
}
}
А вот функция моего устройства atomicAdd:
__device__ double cuda_atomicAdd(double *address, double val)
{
double assumed,old=*address;
do {
assumed=old;
old= __longlong_as_double(atomicCAS((unsigned long long int*)address,
__double_as_longlong(assumed),
__double_as_longlong(val+assumed)));
}while (assumed!=old);
return old;
}