2017-01-19 3 views
-2

Ich habe eine Python-Funktion, die ich nach Cython exportieren möchte. Ich habe zwei Implementierungen getestet, aber ich verstehe nicht, warum der zweite langsamer ist als der erste. Außerdem suche ich nach Möglichkeiten, die Geschwindigkeit etwas zu verbessern, aber ich habe keine Ahnung wie?Cython Anrufoptimierung

Basiscode

import numpy as np 
cimport numpy as np 
cimport cython 
DTYPE = np.int 
ctypedef np.int_t DTYPE_t 
cdef inline int int_max(int a, int b): return a if a >= b else b 
cdef inline int int_min(int a, int b): return a if a <= b else b 
cdef extern from "math.h": 
    double exp(double x) 

@cython.boundscheck(False) 
@cython.wraparound(False) 
def bilateral_filter_C(np.ndarray[np.float_t, ndim=1] samples, int w=20): 
    # Filter Parameters 
    cdef Py_ssize_t size = samples.shape[0] 
    cdef float rang 
    cdef float sigma = 2*3.0*3.0 
    cdef int j, L 
    cdef unsigned int a, b 
    cdef np.float_t W, num, sub_sample, intensity 

    # Initialization 
    cdef np.ndarray[np.float_t, ndim=1] gauss = np.zeros(2*w+1, dtype=np.float) 
    cdef np.ndarray[np.float_t, ndim=1] sub_samples, intensities = np.empty(size, dtype=np.float) 
    cdef np.ndarray[np.float_t, ndim=1] samples_filtered = np.empty(size, dtype=np.float) 

    L = 2*w+1 
    for j in xrange(L): 
     rang = -w+1.0/L 
     rang *= rang 
     gauss[j] = exp(-rang/sigma) 


    <CODE TO IMPROVE> 

    return samples_filtered 

Ich habe versucht, diese beiden Codebeispiele im <CODE TO IMPROVE> Abschnitt zu injizieren:

effizienteste Ansatz

for i in xrange(size):    
     a = <unsigned int>int_max(i-w, 0) 
     b = <unsigned int>int_min(i+w, size-1) 
     L = b-a   

     sub_samples = samples[a:b]-samples[i] 
     sub_samples *= sub_samples 
     for j in xrange(L): 
      sub_samples[j] = exp(-sub_samples[j]/sigma) 
     intensities = gauss[w-i+a:w-i+b]*sub_samples 

     num = 0.0 
     W = 0.0   
     for j in xrange(L): 
      W += intensities[j] 
      num += intensities[j]*samples[a+j] 

     samples_filtered[i] = num/W 

Ergebnis

%timeit -n1 -r10 bilateral_filter_C(x, 20) 
1 loop, best of 10: 45 ms per loop 

Weniger effiziente

for i in xrange(size):    
     a = <unsigned int>int_max(i-w, 0) 
     b = <unsigned int>int_min(i+w, size-1) 

     num = 0.0 
     W = 0.0   
     for j in xrange(b-a): 
      sub_sample = samples[a+j]-samples[i] 
      intensity1 = gauss[w-i+a+j]*exp(-sub_sample*sub_sample/sigma) 
      W += intensity 
      num += intensity*samples[a+j] 

     samples_filtered[i] = num/W  

Ergebnis

%timeit -n1 -r10 bilateral_filter_C(x, 20) 
1 loop, best of 10: 125 ms per loop 
+0

Sie müssen den Unterschied hervorheben und erklären. Sie haben zwei lange Code-Blöcke, die gleich aussehen - bis ich runterscrolle. Wenn es zu viel Zeit braucht, um Ihre Frage zu lesen und zu verstehen, werden Poster zu einfacheren Fragen weitergehen. – hpaulj

+0

Beitrag entsprechend aktualisiert. Der Code of Interest wurde hervorgehoben – GuillaumeA

Antwort

0

Sie haben ein paar Tippfehler:

1) Sie haben vergessen i zu definieren, fügen Sie einfach cdef int i, j, L

2) Im zweiten Algorithmus Sie intensity1 = gauss[w-i+a+j]*exp(-sub_sample*sub_sample/sigma) schrieben, soll es intensity sein, ohne die 1

3) Ich @cython.cdivision(True) hinzufügen würde die Überprüfung der Division durch Null

Mit diesen Änderungen und mit x = np.random.rand(10000) Ich habe das zu vermeiden, folgende Ergebnisse

%timeit bilateral_filter_C1(x, 20) # First code 
10 loops, best of 3: 74.1 ms per loop 
%timeit bilateral_filter_C2(x, 20) # Second code 
100 loops, best of 3: 9.5 ms per loop 

Und um zu überprüfen, die Ergebnisse

np.all(np.equal(bilateral_filter_C1(x, 20), bilateral_filter_C2(x, 20))) 
True 

Um diese Probleme zu vermeiden, schlage ich vor, die Option cython my_file.pyx -a, es erzeugt eine HTML-Datei zu verwenden, die die möglichen Probleme, die Sie in Ihrem Code

EDIT

Lesen Sie den Code erneut haben zeigt, scheint es mehr zu haben Fehler:

for j in xrange(L): 
    rang = -w+1.0/L 
    rang *= rang 
    gauss[j] = exp(-rang/sigma) 

gauss den gleichen Wert hat immer, was ist die Definition von rang?

+0

Vielen Dank !! Ich habe die Definition der Variablen "i" verpasst. Das war das Hauptproblem bei der Leistung. Und danke für die Gauss-Vektor-Generierung, es ist auch ein Copy/Paste aus einem alten Code, der repariert werden musste .... – GuillaumeA