Soru Sayısal dizileri Cython üzerinden C ++ yöntemlerine geçirme ve döndürme


Bu sitede cython'da numpy kullanımı hakkında birçok soru var, özellikle yararlı olanlardan biri. C kodunun cython ile basit bir şekilde sarılması.

Ancak, cython / numpy arayüzü api biraz değişmiş gibi görünüyorÖzellikle, bellek bitişik dizilerin geçirilmesini sağlama ile.

Cython'da bir sarmalayıcı işlevi yazmanın en iyi yolu nedir:

  • Muhtemelen, ancak bitişik olmayan bir numpy dizisi alır
  • İmza ile C ++ sınıf yöntemini çağırır double* data_in, double* data_out
  • numpy dizisini döndürür double* yöntem yazdı?

Benim denemem aşağıda:

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 zorunlu değildir. Yukarıdaki snippet'i iyileştirme konusunda herhangi bir öneriniz var mı?

ve (2) atar ve "np satırda tanımlanmaz X_c = ...") çalışma zamanında çağırırken. Tam test kodu ve hata mesajı 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!


25
2017-07-25 10:10


Menşei


Hala zorundasın import numpy as np senin içinde .pyx numpy işlevlerini kullanacak dosya (cimport numpy as np  "numpy modülü hakkında özel derleme zamanı bilgisi almak için kullanılır"). - jorgeca
@jorgeca Yorumunuzun OP sorusunu cevapladığını düşünüyorum ... - Saullo G. P. Castro
@SaulloCastro Bir yorum olarak yayınladım çünkü küçük bir engel olduğunu düşündüm, ancak bu arayüzleri yazmanın en iyi yolunun ne olduğunu bilmiyorum. - jorgeca
@jorgeca Teşekkür ederim, hata mesajlarına neden olan eksik ifadelerdi. Ve haklısın, ben esas olarak iyimserlik arıyorum :-) - Michael Schubert


Cevaplar:


Temelde doğru anladın. İlk olarak, umarım optimizasyon büyük bir anlaşma olmamalıdır. İdeal olarak, çoğu zaman C ++ çekirdeğinizde, cythnon sarmalayıcı kodunda değil, harcanır.

Kodunuzu basitleştirecek birkaç stil değişikliği vardır. (1) 1D ve 2D dizileri arasında yeniden şekillendirme gerekli değildir. Verilerinizin bellek düzenini (C-sırası ve fortran düzeni, çizilme, vb.) Biliyorsanız, diziyi C ++'da indeksleyeceğiniz bir bellek parçası olarak görebilirsiniz, bu yüzden numpy'nin ndim'i ' C ++ tarafında önemli değil - sadece o işaretçiyi görüyor. (2) Cython'un adres-operatörünü kullanma &, işaretçiyi dizinin başlangıcına biraz daha temiz bir şekilde alabilirsiniz - açık bir döküm gerekmez - &X[0,0].

Yani bu, orijinal snippet'inin düzenlenmiş sürümü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

18
2017-08-11 21:12



Diyelim ki, 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