2011-01-17 12 views
7

Sto facendo alcuni calcoli intensivi e convertito il codice in Cython. Ho fatto Profiling opzione -a Cython con, e ispezionato il file .html, e sembra ogni volta che faccio la divisione galleggiante, c'è un po 'la linea gialla e lo fa qualcosa di simile al seguente:Cython float division PyExc_ZeroDivisionError checking

if (unlikely(__pyx_t_37 == 0)) { 
     PyErr_Format(PyExc_ZeroDivisionError, "float division"); 
     {__pyx_filename = __pyx_f[0]; __pyx_lineno = 84; __pyx_clineno = __LINE__; goto __pyx_L1_error;} 
     } 

Credo che è per i casi in cui il divisore è 0. Sto usando una costante per quello e non c'è probabilità che il divisore sia 0, e mi chiedevo se c'è qualcosa che posso fare per renderlo più veloce.

+0

Stai già utilizzando 'cdef float yourconstant' (e anche per l'altra parte della divisione)? Puoi mostrare un po 'del codice? – TryPyPy

+0

Hmm, sembra che piaccia 'cdef double' meglio. – TryPyPy

risposta

13

È necessario aggiungere @cython.cdivision(True) per evitare la verifica un'eccezione.

import cython 

cdef double pydivision(): 
    cdef int i 
    cdef double k, j 
    k = 2.0 
    j = 0.0 
    for i in range(10): 
    j += i/k 
    # Generated code: Python exception checking 
    # /* "checksum.pyx":9 
    # * j = 0.0 
    # * for i in range(10): 
    # *  j += i/k    # <<<<<<<<<<<<<< 
    # * return j 
    # * 
    # */ 
    # if (unlikely(__pyx_v_k == 0)) { 
    #  PyErr_Format(PyExc_ZeroDivisionError, "float division"); 
    #  {__pyx_filename = __pyx_f[0]; __pyx_lineno = 9; __pyx_clineno = __LINE__; goto __pyx_L1_error;} 
    # } 
    # __pyx_v_j = (__pyx_v_j + (__pyx_v_i/__pyx_v_k)); 
    # } 
    return j 

#This decorator works wonders 
@cython.cdivision(True) 
cdef double cdivision(): 
    cdef int i 
    cdef double k, j 
    k = 2.0 
    j = 0.0 
    for i in range(10): 
    j += i/k 
    # Generated code: no exception checking 
    # /* "checksum.pyx":20 
    # * j = 0.0 
    # * for i in range(10): 
    # *  j += i/k    # <<<<<<<<<<<<<< 
    # * return j 
    # * 
    # */ 
    # __pyx_v_j = (__pyx_v_j + (__pyx_v_i/__pyx_v_k)); 
    # } 
    return j 
+1

oppure è possibile utilizzare una direttiva globale. Vedi http://wiki.cython.org/enhancements/compilerdirectives –

+0

Grazie mille per questo! – joon

0

Se il divisore è costante, è possibile moltiplicare per 1/divisor invece