程序运行后操作系统没有反应。。

有1个char型的数组,长度为nBytes(很大),要求分别找出每1024个点fft之后的幅度最大值及序号。
我采用的步骤是: kernel1(浮点转换)–>cufft–>kernel2(搜索最大值)
kernel1的作用是浮点转换,char型数据不能直接cufft,大概nBytes/1024个block,每个block有1024个线程
cufft每次2048点,大概分nBytes/2048次,cufft每次输出1025点,前1024点有效
kernel2的作用是搜索,大概nBytes/1024个block,每个block有1024个线程
我这里说的block的次数都是大概是为了说明简单,具体见程序里面
出现的问题是,在kernel2返回后进行cudaMemcpy的时候操作系统就没有反应了(刚开始鼠标能动,后来鼠标也不能动了),kernel2后面加的cudaGetLastError返回的是no error。。。
比较急,请版主帮忙解答下,谢谢
不晓得源码贴上去怎么好看,望见谅

先贴2个kernel的代码

//数据格式转换,
global static void DataFormatChange(unsigned char *pBufChar,float pBufFloat,int nByte)
{
const int threadID= threadIdx.x;
const int blockID= blockIdx.x;
int IndexThread=blockID
blockDim.x+threadID;

if(IndexThread<nByte)
(pBufFloat+IndexThread)=(float)((BYTE)((pBufChar+IndexThread)));

}
//搜索频谱幅度最大值
global static void GetMaxAmpIndexAndFilter(cufftComplex *pFFTSource,cufftComplex pLvboResult,float MaxResult)
{
const int threadID= threadIdx.x;
const int blockID= blockIdx.x;
int IndexThread=blockID
blockDim.x+threadID;
int IndexData=blockID
(NPoint/2+1)+threadID;//cufft之后每段数据长度是1025,实际只需要用到1024

extern shared float ABSResult;
extern shared int IndexTmp;

cufftComplex valueTmp=(pFFTSource+IndexData);
ABSResult[threadID]=valueTmp.x
valueTmp.x+valueTmp.y*valueTmp.y;
__syncthreads();

//求模之后查找最大值序号
IndexTmp[threadID]=threadID;
int offset=blockDim.x>>1;
while(offset>0)
{
if(threadID<offset)
{
if(ABSResult[threadID]<ABSResult[threadID+offset])
{
ABSResult[threadID]=ABSResult[threadID+offset];
IndexTmp[threadID]=IndexTmp[threadID+offset];
}
offset >>= 1;
}
__syncthreads();
}
__syncthreads();
if(threadID==0)
*(MaxResult+blockID)=ABSResult[0];
//幅度最大值序号
shared int IndexMax;
IndexMax=IndexTmp[0];

if(threadID<IndexMax+10&&threadID>IndexMax-10)
*(pLvboResult+IndexThread)=valueTmp;

}

主要代码部分是
//原始采样数据
unsigned char pSource_D;
cudaMallocHost((void
*)&pSource_D,sizeof(unsigned char)*nBytes);
cudaMemcpy(pSource_D,pbuf,sizeof(unsigned char)*nBytes,cudaMemcpyHostToDevice);

UINT ThreadSize=1024;
UINT BlockSize=(nBytes+ThreadSize-1)/ThreadSize;
UINT SizeData=ThreadSize*BlockSize; //浮点转换数据长度

//存储浮点转换后的数据
float pFilebuf,pFilebuf_D;
cudaHostAlloc((void
)&pFilebuf, sizeof(float)*SizeData,cudaHostAllocMapped);
cudaMemset(pFilebuf,0,sizeof(float)*SizeData);
cudaHostGetDevicePointer((void **)&pFilebuf_D,(void *)pFilebuf,0);

//采样数据浮点转换
DataFormatChange<<<BlockSize,ThreadSize>>>(pSource_D,pFilebuf_D,nBytes);
cudaFreeHost((void*)pSource_D);

