0

数値のリスト/型付きメモリビューを引数として取り、同じ長さの型付きメモリビューを返す Cython 関数を作成しました。

def test(list_data):
    cdef unsigned int n = len(list_data)
    cdef unsigned int i = 0
    cdef double *results_arr = <double*>malloc(n* sizeof(double) )
    cdef double[:] results = <double[:n]>results_arr
    for i in range(n):
        results[i] = 220 - list_data[i]
    return results

数千回のテストを実行した後、Segmentation fault (core dumped)エラーが発生し始めました。これはメモリ管理の問題であることは認識していますが、関数によって返される型指定されたメモリビューのメモリを管理する方法の例が見つかりません。私が見つけた唯一の役立つ情報は、メモリ割り当てに関するresult_arrもので、のライフタイムをPython オブジェクトに結び付け、__dealloc__メソッドを使用してメモリを解放することを推奨しています。

メモリの割り当てを解除するための python クラスの作成を伴わないメモリビュー ガベージ コレクションを管理する方法はありますか?

編集:これを試してみましたが、正しい方法でメモリを解放しているようです。

def test(list_data):
    cdef unsigned int n = len(list_data)
    cdef unsigned int i = 0
    cdef double *arr = <double*>malloc(n* sizeof(double) )
    if not arr:
        raise MemoryError()
    cdef double[:] results = <double[:n]>arr
    for i in range(n):
        results[i] = 220 - list_data[i]
    free(arr)
    return results

なぜこれが機能し、メモリを管理するためのより良い方法がありますか?

4

1 に答える 1

1

型指定されたメモリ ビューは、その名前が示すように、メモリ バッファーへのビューを意味します。そのメモリの一部を所有するわけではありませんが、効率的なアクセス方法を提供します。あなたが参照している cython ドキュメントの一部は、基になるヒープに割り当てられた c-array を python ガベージ コレクターに結び付ける方法です。ここで行っているように c メモリ割り当てを使用する場合は、それについても責任を負う必要があります。これは、現在 c レベルで作業しているためであり、c は無料で何もしません。関数は割り当てられたメモリのビューを作成しますが、それを参照しているポインターを破棄します。現在、このメモリは、それを解放する責任を負うものは何もありません。

C の世界に入りたくない場合は、データを python の numpy 配列に読み取り、代わりにこの配列を cython 関数に渡すことをお勧めします。Python と numpy は、そのようなことに非常に適しています。

ただし、malloc を使用する場合は、代わりに拡張型でラップすることもできます。

cdef class mymemory:
    cdef:
        double *arr
        double[::1] results

    def __cinit__(self, int n):
        self.arr = <double*>malloc(n*sizeof(double))

    def __init__(self, int n):
        self.results = <double[:n]> arr

        """
        Some code for filling in the results.
        """

    def __dealloc(self):
        if self.arr != NULL:
            free(self.arr)

これで、mymemory がガベージ コレクションされると、基になる c 配列が解放されます。あなたがそれを求めたので、それは代替手段ですが、これよりも numpy をお勧めします。

2番目の関数では、メモリを割り当て、ビューを作成してから再度解放しているようです。現在、このメモリビューが表示しているメモリは存在しません。そうです、メモリは正しく解放されます。しかし今、memoryview はもはや役に立ちません。

于 2016-11-21T11:15:50.850 に答える