5

質問

バイナリ データをロードし、numpy 操作を実行し、結果を保存する小さな python バッチ プロセッサを作成しました。必要以上に多くのメモリを消費します。同様のスタックオーバーフローの議論を見て、さらに推奨事項を求めたいと思います。

バックグラウンド

スペクトル データを RGB に変換します。スペクトル データは、Band Interleaved by Line (BIL) イメージ ファイルに保存されます。そのため、データを 1 行ずつ読み取って処理します。numpy 配列を返す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

ノート

rangexrangeに置き換えましたが、劇的な改善はありませんでした。三次補間が最速ではないことは承知していますが、これは CPU 消費に関するものではありません。

4

1 に答える 1

1

コメントありがとうございます。それらはすべて、メモリ消費を少し改善するのに役立ちました。しかし、最終的に、メモリ消費の主な理由が何であるかを突き止めました。

SpectralPython イメージには、Numpy Memmapオブジェクトが含まれています。これは、ハイパースペクトル データ キューブのデータ構造と同じ形式です。(BIL形式(nrows、nbands、ncols)の場合) 呼び出し時:

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

画像は numpy 配列の戻り値として返されるだけでなく、hyp.memmap にもキャッシュされます。2 回目の呼び出しは高速ですが、私の場合、OS が文句を言うまでメモリが増加します。memmap は実際には優れた実装であるため、将来の作業で直接利用します。

于 2012-12-05T12:14:32.473 に答える