UINT BlockFFTSize=(SizeData+NPoint-1)/NPoint;
UINT SizeFFTData=(NPoint/2+1)*BlockFFTSize; //CUFFT计算长度为N/2+1
//CUFFT
cufftComplex pFFTout,pFFTout_D;
cudaHostAlloc((void
)&pFFTout, sizeof(cufftComplex)*SizeFFTData,cudaHostAllocMapped);
cudaHostGetDevicePointer((void *)&pFFTout_D,(void )pFFTout,0);
cufftHandle plan;
cufftPlan1d(&plan,NPoint,CUFFT_R2C,BlockFFTSize);
cufftExecR2C(plan,(cufftReal
)(pFilebuf_D),(cufftComplex
)pFFTout_D);
cudaMemcpy(pFFTout,pFFTout_D,sizeof(cufftComplex)SizeFFTData,cudaMemcpyDeviceToHost);
cudaFreeHost((void
)pFilebuf);
cufftDestroy(plan);

//保存单个block块中的最大值
float absMax,absMax_D;
cudaHostAlloc((void
)&absMax,sizeof(float)*BlockFFTSize,cudaHostAllocMapped);
cudaHostGetDevicePointer((void **)&absMax_D,(void *)absMax,0);

//保存最后输出
UINT SizeLvboData=NPoint/2*BlockFFTSize;
cufftComplex pFFTLvbo,pFFTLvbo_D;
cudaHostAlloc((void
)&pFFTLvbo,sizeof(cufftComplex)*SizeLvboData,cudaHostAllocMapped);
cudaMemset(pFFTLvbo,0,sizeof(cufftComplex)*SizeLvboData);
cudaHostGetDevicePointer((void **)&pFFTLvbo_D,(void *)pFFTLvbo,0);

//搜索频谱中幅度最大点
GetMaxAmpIndexAndFilter<<<BlockFFTSize,ThreadSize,ThreadSize*(sizeof(float)+sizeof(int))+sizeof(int)>>>(pFFTout_D,pFFTLvbo_D,absMax_D);
const char* error;
error=cudaGetErrorString(cudaGetLastError());
cudaMemcpy(absMax,absMax_D,sizeof(float)*BlockFFTSize,cudaMemcpyDeviceToHost);
cudaMemcpy(pFFTLvbo,pFFTLvbo_D,sizeof(cufftComplex)*SizeLvboData,cudaMemcpyDeviceToHost);

LZ您好:

刚才吃饭去了,才回来。

您的代码长度较大,无法为您目测寻找问题了,见谅。

有一些debug建议供您参考:

1:请逐步检查一下错误,对于同步的cudaMemcpy()请检查其返回值,对于异步的kernel函数,请在后面加上cudaDeviceSynchronize(),并检查这个函数的返回值,并在其后使用一次cudaGetLastError()以防极为少见的kernel同步类型错误。密集的检查错误将有助于您尽快缩小检查范围。
cufft函数请参考其手册检查返回值。

2:请检查您最后copy的API函数的参数是否正确。

3:请减少数据量做初步测试。

4:您叙述中“要求分别找出每1024个点fft之后的幅度最大值及序号”,但是您实现中使用了2048点的fft,这两者是矛盾的,请您注意,这将引起结果在逻辑上的错误(但未必会导致死机)。

大致建议如上,祝您早日解决BUG~

我在kernel2后面加了cudaDeviceSynchronize(),然后程序运行到这里就没反应了,只能重启电脑,问题估计是出在这个kernel里面了,但是我反复检查,也没发现有什么问题啊。。。

另外,比较奇怪的是,我电脑上profiler和nsight都无法运行。。。nsight提示显卡不能调试,Profiler也报错,正在重装cuda5.5。。。

经过仔细观察您的第二个kernel,你得程序死循环了,请把offset右移那句放在if判断外面,否则一开始就不满足if条件的线程将无法结束循环。

此外,您indextmp初始化赋值之后,请同步。否则结果可能错误。

谢谢ice版主,确实是死循环了。。。

不客气的,祝您早日解决全部BUGs~