2016-11-20 8 views
0

私はリストを取りCython機能を書いている/引数として数字のmemoryviewを入力し、同じ長さの型付きMemoryviewを返します。Cython - 任意の長さの戻り型指定されたMemoryView

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)エラーを取得し始めました。私はこれがメモリ管理の問題であることを認識していますが、関数から返された型付きメモリビューのメモリを管理する方法の例は見つかりません。私が見つけた唯一の有用な情報はmemory allocationで、result_arrの寿命をPythonオブジェクトに結びつけ、__dealloc__メソッドを使用してメモリを解放することを推奨しています。

メモリを解放するためのPythonクラスの作成に関係しないmemoryviewガベージコレクションを管理する方法はありますか?

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

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 

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

+0

https://cython.readthedocs.io/en/stable/src/userguide/memoryviews.html#cython-arraysと '.callback_free_data'を参照してください。 – DavidW

答えて

0

型付きmemoryviewは、名前が示すとおり、メモリバッファへのビューを意味します。そのメモリは所有していませんが、効率的なアクセス方法を提供します。あなたが参照している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番目の関数では、メモリを割り当てて、ビューを作成してから再度解放するようです。このメモリビューが表示されているメモリは、もはや存在しなくなりました。あなたは正しいので、メモリは正しく解放されます。しかし今、メモリビューはもはやあなたのために使用されていません。

関連する問題