2011-01-17 18 views
7

Wykonuję obliczenia wymagające dużej pętli i przekonwertowałem kod na Cython. zrobiłem profilowania z opcją -a Cython i sprawdzony plik .html, i wydaje się, ilekroć zrobić podział pływaka, jest nieco żółta linia i robi coś jak następuje: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;} 
     } 

Chyba jest dla przypadków, w których dzielnik wynosi 0. Używam stałej dla tego i nie ma prawdopodobieństwa, że ​​dzielnik wynosi 0, i zastanawiałem się, czy jest coś, co mogę zrobić, aby przyspieszyć.

+0

Czy używasz już 'cdef float yourconstant' (a także dla drugiej części podziału)? Czy możesz pokazać część kodu? – TryPyPy

+0

Hmm, wygląda na to, że lubi "cdef double" lepiej. – TryPyPy

Odpowiedz

13

Trzeba dodać @cython.cdivision(True) uniknąć sprawdzania wyjątku.

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

lub możesz użyć dyrektywy globalnej. Zobacz http://wiki.cython.org/enhancements/compilerdirectives –

+0

Wielkie dzięki za to! – joon

0

Jeżeli dzielnik jest stała, można pomnożyć przez 1/divisor zamiast