2

「イベント」を生成するイテレータ/ジェネレータがあります。イベントは、名前、タイムスタンプ、および値で構成されます。それらをNumPy配列に保存したい。これはで行われ_LoadTriples()ます:

def _LoadTriples(abortEvt, count=[1]):
    it = _YieldTriples()
    while True:
        if abortEvt.is_set():
            it.close()
            break
        t0 = time.time()
        self.allEvents.append(np.fromiter(it,
                                      dtype=[('sigNameIdx', 'i'),
                                             ('time', 'f'),
                                             ('value', 'f8')],
                                      count=count[-1]))
        dur = time.time() - t0
        if dur < 0.2:
            count.append(count[-1]*2)
        elif dur > 0.4 and count[-1] != 1:
            count.append(count[-1]/2)
        else:
            count.append(count[-1])

_YieldTriplesはジェネレーターでabortEvtあり、ユーザーが反復を中止したときに通知するイベントです。self.allEvents空のリストです。ここで、NumPy 配列に Triples を追加します。(name, timestamp, value).反復を中断する可能性が必要で、中断できないため、配列のリストですnumpy.fromiter。したがって、約 0.3 秒ごとに反復を停止できます。

それはすべてうまくいきます。しかし、ある例では、Python がリスト用に 300MB のメモリをすぐに使い切ってしまうことがあります。繰り返しを停止すると、いつ停止したかにもよりますが、リストに必要なのは最大10 MBだけですが、self.allEvents.append(np.fromiter(...))300MBへの呼び出しが数回使用された後、その理由がまったくわかりません。

self.allEventsさらに、このメモリは、その関数の呼び出しの直後に削除しても、プログラム全体を停止するまで解放されません。私がそれをリリースするのを妨げるいくつかの参照があるに違いありません. どのオブジェクトがリストへの参照を持っているかを確認する方法はありますか?

言及すべきもう1つのこと:関数は new として呼び出されますthreading.Threadが、メインスレッドはそれを待ちます...

編集:私は言及しませんでした.300MBが使用されると、リストが大きくなってもメモリは割り当てられません。リストは、いくつかの追加後にこのメモリを予約しているようです。

4

1 に答える 1

2

試してみてください:

def _LoadTriples(abortEvt, count=None):
    if count is None:
        count = [1]
    ...

変更可能なデフォルト引数は、問題を非常に迅速に引き起こす可能性があります。

于 2013-06-20T17:30:25.810 に答える