3

さまざまなインターフェイスを使用して 2D FFT を実行する次の非常に基本的な例があります。

import time
import numpy
import pyfftw
import multiprocessing

a = numpy.random.rand(2364,2756).astype('complex128')

start = time.time()
b1 = numpy.fft.fft2(a)
end1 = time.time() - start

start = time.time()
b2 = pyfftw.interfaces.scipy_fftpack.fft2(a, threads=multiprocessing.cpu_count())
end2 = time.time() - start

pyfftw.forget_wisdom()
start = time.time()
b3 = pyfftw.interfaces.numpy_fft.fft2(a, threads=multiprocessing.cpu_count())
end3 = time.time() - start

pyfftw.forget_wisdom()
start = time.time()
b4 = numpy.zeros_like(a)
fft = pyfftw.FFTW(a, b4, axes=(0,1), flags=('FFTW_ESTIMATE',),planning_timelimit=1.0)
fft()
end4 = time.time() - start

print('numpy.fft.fft2:                        %.3f secs.' % end1)
print('pyfftw.interfaces.scipy_fftpack.fft2:  %.3f secs.' % end2)
print('pyfftw.interfaces.numpy_fft.fft2:      %.3f secs.' % end3)
print('pyfftw.FFTW:                           %.3f secs.' % end4)

これにより、次の結果が生成されます。

numpy.fft.fft2:                        1.878 secs.
pyfftw.interfaces.scipy_fftpack.fft2:  50.133 secs.
pyfftw.interfaces.numpy_fft.fft2:      52.136 secs.
pyfftw.FFTW:                           0.331 secs.

明らかに、pyfftw.FFTWインターフェイスは最速ですが、機能しません (何が間違っているのかわかりません)。

これpyfftw.interfaces.scipy_fftpack.fft2pyfftw.interfaces.numpy_fft.fft2はかなりの時間がかかりますが、その時間は主に計画フェーズにあると判断しました。これは最初の 1 回だけです。私の場合、(プロセスごとに) 1 つの FFT2 と 1 つの IFFT2 だけが実行されるので、計画が私を殺しています。知恵を忘れずにどちらかをもう一度実行すると、約0.33秒で実行されます(ただし、これは私の場合は起こりません)。

したがって、問題は次のとおりです。1.pyfftw.FFTWデータが間違っている原因は何ですか? - または - 2. または の計画スキームと期限を変更するにはどうすればよいですpyfftw.interfaces.scipy_fftpack.fft2pyfftw.interfaces.numpy_fft.fft2?

4

2 に答える 2

4

pyfftw.FFTW クラスを正しく使用するようにコードを修正して、最も効率的にし、「ビルダー」クラスで実行時間を 2 分の 1 に短縮しました。

import time
import numpy
import pyfftw
import multiprocessing
nthread = multiprocessing.cpu_count()
a = numpy.random.rand(2364,2756).astype('complex128')
""" 
Uncomment below to use 32 bit floats, 
increasing the speed by a factor of 4
and remove the difference between the "builders" and "FFTW" methods
"""
#a = numpy.random.rand(2364,2756).astype('complex64')

start = time.time()
b1 = numpy.fft.fft2(a)
end1 = time.time() - start

start = time.time()
b2 = pyfftw.interfaces.scipy_fftpack.fft2(a, threads=nthread)
end2 = time.time() - start

pyfftw.forget_wisdom()
start = time.time()
b3 = pyfftw.interfaces.numpy_fft.fft2(a, threads=nthread)
end3 = time.time() - start

""" By far the most efficient method """
pyfftw.forget_wisdom()
start = time.time()
b4 = numpy.zeros_like(a)
fft = pyfftw.FFTW( a, b4, axes=(0,1), direction='FFTW_FORWARD', flags=('FFTW_MEASURE', ), threads=nthread, planning_timelimit=None )
fft()
end4 = time.time() - start

""" 
For large arrays avoiding the copy is very important, 
doing this I get a speedup of 2x compared to not using it 
"""
pyfftw.forget_wisdom()
start = time.time()
b5 = numpy.zeros_like(a)
fft = pyfftw.builders.fft2(a, s=None, axes=(-2, -1), overwrite_input=False, planner_effort='FFTW_MEASURE', threads=nthread, auto_align_input=False, auto_contiguous=False, avoid_copy=True)
b5 = fft()
end5 = time.time() - start



print('numpy.fft.fft2:                        %.3f secs.' % end1)
print('pyfftw.interfaces.scipy_fftpack.fft2:  %.3f secs.' % end2)
print('pyfftw.interfaces.numpy_fft.fft2:      %.3f secs.' % end3)
print('pyfftw.FFTW:                           %.3f secs.' % end4)
print('pyfftw.builders:                       %.3f secs.' % end5)

64 ビット浮動小数点数を使用した、4 コア i5 CPU での出力時間の例:

numpy.fft.fft2:                        1.537 secs.
pyfftw.interfaces.scipy_fftpack.fft2:  0.248 secs.
pyfftw.interfaces.numpy_fft.fft2:      0.248 secs.
pyfftw.FFTW:                           0.084 secs.
pyfftw.builders:                       0.143 secs.

32 ビット浮動小数点数を使用した、私の 4 コア i5 CPU での出力時間の例:

numpy.fft.fft2:                        1.414 secs.
pyfftw.interfaces.scipy_fftpack.fft2:  0.066 secs.
pyfftw.interfaces.numpy_fft.fft2:      0.066 secs.
pyfftw.FFTW:                           0.043 secs.
pyfftw.builders:                       0.043 secs.
于 2016-04-29T14:21:58.717 に答える
1

私が見つけた解決策は、ビルダー インターフェイスを使用することでした。

fft = pyfftw.builders.fft2(a, overwrite_input=True, planner_effort='FFTW_ESTIMATE', threads=multiprocessing.cpu_count())
b = fft()
于 2014-08-29T11:40:08.337 に答える