我已經實現了一個向量點積如下。 它與CUDA 7.5編譯爲compute_20,sm_20
和const int THREADS_PER_BLOCK = 16;
。兩個向量的cuda點積不適用於N> = 369
浮動和雙打都發生這種情況。
它工作到n=368
,但除此之外,結果是不正確的。我想知道問題出在我的實現代碼還是我正在使用的值(請參閱第二個代碼,初始化),例如可能是除n=368
之外的添加引入了浮點錯誤(這可能很奇怪,因爲浮點和雙精度同時出現錯誤)。
int divUp(int total, int grain) { return (total+grain-1)/grain; }
__device__ __forceinline__ double atomicAdd(double* address, double val)
{
unsigned long long int* address_as_ull = (unsigned long long int*)address;
unsigned long long int old = *address_as_ull, assumed;
do
{
assumed = old;
old = atomicCAS(address_as_ull, assumed, __double_as_longlong(val+__longlong_as_double(assumed)));
}
while(assumed!=old);
return __longlong_as_double(old);
}
__device__ __forceinline__ float atomicAdd(float* address, float val)
{
unsigned int *ptr = (unsigned int *)address;
unsigned int old, newint, ret = *ptr;
do {
old = ret;
newint = __float_as_int(__int_as_float(old)+val);
} while((ret = atomicCAS(ptr, old, newint)) != old);
return __int_as_float(ret);
}
template<typename T>
__global__ void vecdotk(const T* a, const T* b, const int n, T* c)
{
__shared__ T temp[THREADS_PER_BLOCK];
int x = threadIdx.x+blockIdx.x*blockDim.x;
if(x==0) c[0] = 0.0;
if(x<n) {temp[threadIdx.x] = a[x]*b[x];
}
else temp[threadIdx.x] = 0.0;
__syncthreads();
if(0==threadIdx.x)
{
T sum = 0.0;
for(int j=0; j<THREADS_PER_BLOCK; ++j)
{
sum += temp[j];
}
atomicAdd(c, sum);
}
}
template<typename T>
void dot(const T* a, const T* b, const int n, T* c)
{
dim3 block(THREADS_PER_BLOCK);
dim3 grid(divUp(n, block.x), 1);
vecdotk<T><<<grid, block>>>(a, b, n, c);
cudaSafeCall(cudaGetLastError());
};
我使用以下兩個主機矢量來填充輸入設備數組(目前我沒有顯示,因爲它們是更大的庫的一部分)。基本上我想計算平方系列的總和即
// fill host vectors a and b
for(int i=0; i<n; ++i)
{
h_vec_a[i] = i+1;//__mat_rand();
h_vec_b[i] = i+1;//__mat_rand();
}
我正在學習CUDA的基礎知識,併爲通用計算編程GPU。但是,如果我在'if(x == 0)c [0] = 0.0;'行之後使用'__threadfence()'會怎麼樣? – user62039
謝謝羅伯特。另外,我認爲最好在void void(...)函數中初始化sum = 0.0。對? – user62039
threadfence不強制線程執行的順序。是的,只要在內核調用之前就可以將c初始化 –