Эффективная память Python пакетной обработки

вопрос

Я написал небольшой пакетный процессор Python, который загружает двоичные данные, выполняет множество операций и сохраняет результаты. Он потребляет гораздо больше памяти, чем должен. Я посмотрел на подобные обсуждения переполнения стека и хотел бы попросить дальнейшие рекомендации.

фон

Я конвертирую спектральные данные в rgb. Спектральные данные хранятся в файле изображения с чередованием полос (BIL). Вот почему я читаю и обрабатываю данные построчно. Я читаю данные, используя Spectral Python Library, которая возвращает пустые массивы. hyp - дескриптор большого спектрального файла: hyp.ncols=1600, hyp.nrows=3430, hyp.nbands=160

код

import spectral
import numpy as np
import scipy

class CIE_converter (object):
   def __init__(self, cie):
       self.cie = cie

    def interpolateBand_to_cie_range(self, hyp, hyp_line):
       interp = scipy.interpolate.interp1d(hyp.bands.centers,hyp_line, kind='cubic',bounds_error=False, fill_value=0)
       return interp(self.cie[:,0])

    #@profile
    def spectrum2xyz(self, hyp):
       out = np.zeros((hyp.ncols,hyp.nrows,3))
       spec_line = hyp.read_subregion((0,1), (0,hyp.ncols)).squeeze()
       spec_line_int = self.interpolateBand_to_cie_range(hyp, spec_line)
       for ii in xrange(hyp.nrows):
          spec_line = hyp.read_subregion((ii,ii+1), (0,hyp.ncols)).squeeze()
          spec_line_int = self.interpolateBand_to_cie_range(hyp,spec_line)
          out[:,ii,:] = np.dot(spec_line_int,self.cie[:,1:4])
       return out

потребление памяти

Все большие данные инициализируются вне цикла. Моя наивная интерпретация заключалась в том, что потребление памяти не должно увеличиваться (Я использовал слишком много Matlab?) Может кто-нибудь объяснить мне фактор увеличения 10? Это не линейно, так как hyp.nrows = 3430. Есть ли рекомендации по улучшению управления памятью?

  Line #    Mem usage    Increment   Line Contents
  ================================================
  76                                 @profile
  77     60.53 MB      0.00 MB       def spectrum2xyz(self, hyp):
  78    186.14 MB    125.61 MB           out = np.zeros((hyp.ncols,hyp.nrows,3))
  79    186.64 MB      0.50 MB           spec_line = hyp.read_subregion((0,1), (0,hyp.ncols)).squeeze()
  80    199.50 MB     12.86 MB           spec_line_int = self.interpolateBand_to_cie_range(hyp, spec_line)
  81                             
  82   2253.93 MB   2054.43 MB           for ii in xrange(hyp.nrows):
  83   2254.41 MB      0.49 MB               spec_line = hyp.read_subregion((ii,ii+1), (0,hyp.ncols)).squeeze()
  84   2255.64 MB      1.22 MB               spec_line_int = self.interpolateBand_to_cie_range(hyp, spec_line)
  85   2235.08 MB    -20.55 MB               out[:,ii,:] = np.dot(spec_line_int,self.cie[:,1:4])
  86   2235.08 MB      0.00 MB           return out

заметки

Я заменил диапазон на xrange без радикальных улучшений. Я знаю, что кубическая интерполяция не самая быстрая, но речь идет не о загрузке процессора.

1 ответ

Спасибо за комментарии. Все они помогли мне немного улучшить потребление памяти. Но в конце концов я выяснил, что является основной причиной потребления памяти:

SpectralPython Изображения содержат объект Numpy Memmap. Он имеет тот же формат, что и структура данных куба гиперспектральных данных. (в случае формата BIL (nrows, nbands, ncols)) При вызове:

spec_line = hyp.read_subregion((ii,ii+1), (0,hyp.ncols)).squeeze()

изображение не только возвращается как возвращаемое значение массива, но также кэшируется в hyp.memmap. Второй вызов будет быстрее, но в моем случае память просто увеличивается, пока ОС не жалуется. Поскольку memmap на самом деле является отличной реализацией, я воспользуюсь ее преимуществами в будущей работе.

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