6

特定の Python スクリプトのメモリ使用量について完全に混乱しています。いくつかの SO Questions/ Answersからのアドバイスにもかかわらず、使用法をプロファイルする方法が本当にわからないと思います。

私の質問は次のとおりです。の違いは何ですか? 1 つは大量のメモリを使用していると言われ、もう 1 つはそうではないと言われるのはなぜですか?memory_profilerguppy.hpy

私はpysam、バイオインフォマティクスの SAM/BAM ファイルにアクセスするためのライブラリである を使用しています。私のメイン スクリプトは、SAM (ASCII) を BAM (バイナリ) に変換し、その間にファイルを操作するときに、すぐにメモリ不足になります。

各ステップでどれだけのメモリが割り当てられるかを理解するために、小さなテスト例を作成しました。

# test_pysam.py: 

import pysam
#from guppy import hpy

TESTFILENAME = ('/projectnb/scv/yannpaul/MAR_CEJ082/' +
                'test.sam')
#H = hpy()

@profile # for memory_profiler
def samopen(filename):
#    H.setrelheap()
    samf = pysam.Samfile(filename)
#    print H.heap()
    pass


if __name__ == "__main__":
    samopen(TESTFILENAME)

memory_profiler ( python -m memory_profiler test_pysam.py) を使用してメモリ使用量を監視すると、次の出力が得られます。

Filename: test_pysam.py

Line #    Mem usage    Increment   Line Contents
================================================
    10                             @profile # for memory_profiler
    11                             def samopen(filename):
    12     10.48 MB      0.00 MB   #    print H.setrelheap()
    13    539.51 MB    529.03 MB       samf = pysam.Samfile(filename)
    14                             #    print H.heap()
    15    539.51 MB      0.00 MB       pass

@profile次に、デコレータをコメントアウトし、guppy関連する行のコメントを解除すると、次の出力が得られます ( python test_pysam.py)。

Partition of a set of 3 objects. Total size = 624 bytes.
 Index  Count   %     Size   % Cumulative  % Kind (class / dict of class)
     0      1  33      448  72       448  72 types.FrameType
     1      1  33       88  14       536  86 __builtin__.weakref
     2      1  33       88  14       624 100 csamtools.Samfile

行 13 の合計サイズは、あるケースでは 529.03 MB、別のケースでは 624 バイトです。ここで実際に何が起こっているのですか?「test.sam」は ~52MB の SAM (これも ASCII 形式) ファイルです。pysamに関連する C ライブラリのラッパーであるため、 を深く掘り下げるのは少し難しいですsamtools。が実際に何であるかに関係なく、Samfileそれを作成するためにどれだけのメモリが割り当てられているかを知ることができるはずだと思います。大規模で複雑な Python プログラムの各ステップのメモリ使用量を正しくプロファイリングするには、どの手順を使用すればよいですか?

4

1 に答える 1

9

memory_profiler と guppy.hpy の違いは何ですか?

ヒープの内部ビューと、プログラムの OS の外部ビューの違いを理解していますか? (たとえば、Python インタープリターがfree1MB を呼び出した場合、OS に 1MB 相当のページが返されることはありません。その理由は複数あります)。 OS にメモリ使用量を問い合わせる。guppy は、ヒープ構造から内部的にそれを把握しています。

さらに、memory_profiler には guppy にはない機能が 1 つあります。コードの各行の後にレポートを出力するように関数を自動的にインストルメント化します。それ以外の場合は、はるかに単純で簡単ですが、柔軟性が低くなります。やりたいことがわかっていて、memory_profiler がそれを実行していないように見える場合は、おそらく実行できません。グッピーを使えばできるかもしれないので、ドキュメントとソースを調べてください。

1 つは大量のメモリを使用していると言われ、もう 1 つはそうではないと言われるのはなぜですか?

確かなことはわかりませんが、いくつかの推測があります。答えは、複数の組み合わせになる可能性があります。

おそらく、samtools は mmap を使用して十分に小さいファイルを完全にメモリにマップします。これにより、ページの使用量がファイルのサイズだけ増加しますが、ヒープの使用量はまったく増加しません。

おそらく、samtools または pysam は、すぐに解放される多くの一時オブジェクトを作成します。多くの断片化 (各ページに 2 つのライブ PyObject のみ) があるか、システムの malloc が割り当て方法のために多くのノードをフリーリストに保持する必要があると判断したか、またはページが返されなかった可能性があります。または、返されたページが OS の VM に回収されていない可能性があります。正確な理由を推測することはほとんどの場合不可能です。最も簡単な方法は、解放されたメモリが返されないと仮定することです。

大規模で複雑な Python プログラムの各ステップのメモリ使用量を正しくプロファイリングするには、どの手順を使用すればよいですか?

OS の観点からメモリ使用量について質問している場合、memory_profiler はまさにあなたが望むことを行っています。pysam を深く掘り下げるのは難しいかもしれませんが、いくつかの関数を@profileデコレータでラップするのは簡単です。次に、どの C 関数がメモリを担当しているかがわかります。さらに深く掘り下げたい場合は、明らかに C レベルでプロファイリングする必要があります (samtools ドキュメントまたは samtools コミュニティからの情報がない限り)。

于 2012-09-21T17:36:44.370 に答える