Tôi đang cố gắng triển khai hạt nhân dot-sản phẩm cổ điển cho các mảng chính xác kép với tính toán nguyên tử của tổng cuối cùng trên các khối khác nhau. Tôi đã sử dụng atomicAdd cho độ chính xác gấp đôi như đã nêu trong trang 116 của hướng dẫn lập trình. Có lẽ tôi đang làm điều gì đó sai. Khoản tiền một phần trên các chủ đề trong mỗi khối được tính toán một cách chính xác nhưng sau đó hoạt động nguyên tử dường như không hoạt động đúng cách vì mỗi khi tôi chạy hạt nhân với cùng một dữ liệu, tôi nhận được các kết quả khác nhau. Tôi sẽ biết ơn nếu ai đó có thể phát hiện ra sai lầm hoặc cung cấp một giải pháp thay thế! Đây là hạt nhân của tôi:Sản phẩm CUDA Dot
__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]);
}
}
Và đây là chức năng điện thoại của tôi 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;
}
Nguyên tử bộ nhớ chia sẻ khá chậm. Đây không phải là cách hay để triển khai sản phẩm chấm. Bạn nên sử dụng lực đẩy tốt hơn, như Jared chỉ ra. Nếu bạn nhấn mạnh vào việc viết mã của riêng bạn, và bạn thực sự muốn làm điều đó trong một hạt nhân, hãy xem mẫu threadFenceReduction trong các mẫu mã CUDA SDK. Nó sẽ hiệu quả hơn nhiều (nó không phải là một sản phẩm dấu chấm, chỉ cần giảm tổng, nhưng việc bổ sung nhân tố nguyên tố ban đầu sẽ là tầm thường.) – harrism
@harrism: Có nguyên tử bộ nhớ chia sẻ trong mã này ở đâu? Đây chỉ là một giảm bộ nhớ chia sẻ tiêu chuẩn với các hoạt động nguyên tử bộ nhớ toàn cục để hoàn thành việc tổng hợp các giá trị giảm một phần khối. – talonmies
Xin lỗi, tôi đã hoán đổi các đối số nguyên tử trong đầu tôi! Bất kể, bạn không nên cần nguyên tử để thực hiện giảm trong một hạt nhân duy nhất nếu bạn sử dụng threadfence. – harrism