2017-06-15 3 views
0

Ich teste Cython-Leistung, wenn ein numpy ndarray geändert wird, basierend darauf, ob die Summe der i-ten und j-ten Indizes gerade oder ungerade ist. Im Vergleich zu Python ist die Cython-Geschwindigkeit lediglich 80% schneller, was einen mittelmäßigen Geschwindigkeitsgewinn darstellt. Mir sind im Moment die Ideen ausgegangen. Irgendwelche Vorschläge?Verbesserte Geschwindigkeit mit Cython im Umgang mit Numpy ndarray

@Python:

def even_odd_function(matrix): 

    dim = matrix.shape[1] 

    for i in range(dim): 
     for j in range(dim): 
      if (i + j) % 2 == 0: 
       matrix[i, j] = matrix[i, j] ** 2 
      else: 
       matrix[i, j] = matrix[i, j] * -1 

    return matrix 

@Cython:

%%cython 

import numpy as np 
cimport numpy as np 
cimport cython 

DTYPE = np.int 
ctypedef np.int DTYPE_t 

@cython.boundscheck(False) 
@cython.wraparound(False) 
@cython.nonecheck(False) 
def even_odd_function7(np.ndarray matrix): 

    cdef int dim = matrix.shape[1] 
    cdef int i 
    cdef int j 

    for i in range(dim): 
     for j in range(dim): 
      if (i + j) % 2 == 0: 
       matrix[i, j] = matrix[i, j] * matrix[i, j] 
      else: 
       matrix[i, j] = matrix[i, j] * -1 

    return matrix 

Hier sind die markierten Linien: enter image description here

Antwort

4

Sie müssen den Typ Ihrer Array für die großen Speedup mit Anmerkungen versehen.

import numpy as np 
cimport numpy as np 
cimport cython 

@cython.boundscheck(False) 
@cython.wraparound(False) 
@cython.nonecheck(False) 
def even_odd_function8(np.ndarray[np.float64_t, ndim=2] matrix): 

    cdef int dim = matrix.shape[1] 
    cdef int i 
    cdef int j 

    for i in range(dim): 
     for j in range(dim): 
      if (i + j) % 2 == 0: 
       matrix[i, j] = matrix[i, j] * matrix[i, j] 
      else: 
       matrix[i, j] = matrix[i, j] * -1 

    return matrix 

In [20]: arr = np.random.randn(1000, 1000) 

In [21]: %timeit even_odd_function(arr) 
1 loop, best of 3: 636 ms per loop 

In [22]: %timeit even_odd_function7(arr) 
1 loop, best of 3: 480 ms per loop 

In [24]: %timeit even_odd_function8(arr) 
1000 loops, best of 3: 1.61 ms per loop 

Weitgehend eine stilistische Sache, aber ich ziehe die neuere typisierten memoryview Syntax, die das gleiche tun werden.

def even_odd_function(np.float64_t[:,:] matrix) 
+0

Vielen Dank dafür. Es funktionierte. Der einzige Teil, den ich nicht verstanden habe, ist ndim. Was bedeutet das? – MLhacker

+0

'ndim' = Anzahl der Dimensionen im Array, also in diesem Fall 2. In den memoryview-Versionen wird die Anzahl der Dimensionen durch die Anzahl der leeren Slices angegeben -' float64_t [:] '= 1 dim,' float64_t [: ,:] '= 2 dunkel usw. – chrisb

Verwandte Themen