2016-09-30 20 views
0

私は2つの行列の畳み込みを生成する次のコードを持っています。私が持っている問題は、畳み込みがかなりメモリを消費しているということです。どのようにこれをより速くするためのアイデアですか?matlabでFFT2を改善する方法

  1. 一時変数を削除するにはどうすればよいですか?
  2. fftをより速く実行する方法はありますか?
  3. これにはMatlabのより良いバージョンがありますか?私はどこかに割り当てるか?

    function res = fftconv(data,query) 
    
        N = size(data,1); 
        R = size(query,1); 
        C = size(query,2); 
        query(end+1:N,end+1:N)=0; 
    
        temp = ifft2(fft2(data).*fft2(query)); 
        res = temp(R:end,C:end); 
    
    end 
    
+0

GPUで高速化することができます。私はそれを解決する明確な簡単な方法はないと思います。 –

+0

fftはフーリエ変換のための最速のアルゴリズムで、N * Nから2 * N + 1への計算を減らすので、fftをもっと速くすることができるとは思えません。 – Umar

+0

['fftw'を使ってfftを最適化することを検討してください。 ](https://www.mathworks.com/help/matlab/ref/fftw.html)しかし、私はそれがどんなに大きな違いを生み出すのではないかと心配しています。ちなみに、 'fft2(query、N、N)'はパディングを行い、より速く見えますが、速度は変わりません。 – erfan

答えて

1

あなたのアプローチは、誤って「悪い」の長さ、大きな素因数を持つ、すなわち、数字以上の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)を書いていますが、コードは一般的な消費のために準備が整っていません。
+0

ありがとうございました@ahmed私はコードを実行しており、より小さなデータセットではより速く、元のコードはより大きなデータセットでそれを上回ります。私はランダムにデータを生成し、それを計時しました。ここでの精度は、どちらも同じ結果を生み出すため、問題ではありませんでした。 (私の場合、ゼロ補填は関数外で行われます) – Amir

関連する問題