Следующие загрузки программы два изображения с PyGame, преобразовывает их в массивы Numpy и затем выполняет некоторые другие операции Numpy (такие как FFT) для испускания конечного результата (нескольких чисел). Исходные данные могут быть большими, но в любой момент только один или два больших объекта должны быть живыми.
Тестовое изображение о 10M пиксели, который переводит в 10 МБ, после того как это - greyscaled. Это преобразовывается в массив Numpy dtype uint8
, который после некоторой обработки (применение окон Хэмминга), массив dtype float64
. Два изображения загружаются в массивы этот путь; позже FFT ступает результат в массив dtype complex128
. До добавления чрезмерного gc.collect
вызовы, размер памяти программ имел тенденцию увеличиваться с каждым шагом. Кроме того, кажется, что большинство операций Numpy даст результат в самой высокой доступной точности.
Запущение теста (без gc.collect
вызовы) на моих результатах машины Linux на 1 ГБ в длительной перегрузке, которой я не ожидал. У меня еще нет подробной статистики использования памяти - я попробовал некоторые модули Python и time
команда напрасно; теперь я изучаю valgrind. Наблюдение PS (и контакт с безразличностью машины на более поздних этапах теста) предлагают максимальное использование памяти приблизительно 800 МБ.
10 миллионов массивов ячеек complex128 должны занять 160 МБ. Наличие (идеально) самое большее двух из них живет когда-то, плюс не - иллюзорные библиотеки Python и Numpy и другие принадлежности, вероятно, средства допускать 500 МБ.
Я могу думать о двух углах, от которых можно приняться за решение проблемы:
Отбрасывание промежуточного звена выстраивает как можно скорее. Это что gc.collect
вызовы для - они, кажется, улучшили ситуацию, поскольку она теперь завершается только с несколькими минутами перегрузки ;-). Я думаю, что можно ожидать, что интенсивно использующее память программирование на языке как Python потребует некоторого ручного вмешательства.
Используя менее - точный Numpy выстраивает на каждом шаге. К сожалению, операции это возвращаемые массивы, как fft2
, кажись, не позволить типу быть указанным.
Таким образом, мой основной вопрос: существует ли способ указать выходную точность в операциях над массивом Numpy?
В более общем плане есть ли другие сохраняющие общую память методы при использовании Numpy?
Кроме того, Numpy имеет более идиоматический способ освободить матрицу элементов памяти? (Я предполагаю, что это оставило бы объект массива живым в Python, но в неприменимом состоянии.) Явное удаление, сопровождаемое непосредственным GC, чувствует hacky.
import sys
import numpy
import pygame
import gc
def get_image_data(filename):
im = pygame.image.load(filename)
im2 = im.convert(8)
a = pygame.surfarray.array2d(im2)
hw1 = numpy.hamming(a.shape[0])
hw2 = numpy.hamming(a.shape[1])
a = a.transpose()
a = a*hw1
a = a.transpose()
a = a*hw2
return a
def check():
gc.collect()
print 'check'
def main(args):
pygame.init()
pygame.sndarray.use_arraytype('numpy')
filename1 = args[1]
filename2 = args[2]
im1 = get_image_data(filename1)
im2 = get_image_data(filename2)
check()
out1 = numpy.fft.fft2(im1)
del im1
check()
out2 = numpy.fft.fft2(im2)
del im2
check()
out3 = out1.conjugate() * out2
del out1, out2
check()
correl = numpy.fft.ifft2(out3)
del out3
check()
maxs = correl.argmax()
maxpt = maxs % correl.shape[0], maxs / correl.shape[0]
print correl[maxpt], maxpt, (correl.shape[0] - maxpt[0], correl.shape[1] - maxpt[1])
if __name__ == '__main__':
args = sys.argv
exit(main(args))
Это
на SO говорит: «Scipy 0.8 будет поддерживать одинарную точность почти для всего кода fft»,
и SciPy 0.8.0 beta 1 только что вышла.
(Сам не пробовал, трусливый.)
Если я правильно понимаю, вы вычисляете свертку между двумя изображениями. Пакет Scipy содержит специальный модуль для этого ( ndimage ), который может быть более эффективным с точки зрения памяти, чем "ручной" подход с помощью преобразований Фурье. Было бы хорошо попробовать использовать его вместо того, чтобы проходить через Numpy.