我正在为C++和Cuda的学校作业编写一个频率过滤应用程序,它使用cuFFT,我无法让它工作。您可以找到整个Visual 2010解决方案这里。(需要过剩.)
以下是我认为相关的部分:(furierUtils.cu/194)
//////////////////////////////////////////////////////////////////////////////
// Function to help invoking the kernel, creates the parameters and gets
// the result
__host__
void Process(
BitmapStruct& in_img, // these contain an image in an rgba byte array
BitmapStruct& out_img,
MaskGenerator maskGenerator, // this is a pointer to a device function
float param1, // mask parameters
float param2)
{
// Declare and allocate variables
cufftHandle plan;
cufftReal* img;
cufftReal* dev_img;
cufftComplex* dev_freq_img;
int imgsize = in_img.image_size();
int pixelcount = imgsize / 4;
img = new float[pixelcount];
checkResult(
cudaMalloc(&dev_img, sizeof(cufftReal) * pixelcount));
checkResult(
cudaMalloc(&dev_freq_img, sizeof(cufftComplex) * pixelcount));
// Optimize execution
cudaFuncAttributes attrs;
checkResult(
cudaFuncGetAttributes(&attrs, &Filter));
std::pair<dim3, dim3> params
= Optimizer::GetOptimalParameters(pixelcount, attrs);
// Process r, g, b channels
for(int chan = 0; chan <= 2; chan++)
{
// Init
for(int i = 0; i < pixelcount; i++)
{
img[i] = in_img.pixels[4 * i + chan];
}
checkResult(
cudaMemcpy(dev_img, img, pixelcount, cudaMemcpyHostToDevice));
// Create frequency image
checkResult(
cufftPlan1d(&plan, pixelcount, CUFFT_R2C, 1));
checkResult(
cufftExecR2C(plan, dev_img, dev_freq_img));
checkResult(
cudaThreadSynchronize());
checkResult(
cufftDestroy(plan));
// Mask frequency image
Filter<<<params.first, params.second>>>(
dev_freq_img, in_img.x, in_img.y, maskGenerator, param1, param2);
getLastCudaError("Filtering the image failed.");
// Get result
checkResult(
cufftPlan1d(&plan, pixelcount, CUFFT_C2R, 1));
checkResult(
cufftExecC2R(plan, dev_freq_img, dev_img));
checkResult(
cudaThreadSynchronize());
checkResult(
cufftDestroy(plan));
checkResult(
cudaMemcpy(img, dev_img, pixelcount, cudaMemcpyDeviceToHost));
for(int i = 0; i < pixelcount; i++)
{
out_img.pixels[4 * i + chan] = img[i];
}
}
// Copy alpha channel
for(int i = 0; i < pixelcount; i++)
{
out_img.pixels[4 * i + 3] = in_img.pixels[4 * i + 3];
}
// Free memory
checkResult(
cudaFree(dev_freq_img));
checkResult(
cudaFree(dev_img));
delete img;
getLastCudaError("An error occured during processing the image.");
}与我看到的官方示例相比,我看不到任何实际差异,但是当我用Nsight调试它时,内核接收到的所有cufftComplex值都是NaNs,输入和结果图像之间唯一的区别是,结果在底部有一个黑条,不管我使用哪个过滤掩码和参数。所有Cuda和cuFFT调用都返回成功,并且在内核调用之后也没有报告错误。
我做错什么了?
我尝试用复杂数组替换img和dev_img,并使用C2C转换并在内部进行转换,但它只改变了结果图像上黑条的大小。
谢谢你的帮助。
编辑: 这里是一个简化的版本,不需要过剩,也应该在linux上编译。
发布于 2013-11-29 22:10:12
我的错误是忘记在一些cudaMemcpy调用中将项目的数量与其大小相乘,因此输入到cuFFT的向量的末尾由NaNs组成。修复这些问题解决了问题。
我还将cufftReal数组替换为cufftComplex数组,因为C2C转换似乎更可预测,并为值添加了规范化。
因此,最后的工作方法是:
///////////////////////////////////////////////////////////////////////////////
// Function to help invoking the kernel, creates the parameters and gets
// the result
__host__
void Process(
BitmapStruct& in_img,
BitmapStruct& out_img,
MaskGenerator maskGenerator,
float param1,
float param2)
{
// Declare and allocate variables
cufftHandle plan;
cufftComplex* img;
cufftComplex* dev_img;
cufftComplex* dev_freq_img;
int imgsize = in_img.image_size();
int pixelcount = imgsize / 4;
img = new cufftComplex[pixelcount];
checkResult(
cudaMalloc(&dev_img, sizeof(cufftComplex) * pixelcount));
checkResult(
cudaMalloc(&dev_freq_img, sizeof(cufftComplex) * pixelcount));
// Optimize execution
cudaFuncAttributes attrs;
checkResult(
cudaFuncGetAttributes(&attrs, &Filter));
std::pair<dim3, dim3> params =
Optimizer::GetOptimalParameters(pixelcount, attrs);
// Process r, g, b channels
for(int chan = 0; chan <= 2; chan++)
{
// Init
for(int i = 0; i < pixelcount; i++)
{
img[i].x = in_img.pixels[4 * i + chan];
img[i].y = 0;
}
checkResult(
cudaMemcpy(
dev_img,
img,
pixelcount * sizeof(cufftComplex),
cudaMemcpyHostToDevice));
// Create frequency image
checkResult(
cufftPlan1d(&plan, pixelcount, CUFFT_C2C, 1));
checkResult(
cufftExecC2C(plan, dev_img, dev_freq_img, CUFFT_FORWARD));
checkResult(
cudaThreadSynchronize());
checkResult(
cufftDestroy(plan));
// Mask frequency image
Filter<<<params.first, params.second>>>(
dev_freq_img,
in_img.x,
in_img.y,
maskGenerator,
param1,
param2);
getLastCudaError("Filtering the image failed.");
// Get result
checkResult(
cufftPlan1d(&plan, pixelcount, CUFFT_C2C, 1));
checkResult(
cufftExecC2C(plan, dev_freq_img, dev_img, CUFFT_INVERSE));
checkResult(
cudaThreadSynchronize());
checkResult(
cufftDestroy(plan));
checkResult(
cudaMemcpy(
img,
dev_img,
pixelcount * sizeof(cufftComplex),
cudaMemcpyDeviceToHost));
for(int i = 0; i < pixelcount; i++)
{
out_img.pixels[4 * i + chan] = img[i].x / pixelcount;
}
}
// Copy alpha channel
for(int i = 0; i < pixelcount; i++)
{
out_img.pixels[4 * i + 3] = in_img.pixels[4 * i + 3];
}
// Free memory
checkResult(
cudaFree(dev_freq_img));
checkResult(
cudaFree(dev_img));
delete img;
getLastCudaError("An error occured during processing the image.");
}谢谢你的帮助。
发布于 2013-11-28 21:47:53
我还没有编译和运行您的简化版本,但我认为问题在于dev_img和dev_freq_imag的大小。
考虑CUFFT图书馆用户指南第4.2节中的示例。它执行就地实到复转换,这是您首先执行的相同步骤。
#define NX 256
cufftHandle plan;
cufftComplex *data;
cudaMalloc((void**)&data, sizeof(cufftComplex)*(NX/2+1)*BATCH);
cufftPlan1d(&plan, NX, CUFFT_R2C, BATCH);
cufftExecR2C(plan, (cufftReal*)data, data);由于转换的对称性,cufftExecR2C只填充NX/2+1输出元素,其中NX是输入数组的大小。
在您的例子中,您正在执行以下操作:
cufftHandle plan;
cufftReal* dev_img;
cufftComplex* dev_freq_img;
cudaMalloc(&dev_img, sizeof(cufftReal) * pixelcount);
cudaMalloc(&dev_freq_img, sizeof(cufftComplex) * pixelcount);因此,您将分配一个cufftReal数组和一个大小相同的cufftComplex数组。当你使用
cufftPlan1d(&plan, pixelcount, CUFFT_R2C, 1);
cufftExecR2C(plan, dev_img, dev_freq_img);然后,只有一半的dev_freq_img被cufftExecR2C填充,剩下的部分包含垃圾。如果在dev_freq_img函数中使用Filter __global__函数的全部范围,那么这可能就是NaN的原因。
https://stackoverflow.com/questions/20265991
复制相似问题