2016-05-25 4 views
0

Ich habe ein Problem mit meinem Code cythonizing, insbesondere die folgende (und ähnlichen) sniplets:Wie vermeidet man PyObject_to_MemoryviewSlice, GOTREF/DECREF Python API Aufrufe?

cdef double [:,:] grad_d_him_d_jm 
grad_d_ihm_d_jm = grad_d_im_d_jm(...) 

wo grad_d_im_d_jm (...) einen doppelten zurückkehren würde [:,:] memoryview. Dieser Code würde durch Cython in den folgenden C-Code übersetzt werden:

__pyx_t_1 = __pyx_f_24gradient_better_c_mviews_grad_d_im_d_jm(__pyx_v_i, __pyx_v_j, __pyx_v_m, __pyx_v_structure, __pyx_v_distances); 
if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 203; __pyx_clineno = __LINE__; goto __pyx_L1_error;} 
__Pyx_GOTREF(__pyx_t_1); 
__pyx_t_7 = __Pyx_PyObject_to_MemoryviewSlice_dsds_double(__pyx_t_1); 
if (unlikely(!__pyx_t_7.memview)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 203; __pyx_clineno = __LINE__; goto __pyx_L1_error;} 
__Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; 
__pyx_v_grad_d_ihm_d_jm = __pyx_t_7; 
__pyx_t_7.memview = NULL; 
__pyx_t_7.data = NULL; 

Während ich dies in Schleifen mache, ich vermute, dass die Python-API ganz gewissen Einfluss auf die Geschwindigkeit meines Code haben, nennt.

die GOTREF/DECREF Anruf tritt auch bei anderen Gelegenheiten, zusammen mit einem PyFloat_asFloat:

cdef float sp 
sp = scalar_product() 

wo scalar_product() eine cdef Schwimmers zurückgibt. Dieser Ausschnitt wird auf

übersetzt
__pyx_t_1 = __pyx_f_24gradient_better_c_mviews_scalar_product(__pyx_v_i, __pyx_v_j, __pyx_v_m, __pyx_v_structure); 
if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 178; __pyx_clineno = __LINE__; goto __pyx_L1_error;} 
__Pyx_GOTREF(__pyx_t_1); 
__pyx_t_2 = __pyx_PyFloat_AsFloat(__pyx_t_1); 
if (unlikely((__pyx_t_2 == (float)-1) && PyErr_Occurred())) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 178; __pyx_clineno = __LINE__; goto __pyx_L1_error;} 
__Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; 
__pyx_v_sp = __pyx_t_2; 

ich Python bin mit 2.7.11+ und Cython 0.23.4. Ich wäre Ihnen sehr dankbar, wenn Sie mir entweder mitteilen könnten, dass dies für die Leistung nicht relevant ist oder b) wie Sie es beheben können. Lassen Sie mich wissen, wenn ich die Frage verbessern kann, würde ich mich freuen, dies zu tun.

Antwort

1

Diese scheinen Teil der Cython Referenzzählung API zu sein erklärt here.

Meine Vermutung ist, dass grad_d_im_d_jm ein Python-Objekt (z. B. NumPy-Array) zurückgibt und Cython daher den Objekt-Referenzzähler dekrementieren muss, nachdem die Speicheransicht erhalten wurde.

Wie für scalar_product, ich denke, es ist entweder ein Def (anstatt Cdef) oder ist untypisiert. Zum Beispiel die folgende

cdef g(): 
    return 1.0 

kompiliert

// ... 
__Pyx_XDECREF(__pyx_r); 
__Pyx_INCREF(__pyx_float_1_0); 
__pyx_r = __pyx_float_1_0; 
goto __pyx_L0; 

Sobald Sie jedoch die Rückkehr geben die Refcounting Anrufe werden

cdef float g(): 
    return 1.0 

// ... 
__pyx_r = 1.0; 
goto __pyx_L0; 
wird
+0

Dank weg geben für Ihre Antworten! scalar_product ist ein cdef und sein zurückgegebener Wert ist ein cdef-float. Das gleiche gilt für grad_d_im_d_jm; nur, dass der zurückgegebene Wert eine 2D-Speicheransicht mit Float-Typ ist. Beim Drucken (grad_d_im_d_jm) heißt es, dass es sich um eine Memory-Ansicht handelt. Was ich in grad_d_im_d_jm() mache, initialisiert einen memoryview mit mv = numpy.zeros ((n, n)) und fügt dann Sachen zu einzelnen Elementen hinzu. Ich habe mir das Refnanny-Ding angeschaut, konnte aber noch keinen Weg finden es abzuschalten (nur als Option für runtests.py). Würdest du zufällig einen kennen? –

+0

Nanny wird nur verwendet, um Cython selbst zu debuggen. Z.B. Die generierte C-Datei hat ein ifdef, das "__Pyx_DECREF" durch "Py_DECREF" ersetzt, sofern der Benutzer nicht ausdrücklich "-DYTHON_REFNANY" festgelegt hat. –

+0

Ist es möglich, den relevanten Code zu teilen? Ich kann das Problem nicht lokal mit Stub-Funktionen reproduzieren. –

Verwandte Themen