2011-01-17 7 views
7

Estoy haciendo algunos cálculos de bucle intensivo y convertí el código en Cython. lo hice perfilado opción -a con Cython, e inspeccionó el archivo .html, y parece que cada vez que hago la división de flotación, no hay línea algo amarillo y lo hace algo como lo siguiente: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;} 
     } 

supongo que es para los casos en que el divisor es 0. Estoy usando una constante para eso y no hay probabilidad de que el divisor sea 0, y me preguntaba si hay algo que pueda hacer para hacerlo más rápido.

+0

¿Ya está usando 'cdef float yourconstant' (y para la otra parte de la división también)? ¿Puedes mostrar algo del código? – TryPyPy

+0

Hmm, parece que le gusta 'cdef double' mejor. – TryPyPy

Respuesta

13

Es necesario añadir @cython.cdivision(True) para evitar la comprobación excepción.

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

o puede usar una directiva global. Ver http://wiki.cython.org/enhancements/compilerdirectives –

+0

¡Muchas gracias por esto! – joon

0

Si el divisor es constante, se puede multiplicar por 1/divisor lugar