我从NVIDIA手册中复制了以下代码,例如:__threadfence()
。为什么他们有
在下面的代码中使用了__threadfence()
。我认为使用__syncthreads()
代替
__threadfence()
会给你相同的结果。
有人可以解释__syncthreads()
和__threadfence()
来电之间的区别吗?
__device__ unsigned int count = 0;
__shared__ bool isLastBlockDone;
__global__ void sum(const float* array, unsigned int N,float* result)
{
// Each block sums a subset of the input array
float partialSum = calculatePartialSum(array, N);
if (threadIdx.x == 0) {
// Thread 0 of each block stores the partial sum
// to global memory
result[blockIdx.x] = partialSum;
// Thread 0 makes sure its result is visible to
// all other threads
__threadfence();
// Thread 0 of each block signals that it is done
unsigned int value = atomicInc(&count, gridDim.x);
// Thread 0 of each block determines if its block is
// the last block to be done
isLastBlockDone = (value == (gridDim.x - 1));
}
// Synchronize to make sure that each thread reads
// the correct value of isLastBlockDone
__syncthreads();
if (isLastBlockDone)
{
// The last block sums the partial sums
// stored in result[0 .. gridDim.x-1]
float totalSum = calculateTotalSum(result);
if (threadIdx.x == 0)
{
// Thread 0 of last block stores total sum
// to global memory and resets count so that
// next kernel call works properly
result[0] = totalSum;
count = 0;
}
}
}
答案 0 :(得分:15)
就共享内存而言,__syncthreads()
比__threadfence()
更强大。关于全球记忆 - 这是两件不同的事情。
__threadfence_block()
停止当前线程,直到对共享内存的所有写入对同一块中的其他线程可见。它通过在寄存器中缓存共享内存写入来防止编译器进行优化。它不同步线程,并不是所有线程都必须实际到达此指令。__threadfence()
停止当前线程,直到对共享和全局内存的所有写入对所有其他线程都可见。__syncthreads()
(例如,没有发散if
语句),并确保在之前执行指令之前的代码 ,对于块中的所有线程。在您的特定情况下,__threadfence()
指令用于确保对全局数组result
的写入对所有人可见。 __syncthreads()
只会同步当前块中的线程,而不会强制执行其他块的全局内存写入。更重要的是,在代码中你在if
分支内的那一点上,只有一个线程正在执行该代码;使用__syncthreads()
会导致GPU的未定义行为,最有可能导致内核完全失步。
查看CUDA C编程指南中的以下章节: