あなたのアプローチは、誤って「悪い」の長さ、大きな素因数を持つ、すなわち、数字以上のFFTを計算することがあります。
また、あなたのアプローチは循環畳み込みを行います。Matlabに内蔵されているゼロ埋め込みのないconv2
の出力とは一致しません。 (あなたがnx + ny - 1
に両方の入力をZEROPADときFFTが時間領域の線形畳み込みと等価である使用して、その巡回畳み込みを思い出してください。)
ここconv2
と同じ値を返します。あなたが使用できる簡単な関数、です:
function z = conv2fft(x, y, nfft)
nx = size(x);
ny = size(y);
nz = nx + ny - 1;
if ~exist('nfft', 'var') || isempty(nfft)
nfft = 2 .^ nextpow2(nz);
else
assert(all(nfft >= nz), 'nfft >= nx + ny - 1 for linear convolution');
end
zfull = ifft2(fft2(x, nfft(1), nfft(2)) .* fft2(y, nfft(1), nfft(2)));
z = zfull(1 : nz(1), 1 : nz(2));
は、
>> x = randn(10, 11);
>> y = randn(4, 3);
>> z1 = conv2(x, y);
>> z2 = conv2fft(x, y);
>> max(abs(z2(:) - z1(:)))
ans =
2.2204e-15
2の間にもエラーが長方形の入力のために、非常に小さなです:
は、それが動作しますが、それをチェックアウト。それが速いことを確認するために、データのベンチマークを行う必要があります。
スピードに関する重要な注意点:この機能では、何も指定されていない場合、デフォルトのnfft
(2の累乗)が使用されます。時にはこれが最善ではない場合もあります。たとえば、nx + ny - 1
が[1025, 1025]
(つまり、conv2
の出力は1025×1025)の場合、デフォルトで2048×2048の中間配列が生成されます(1025×1025より遅い場合があります)。これは、FFTWが内部的に4倍のメモリを割り当て、4倍のFFTを取らなければならないためです。 この場合、conv2fft
がより良いnfft
、たとえば[1080, 1080]
(1,080の固有の係数は2,3および5です)を指定できます。 Juliaには、nextprod
という素晴らしい機能があり、特定の要素を持つ次の整数を見つけることができます。 nextprod([2 3 5], 1025)
のように使用できるfree Matlab version of nextprod
があります。これは、要約すると1080
を返します。
- あなたはFFTは、上記のように長さ「素敵」を使用して高速化を少しかもしれません。
- コメント欄に記載されているように、FFTを高速に評価できるGPUベースのFFTを見ることもできますが、GPUとの入出力をコピーするのに要する時間を考慮する必要があります。
- また、FFTWに必要な正確なサイズの計画を作成するようFFTWに依頼することもできます.Matlabが使用するデフォルトの計画よりも数%速くなる場合があります。
- 最後に、人々はまた、より高速なFFT実装(例えば、FFTS)を書いていますが、コードは一般的な消費のために準備が整っていません。
GPUで高速化することができます。私はそれを解決する明確な簡単な方法はないと思います。 –
fftはフーリエ変換のための最速のアルゴリズムで、N * Nから2 * N + 1への計算を減らすので、fftをもっと速くすることができるとは思えません。 – Umar
['fftw'を使ってfftを最適化することを検討してください。 ](https://www.mathworks.com/help/matlab/ref/fftw.html)しかし、私はそれがどんなに大きな違いを生み出すのではないかと心配しています。ちなみに、 'fft2(query、N、N)'はパディングを行い、より速く見えますが、速度は変わりません。 – erfan