我正在尝试使用 FFT 和 pyfftw 实现 3d 卷积。我使用在 SO 的另一篇文章中发布的代码作为基础:
class CustomFFTConvolution(object):
def __init__(self, A, B, threads=1):
shape = (np.array(A.shape) + np.array(B.shape))-1
#shape=np.array(A.shape) - np.array(B.shape)+1
if np.iscomplexobj(A) and np.iscomplexobj(B):
self.fft_A_obj = pyfftw.builders.fftn(
A, s=shape, threads=threads)
self.fft_B_obj = pyfftw.builders.fftn(
B, s=shape, threads=threads)
self.ifft_obj = pyfftw.builders.ifftn(
self.fft_A_obj.get_output_array(), s=shape,
threads=threads)
else:
self.fft_A_obj = pyfftw.builders.rfftn(
A, s=shape, threads=threads)
self.fft_B_obj = pyfftw.builders.rfftn(
B, s=shape, threads=threads)
self.ifft_obj = pyfftw.builders.irfftn(
self.fft_A_obj.get_output_array(), s=shape,
threads=threads)
def __call__(self, A, B):
s1=np.array(A.shape)
s2=np.array(B.shape)
fft_padded_A = self.fft_A_obj(A)
fft_padded_B = self.fft_B_obj(B)
ret= self.ifft_obj(fft_padded_A * fft_padded_B)
return self._centered(ret, s1 - s2 + 1)
def _centered(self,arr, newshape):
# Return the center newshape portion of the array.
newshape = np.asarray(newshape)
currshape = np.array(arr.shape)
startind = (currshape - newshape) // 2
endind = startind + newshape
myslice = [slice(startind[k], endind[k]) for k in range(len(endind))]
return arr[tuple(myslice)]
我的数据 A 的形状为 (931, 411, 806),我的过滤器 B 的形状为 (32, 32, 32)。如果我在 24 核机器上使用 24 个线程运行此代码,则该操作需要 263 秒。现在,如果我在同一台机器上运行相同的实验,但这次 A 的形状为 (806, 411, 931)只是轴的交换,代码只需要 16 秒。这是什么原因?是否有获得最佳性能的经验法则?也许填充尺寸之一?谢谢!