2013-07-25 27 views
25
yoluyla C++ yöntemlere numpy diziler dönen

özellikle kullanışlı bir Simple wrapping of C code with cython olmanın bu sitede Cython içinde numpy kullanmayla ilgili birçok soru vardır. Bununla birlikte, özellikle bellek bitişik dizilerinin geçirilmesini sağlayarak, cyton/numpy arabirimi api seems to have changed a bit, özellikle de .Geçme ve Cython

o Cython bir sarmalayıcı işlevi yazmak için en iyi yolu nedir:

  • muhtemel ancak mutlaka bitişik olmayan bir numpy dizi alır
  • imza double* data_in, double* data_out
  • ile bir C++ sınıfı yöntemini çağırır Yöntemin yazdığı double* numpy dizisini döndürür?

Benim deneyin aşağıdaki gibidir:

cimport numpy as np 
import numpy as np # as suggested by jorgeca 

cdef extern from "myclass.h": 
    cdef cppclass MyClass: 
     MyClass() except + 
     void run(double* X, int N, int D, double* Y) 

def run(np.ndarray[np.double_t, ndim=2] X): 
    cdef int N, D 
    N = X.shape[0] 
    D = X.shape[1] 

    cdef np.ndarray[np.double_t, ndim=1, mode="c"] X_c 
    X_c = np.ascontiguousarray(X, dtype=np.double) 

    cdef np.ndarray[np.double_t, ndim=1, mode="c"] Y_c 
    Y_c = np.ascontiguousarray(np.zeros((N*D,)), dtype=np.double) 

    cdef MyClass myclass 
    myclass = MyClass() 
    myclass.run(<double*> X_c.data, N, D, <double*> Y_c.data) 

    return Y_c.reshape(N, 2) 

Bu kod derler ama ille optimal değildir. Yukarıdaki snippet'i iyileştirme konusunda herhangi bir öneriniz var mı?

ve

(2) zamanında çağırmak olduğunda) "np hattı X_c = ... tanımlı değildir" atar ve. kesin test kodu ve hata iletisi aşağıdaki gibidir:

import numpy as np 
import mywrapper 
mywrapper.run(np.array([[1,2],[3,4]], dtype=np.double)) 

# NameError: name 'np' is not defined [at mywrapper.pyx":X_c = ...] 
# fixed! 

+5

"numpy modülü hakkında özel derleme zamanı bilgisi almak için kullanılır"] (http://docs.cython.org/src/tutorial/numpy.html#adding-types)). – jorgeca

+0

@jorgeca Yorumunuzun OP sorusuna cevap verdiğini tahmin ediyorum ... –

+1

@SaulloCastro Bir yorum olarak gönderdim çünkü küçük bir engel olduğunu düşündüm, ancak bu arayüzleri yazmanın en iyi yolunun ne olduğunu bilmiyorum. – jorgeca

cevap

17

Temelde doğru var. İlk olarak, umarım optimizasyon büyük bir anlaşma olmamalıdır. İdeal olarak, çoğu zaman değil cythnon sarıcı kodunda, C++ çekirdek içinde harcanmaktadır.

o kodunuzu basitleştirecek yapabilir birkaç üslup değişiklikler var. (1) 1D ve 2D dizileri arasında yeniden şekillendirme gerekli değildir. verilerinizin bellek düzenini bildiğinizde (C dereceden fortran sipariş vs, uzun adımlarla, vs), size C++ indeksine kendinizi gidiyoruz belleğin sadece bir yığın olarak diziyi görebilirsiniz, böylece numpy en ndim kokan C++ tarafında önemli değil - sadece o işaretçiyi görüyor. Gerekli hiçbir açık döküm - - &X[0,0] kullanarak (2) Cython adresini-operatörü & kullanarak, biraz daha temiz bir şekilde diziye başlamadan işaretçi alabilirsiniz.

Yani bu orijinal snippet'in benim Düzenlenen sürümü:

cimport numpy as np 
import numpy as np 

cdef extern from "myclass.h": 
    cdef cppclass MyClass: 
     MyClass() except + 
     void run(double* X, int N, int D, double* Y) 

def run(np.ndarray[np.double_t, ndim=2] X): 
    X = np.ascontiguousarray(X) 
    cdef np.ndarray[np.double_t, ndim=2, mode="c"] Y = np.zeros_like(X) 

    cdef MyClass myclass 
    myclass = MyClass() 
    myclass.run(&X[0,0], X.shape[0], X.shape[1], &Y[0,0]) 

    return Y 
Hala [np` olarak numpy fonksiyonları (`cimport numpy kullanmak için` .pyx` dosyasında np` olarak ithal Numpy `zorunda
+1

Say, bu diziyi geçmek yerine Cython'da yazılan bir bellek görüntüsü ile yapılabilir mi? Bunun bazı hafıza yüklerini, vb. – krishnab