我在Linux系统和Tesla C2075机器上运行。我正在启动一个内核,它是还原内核的修改版本。我的目标是找到大数据集(结果)的平均值和逐步平均版本(time_avg)。请参阅下面的代码。
“result”和“time_avg”的大小相同并且等于“nsamps”。 “time_avg”包含连续的平均数组结果集。因此,前半部分包含每两个非重叠样本的平均值,之后的四分之一具有每四个非重叠样本的平均值,8个样本中的下八分之一,依此类推。
__global__ void timeavg_mean(float *result, unsigned int *nsamps, float *time_avg, float *mean) {
__shared__ float temp[1024];
int ltid = threadIdx.x, gtid = blockIdx.x*blockDim.x + threadIdx.x, stride;
int start = 0, index;
unsigned int npts = *nsamps;
printf("here here\n");
// Store chunk of memory=2*blockDim.x (which is to be reduced) into shared memory
if ( (2*gtid) < npts ){
temp[2*ltid] = result[2*gtid];
temp[2*ltid+1] = result[2*gtid + 1];
}
for (stride=1; stride<blockDim.x; stride>>=1) {
__syncthreads();
if (ltid % (stride*2) == 0){
if ( (2*gtid) < npts ){
temp[2*ltid] += temp[2*ltid + stride];
index = (int)(start + gtid/stride);
time_avg[index] = (float)( temp[2*ltid]/(2.0*stride) );
}
}
start += npts/(2*stride);
}
__syncthreads();
if (ltid == 0)
{
atomicAdd(mean, temp[0]);
}
__syncthreads();
printf("%f\n", *mean);
}
启动配置是40个块,512个线程。数据集约为40k样本。
在我的主代码中,我在内核调用后调用cudaGetLastError()
并且它不返回任何错误。内存分配和内存副本不会返回任何错误。如果我在内核调用之后写cudaDeviceSynchronize()
(或cudaMemcpy
以检查mean的值),程序在内核调用之后会完全挂起。如果我删除它,程序运行并退出。在这两种情况下,我都不会在此处输出输出或打印平均值。据我所知,除非内核成功执行,否则printf将无法打印。
这与递归中的__syncthreads()
有关吗?所有的线程将一直到相同的深度,所以我认为检查出来。
这里有什么问题?
谢谢!
答案 0 :(得分:3)
内核调用是异步的,如果内核成功启动,主机代码将继续运行,您将看不到任何错误。内核运行期间发生的错误仅在您执行显式同步或调用导致隐式同步的函数后才会出现
如果你的主机挂起同步而不是你的内核可能没有完成运行 - 它要么运行一些无限循环,要么等待一些__synchthreads()
或其他同步原语。
您的代码似乎包含无限循环:for (stride=1; stride<blockDim.x; stride>>=1)
。你可能想要向右移动步幅:stride<<=1
。
你提到了递归,但你的代码只包含一个__global__
函数,没有递归调用。
答案 1 :(得分:1)
你的内核有一个无限循环。用
替换for循环for (stride=1; stride<blockDim.x; stride<<=1) {