Pregunta

Actualmente estoy tratando de optimizar el código que había escrito en Pure Python. Este código usa Numpy Muy fuertemente mientras estoy trabajando con matrices numpy. A continuación puedes ver la más simple de mis clases a las que convirtí Cython. Que solo hace una multiplicación de dos matrices numpy. Aquí:

bendingForces = self.matrixPrefactor * membraneHeight

Mi pregunta es, si y cómo puedo optimizar esto como, cuando miro el código C que genera "Cython -A" tiene muchas llamas numpy, que no se ve muy eficiente.

import numpy as np
cimport numpy as np
ctypedef np.float64_t dtype_t
ctypedef np.complex128_t cplxtype_t
ctypedef Py_ssize_t index_t

    cdef class bendingForcesClass( object ):
        cdef dtype_t bendingRigidity
        cdef np.ndarray matrixPrefactor
        cdef np.ndarray bendingForces

        def __init__( self, dtype_t bendingRigidity, np.ndarray[dtype_t, ndim=2] waveNumbersNorm ):
            self.bendingRigidity = bendingRigidity
            self.matrixPrefactor = -self.bendingRigidity * waveNumbersNorm**2

        cpdef np.ndarray calculate( self, np.ndarray membraneHeight ) :
            cdef np.ndarray bendingForces
            bendingForces = self.matrixPrefactor * membraneHeight
            return bendingForces

La idea que tenía era usar dos for bucles e iterar sobre las entradas de las matrices. ¿Quizás podría usar el compilador para optimizar esto con operaciones SIMD? Lo intenté, que pude compilar, pero dio resultados extraños y tomó una eternidad. Aquí está el código de la función sustituta:

cpdef np.ndarray calculate( self, np.ndarray membraneHeight ) :

    cdef index_t index1, index2 # corresponds to: cdef Py_ssize_t index1, index2
    for index1 in range( self.matrixSize ):
        for index2 in range( self.matrixSize ):
            self.bendingForces[ index1, index2 ] = self.matrixPrefactor.data[ index1, index2 ] * membraneHeight.data[ index1, index2 ]
    return self.bendingForces

Sin embargo, este código, como dije, es realmente lento y no funciona como se esperaba. Entonces, ¿qué estoy haciendo mal? ¿Cuál sería la mejor manera de optimizar esto y eliminar las operaciones de llamadas numpy?

¿Fue útil?

Solución

Para multiplicaciones de matriz simples, el código Numpy ya está haciendo solo el bucle y multiplicando de forma nativa, por lo que sería difícil superar eso en Cython. Cython es ideal para situaciones en las que reemplaza los bucles en Python con los de Cython. Una de las razones por las que su código es más lento que Numpy es porque cada vez que realiza una búsqueda de índice en su matriz,

self.bendingForces[ index1, index2 ] = self.matrixPrefactor.data[ index1, index2 ] * membraneHeight.data[ index1, index2 ]

Hace más cálculos como verificación de límites (el índice es válido). Si lanza sus índices a unsigned ints, puede usar el decorador @cython.boundscheck(False) antes de la función.

Mira esto tutorial Para más detalles al acelerar el código Cython.

Otros consejos

Probablemente podrías acelerar esto usando

for index1 from 0 <= index1 < max1:

En lugar de usar una gama, no estoy seguro de que esté escrito.

Te fijaste esto afuera y Éste ?

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top