我正在爲使用cuFFT的C++和Cuda的學校作業編寫一個頻率過濾應用程序,我無法使其工作。您可以找到整個Visual Studio 2010解決方案here。 (需要glut)cuFFT的NaN問題
這裏是我認爲相關的部分:(fourierUtils.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值都是NaN,並且input和result圖像之間的唯一區別在於,結果在底部有一個黑色條,無論是哪個過濾掩碼和哪些參數我用。所有Cuda和cuFFT調用都會返回成功,並且在內核調用後也不會報告錯誤。
我該怎麼做?
我已經嘗試用複雜數組替換img和dev_img,並使用C2C轉換並在原地進行,但它只改變了結果圖像上黑條的大小。
謝謝你的幫助。
編輯:here是一個簡化版本,不需要過剩,也應該在linux上編譯。
如果你省略了過濾步驟,你會得到你的原始圖像還是你仍然會得到'NaN's? –
我認爲人們會花費一些時間來處理整個VS psoject,包括過度使用,特別是對於linux用戶。你能否提供一個更簡潔的例子來重現你的問題? – JackOLantern
@PaulR我在過濾步驟中得到了NaNs,但是省略它並不會改變最終結果(過濾器試圖乘以nans,這對它們什麼也不做)。 我可能是錯的,但在我看來,我的內核無法訪問dev_freq_img指向的內存(這與設備內存中的奇怪)。而出現的黑條可能是一個不同的問題。 –