Использование памяти Python pyfftw

Задача: Быстрое вычисление БПФ в реальном масштабе для большого массива.

Форма массива a это (103430 x 1 x 100 x 900), где размеры (время, фиктивная яркость, долгота, широта), скажем так (~100000 x 1 x 100 x 900). БПФ должно быть рассчитано по осям 0,2,3.

Numpy.fft.fftn(a,axes=(0,2,3)) занимает слишком много времени (~6 часов), поэтому я хочу использовать pyfftw. Я пытался с помощью pyfftw.interfaces.numpy_fft.fftn(a,axes=(0,2,3)),

Проблема: потребление памяти входного массива соответствует ок. 13 % оперативной памяти нашей машины, таким образом, включая массив вывода, он должен составлять ~ 40 % (вывод сложный). Однако во время вычислений использование памяти увеличивается почти до 100 %, пока команда не завершится с ошибкой памяти в PyCharm.

Я создал уменьшенную версию массива случайных чисел (10000,1100,900) с потреблением памяти ~ 1,3%. Использование памяти временно возрастает до ~ 10,6 %, если БПФ выполняется только по оси 3, и до ~ 13 %, если выполняется по осям 0,2,3, как упоминалось ранее.

Я предполагаю, что копии промежуточного массива вызывают такое высокое использование памяти. Я погуглил документацию по pyfftw и попытался установить auto_align_input а также auto_contiguous варианты ложных, а также overwrite_input Правда, без успеха. Я также попытался создать объект FFTW сам и поиграться с параметрами.

MATLAB, также использующий FFTW, выполняет задачу за (100000,1000000) за несколько секунд, при этом максимальное потребление памяти составляет ~40 %. Очевидно, что промежуточные копии массива, вероятная причина дополнительной памяти, используемой при запуске pyfftw, с точки зрения алгоритма не нужны, как показывает пример MATLAB.

Вопрос: есть ли какой-нибудь способ принудительно установить полное отсутствие потребления памяти в pyfftw? Если так, то как? Какие параметры?


PS: два возможных пути обхода

  1. сохранить массив из python для подгонки, загрузить его в MATLAB, выполнить FFT, сохранить его из MATLAB для подгонки и загрузить обратно в python
  2. делать повторные одномерные БПФ через циклы for; тогда издержки памяти не будут релевантными, и результаты могут быть вставлены в выходной массив как часть цикла

Однако я бы хотел этого избежать. Должен быть способ выполнить одно 3D-FFT, которое не будет занимать всю оперативную память, имеющуюся на машине (512 ГБ).


Обновление: я выполнил следующие команды:

a = np.random.rand(10000,1,100,900)
run_fftw = pyfftw.builders.fftn(a, axes=(3,), auto_contiguous=False, auto_align_input=False, avoid_copy=True)
b = run_fftw()

Оказывается, что используемая память на самом деле является памятью a + b + комплексно транслируемой копии внутренней функции run_fftw(). Это может быть уменьшено до памяти, передаваемой комплексом a + b, если a уже передана комплексу до определения run_fftw или путем удаления a после создания run_fftw.

Так как проблема квазирешена прямо сейчас (благодаря @HenryGomersall), единственный вопрос любопытства заключается в том, существует ли схема от реального к сложному, вызываемая через fftn, которая выдает все частоты, включая отрицательные, и не транслирует входные данные изнутри. массив к сложному.

Я понимаю, что для этого случая можно использовать rfftn. Это, однако, отбрасывает (избыточные) отрицательные частоты.

0 ответов

Другие вопросы по тегам