numpy fftn очень неэффективен для 2d fft нескольких изображений - PullRequest
3 голосов
/ 19 сентября 2019

Я хотел вычислить преобразование Фурье для нескольких изображений.Поэтому я сравнивал numpy fft.fftn с грубой силой для цикла.

Этот код я использовал для сравнения 2 подходов (в блокноте Jupyter):

import numpy as np

x = np.random.rand(32, 256, 256)

def iterate_fft(arr):
    k = np.empty_like(arr, dtype=np.complex64)
    for i, a in enumerate(arr):
        k[i] = np.fft.fft2(a)
    return k

k_it = iterate_fft(x)
k_np = np.fft.fftn(x, axes=(1, 2))
np.testing.assert_allclose(k_it.real, k_np.real)
np.testing.assert_allclose(k_it.imag, k_np.imag)
%%timeit
k_it = iterate_fft(x)

Вывод: 63.6 ms ± 1.23 ms per loop (mean ± std. dev. of 7 runs, 10 loops each)

%%timeit
k_np = np.fft.fftn(x, axes=(1, 2))

Вывод: 122 ms ± 1.79 ms per loop (mean ± std. dev. of 7 runs, 10 loops each)

Почему такая огромная разница?

1 Ответ

1 голос
/ 19 сентября 2019

Эти процедуры в numpy в настоящее время, похоже, предполагают, что последнее измерение всегда будет наименьшим.Когда это действительно так, fftn быстрее, иногда намного.

Тем не менее, я получаю гораздо меньшую разницу в производительности между этими двумя методами, чем вы (с Python 3.7.4, numpy 1.17.2).Для вашего примера, iterate_fft занимает 46 мс, а ffn - 50. Но если я переверну оси, до (256, 256, 32), я получу 55 мс и 40 мс соответственно.Если двигаться еще дальше с формой (256, 256, 2), я получаю 21 мс и 4 мс соответственно.

Обратите внимание, что, если производительность действительно является проблемой, доступны другие библиотеки FFT, которые работают лучше в некоторых ситуациях,Также полный пакет fftpack в scipy может иметь очень отличную производительность, чем более ограниченный код в numpy.

Обратите внимание, что ваше использование fftn в основном делает:

x = np.random.rand(32, 256, 256)

a = np.fft.fft(x, n=256, axis=2)
a = np.fft.fft(a, n=256, axis=1)

np.testing.assert_allclose(np.fft.fftn(x, axes=(1, 2)), a)
...