위의 그의 의견에서 dolan은 Can I use __syncthreads() after having dropped threads?에 따르면 윌리엄 퍼셀 (William Pursell)이 제안한 계획이 교착 상태에 빠질 것이라고 문제를 제기하고 있습니다. 이 문제에 관해서는 conditional syncthreads & deadlock (or not)에 따르면 코드가 대부분의 GPU에서 교착 상태가되지 않는다고합니다. 그 이유는 조기 종료를 지원하기 때문입니다. 하드웨어가 각 블록에 대한 활성 스레드 수를 유지하기 때문입니다.이 수는 장벽 동기화에 사용됩니다 블록의 초기 스레드 수보다
나는 reduce4
CUDA SDK 예제를 고려했으며 OP 질문에 따라 수정했습니다. 즉, 나는 두 __global__
기능을 비교하고 있습니다 :
ORIGINAL
template <class T>
__global__ void reduce4(T *g_idata, T *g_odata, unsigned int N)
{
extern __shared__ T sdata[];
unsigned int tid = threadIdx.x; // Local thread index
unsigned int i = blockIdx.x*(blockDim.x*2) + threadIdx.x; // Global thread index - Fictitiously double the block dimension
// --- Performs the first level of reduction in registers when reading from global memory.
T mySum = (i < N) ? g_idata[i] : 0;
if (i + blockDim.x < N) mySum += g_idata[i+blockDim.x];
sdata[tid] = mySum;
// --- Before going further, we have to make sure that all the shared memory loads have been completed
__syncthreads();
// --- Reduction in shared memory. Only half of the threads contribute to reduction.
for (unsigned int s=blockDim.x/2; s>32; s>>=1)
{
if (tid < s) { sdata[tid] = mySum = mySum + sdata[tid + s]; }
// --- At the end of each iteration loop, we have to make sure that all memory operations have been completed
__syncthreads();
}
// --- Single warp reduction by loop unrolling. Assuming blockDim.x >64
if (tid < 32) {
sdata[tid] = mySum = mySum + sdata[tid + 32]; __syncthreads();
sdata[tid] = mySum = mySum + sdata[tid + 16]; __syncthreads();
sdata[tid] = mySum = mySum + sdata[tid + 8]; __syncthreads();
sdata[tid] = mySum = mySum + sdata[tid + 4]; __syncthreads();
sdata[tid] = mySum = mySum + sdata[tid + 2]; __syncthreads();
sdata[tid] = mySum = mySum + sdata[tid + 1]; __syncthreads();
}
// --- Write result for this block to global memory. At the end of the kernel, global memory will contain the results for the summations of
// individual blocks
if (tid == 0) g_odata[blockIdx.x] = sdata[0];
}
이
template <class T>
__global__ void reduce4_deadlock_test(T *g_idata, T *g_odata, unsigned int N)
{
extern __shared__ T sdata[];
unsigned int tid = threadIdx.x; // Local thread index
unsigned int i = blockIdx.x*(blockDim.x*2) + threadIdx.x; // Global thread index - Fictitiously double the block dimension
// --- Performs the first level of reduction in registers when reading from global memory.
T mySum = (i < N) ? g_idata[i] : 0;
if (i + blockDim.x < N) mySum += g_idata[i+blockDim.x];
sdata[tid] = mySum;
// --- Before going further, we have to make sure that all the shared memory loads have been completed
__syncthreads();
// --- Reduction in shared memory. Only half of the threads contribute to reduction.
for (unsigned int s=blockDim.x/2; s>32; s>>=1)
{
if (tid >= s) return;
sdata[tid] = mySum = mySum + sdata[tid + s];
// --- At the end of each iteration loop, we have to make sure that all memory operations have been completed
__syncthreads();
}
// --- Single warp reduction by loop unrolling. Assuming blockDim.x >64
if (tid < 32) {
sdata[tid] = mySum = mySum + sdata[tid + 32]; __syncthreads();
sdata[tid] = mySum = mySum + sdata[tid + 16]; __syncthreads();
sdata[tid] = mySum = mySum + sdata[tid + 8]; __syncthreads();
sdata[tid] = mySum = mySum + sdata[tid + 4]; __syncthreads();
sdata[tid] = mySum = mySum + sdata[tid + 2]; __syncthreads();
sdata[tid] = mySum = mySum + sdata[tid + 1]; __syncthreads();
}
// --- Write result for this block to global memory. At the end of the kernel, global memory will contain the results for the summations of
// individual blocks
if (tid == 0) g_odata[blockIdx.x] = sdata[0];
}
수정 내가 수정 된 코드는 GT210, GT540M에 교착하지 않음을 확인하고있다 케플러 K20c. 그러나 케플러 카드, 수정 된 버전의 속도 향상은 관련 (ms
에서 회)되지 않습니다 : 내가 다른 아키텍처에 대한 타이밍을 확인하지 않은
N Original Modified
131072 0.021 0.019
262144 0.030 0.032
524288 0.052 0.052
1048576 0.091 0.080
2097152 0.165 0.146
4194304 0.323 0.286
8388608 0.637 0.555
16777216 1.264 1.122
33554432 2.514 2.189
, 그러나 아마 위험은에 붙어 하락 일부 GPU의 교착 상태는 도달 가능한 속도 향상에 도달 할 가치가 없습니다 (도달 가능한 속도 향상이 동일한 순서로 유지되는 경우).
두 번째 코드는 dead lock으로 연결됩니다. 내 질문보기 http://stackoverflow.com/questions/6666382/can-i-use-syncthreads-after-having-dropped-threads –
@cicada - 그 링크에 대해 감사드립니다. –