2011-10-18 14 views
1

私はここに手を投げて、NumpyのC APIの新しいNpyIter APIについて十分に知っている人に、私が間違っていることをすぐに教えてくれることを願っています。NpyIter(新しいAPI)による直接データアクセスはどのように機能しますか?どのようにchar *型を扱うのですか?

私は形状の配列を持っています(本当に大きく、多少大きめです)。要素はdouble> = 0.です。すべての行について、最も大きな値に合計される連続しない非ゼロ値の合計を見つける必要があります。 Pythonだけでこれをすばやく行う方法はわかりません(本当に大きいのは〜1e5時です)ので、代わりにWeaveを使用しています。私の古いコードで

、私は次のように持っていた:

  double *p1,*res; 
      double g,d,q; 
      PyArrayIterObject *itr; 
      int axis = 1; 
      g = 0; 
      d = 0; 
      itr = (PyArrayIterObject *) PyArray_IterAllButAxis(py_x,&axis); 
      while(PyArray_ITER_NOTDONE(itr)) { 
       const int go = x_array->strides[axis]/sizeof(double); 
       p1 = (double *) PyArray_ITER_DATA(itr); 
       res = (double *) PyArray_GETPTR1(py_r,itr->index); 
       g = 0; 
       d = 0; 
       for (int i = 0; i < x_array->dimensions[axis]; i++) { 
        d+=*p1; 
        if (d>g) g=d; 
        if ((*p1)==0) d=0; 
        p1+=go; 
       } 
       *res = g; 
       PyArray_ITER_NEXT(itr); 
      } 
      PyArray_free(itr); 

これは動作しますが、それはひどくメモリリークが発生します。私はそれを漏らさないようにする方法がわかりません。古いPyArrayIterのドキュメントは、メモリ管理の面ではむしろ欠けています。

NpyIter APIを使用して新しいコードを書き込もうとしましたが、メモリ管理より以外ののドキュメントが欠けています。具体的には、実際の配列値にどのようにアクセスするのかについては全くわかりません。私は以下を試しました:

  char *p1; 
      double *res; 
      char **p1p; 
      double g,d,q; 
      int go; 
      NpyIter* iter; 
      NpyIter_IterNextFunc *iternext; 
      g = 0; 
      d = 0; 
      iter = NpyIter_New(x_array, NPY_ITER_READONLY|NPY_ITER_EXTERNAL_LOOP, NPY_KEEPORDER, NPY_NO_CASTING, NULL); 
      iternext = NpyIter_GetIterNext(iter, NULL); 
      p1p = NpyIter_GetDataPtrArray(iter); 

      do { 
       p1 = *p1p; 
       const int go = x_array->strides[1]/sizeof(double); 
       res = (double *) PyArray_GETPTR1(py_r,NpyIter_GetIterIndex(iter)); 
       g = 0; 
       d = 0; 
       for (int i = 0; i < x_array->dimensions[1]; i++) { 
        d+= p1; 
        if (d>g) g=d; 
        if ((*p1)==0) d=0; 
        p1+=go; 
       } 
       *res = g; 
      } while(iternext(iter)); 

      NpyIter_Deallocate(iter); 

しかし、これは明らかにchar *対double *のために動作しません。しかし、NpyIter_GetDataPtrArrayから返された(char **)をどのようにして実際の配列値に変換するかは分かりません。ドキュメントは非常に有益ではなく、与えられていないchar *を使用します。

どのように動作し、メモリをリークさせない方法でこれを行うことができますか?

+0

私はNPyIter APIを一度も使用していませんが、メモリに直接アクセスできない理由はありますか?私はnumpy配列でctypesを使用して多くの喜びを持っています。その通常はメモリブロックです。 –

答えて

2

最初のケースでは、メモリのリークを避けるために、通常のPyObjectメモリ管理ルール、Py_DECREFPyArrayIterObjectを使用する必要があります。 (PyArray_freeは全く異なる何かをする。)

NpyIterについて:

データへのアクセスを取得するには、グラブ(double*)(*dataptr)

あなたが行っていることを正確に把握していない場合は、NPY_ITER_EXTERNAL_LOOPを使用しないでください。 IterAllButAxisの振る舞いを再現するには、繰り返しから反復したくない軸を削除するにはNpyIter_RemoveAxisに電話する必要があります。

関連する問題