Неправильные результаты 2D-свертки cuFFT с неквадратной матрицей

Я пытаюсь выполнить двумерную свертку, используя подход «FFT + point_wise_product + iFFT». Используя матрицы NxN, метод хорошо работает, однако неквадратные матрицы результаты не верны. Я прочитал всю документацию cuFFT в поисках каких-либо заметок о поведении с такими матрицами, проверенных на месте и вне места FFT, но я кое-что забыл.

Я протестировал тот же алгоритм с теми же матрицами в MATLAB, и все правильно.
Я покажу вам очень упрощенный код с очень простым фильтром для ясности, его вывода и ожидаемого вывода. Что я делаю неправильно?
Я также прочитал другие связанные вопросы / ответы, но ни один из них не решил проблему. Заранее большое спасибо.

const int W = 5;
const int H = 4;

//Signal, with just one value, for simplicity.
float A[H][W] = {{0,0,0,0,0},
{0,1,0,0,0},
{0,0,0,0,0},
{0,0,0,0,0}};

//Central element of the kernel in the (0,0) position of the array.
float B[H][W] = {{0.5, 0.1,  0,    0,  0.2},
{0  ,  0  ,  0,    0,  0},
{0  ,  0  ,  0,    0,  0},
{0  ,  0  ,  0,    0,  0}};cufftReal* d_inA, *d_inB;
cufftComplex* d_outA, *d_outB;

size_t real_size = W * H * sizeof(cufftReal);
size_t complex_size = W * (H/2+1) * sizeof(cufftComplex);

cudaMalloc((void**)&d_inA, real_size);
cudaMalloc((void**)&d_inB, real_size);

cudaMalloc((void**)&d_outA, complex_size);
cudaMalloc((void**)&d_outB, complex_size);

cudaMemset(d_inA,0,real_size);
cudaMemset(d_inB,0,real_size);

cudaMemcpy(d_inA, A, real_size, cudaMemcpyHostToDevice);
cudaMemcpy(d_inB, B, real_size, cudaMemcpyHostToDevice);cufftHandle fwplanA, fwplanB, bwplan;
cufftPlan2d(&fwplanA, W, H, CUFFT_R2C);
cufftPlan2d(&fwplanB, W, H, CUFFT_R2C);
cufftPlan2d(&bwplan, W, H, CUFFT_C2R);

cufftSetCompatibilityMode(fwplanA,CUFFT_COMPATIBILITY_NATIVE);
cufftSetCompatibilityMode(fwplanB,CUFFT_COMPATIBILITY_NATIVE);
cufftSetCompatibilityMode(bwplan,CUFFT_COMPATIBILITY_NATIVE);

cufftExecR2C(fwplanA, d_inA, d_outA);
cufftExecR2C(fwplanB, d_inB, d_outB);

int blocksx = ceil((W*(H/2+1 )) / 256.0f);
dim3 threads(256);
dim3 grid(blocksx);
// One complex product for each thread, scaled by the inverse of the
// number of elements involved in the FFT
pointwise_product<<<grid, threads>>>(d_outA, d_outB, (W*(H/2+1)), 1.0f/(W*H));

cufftExecC2R(bwplan, d_outA, d_inA);cufftReal* result = new cufftReal[W*2*(H/2+1)];
cudaMemcpy(result, d_inA, real_size,cudaMemcpyDeviceToHost);

// Print result...
// Free memory...

Выход. Обратите внимание на смещенное значение

-0.0  0.0   -0.0   -0.0   0.0
0.0   0.5    0.1    0.0   -0.0
0.2   0.0    0.0   -0.0   -0.0
-0.0  0.0   -0.0   -0.0   -0.0

Ожидаемый результат (MATLAB)

0         0         0         0         0
0.2000    0.5000    0.1000    0.0000    0.0000
0         0         0         0         0
0         0         0         0         0

Родственный Документ:
http://developer.download.nvidia.com/compute/cuda/2_2/sdk/website/projects/convolutionFFT2D/doc/convolutionFFT2D.pdf

2

Решение

Вы обмениваетесь строками со столбцами в вашем плане манжеты.

Соответствующий прототип

 cufftPlan2d(cufftHandle *plan, int nx, int ny, cufftType type)

где nx это количество строк и ny это количество столбцов, поэтому оно должно быть

 cufftPlan2d(&fwplanA, H, W, CUFFT_R2C);

и не

 cufftPlan2d(&fwplanA, W, H, CUFFT_R2C);
3

Другие решения

Других решений пока нет …

По вопросам рекламы [email protected]