Question

Je tente actuellement d'optimiser le code que je l'avais écrit en Python pur. Ce code utilise NumPy très fortement que je travaille avec des tableaux numpy. Ci-dessous vous pouvez voir la plus simple de mes cours que je me suis converti Cython . Ce qui ne fait que la multiplication de deux tableaux NumPy. Ici:

bendingForces = self.matrixPrefactor * membraneHeight

Ma question est, si et comment je peux optimiser ce que, quand je regarde le code C qui « cython -a » génère a beaucoup de numpy-appels, ce qui ne semble pas très efficace.

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

L'idée que j'avais été d'utiliser deux boucles de for et itérer sur les entrées des tableaux. Peut-être que je pourrais utiliser le compilateur pour optimiser ce cas avec SIMD opérations ?! J'ai essayé, que je pouvais compiler, mais il a donné des résultats étranges et a pris une éternité. Voici le code de la fonction de remplacement:

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

Cependant, ce code comme je l'ai dit, est vraiment lent et ne fonctionne pas comme prévu. Alors qu'est-ce que je fais mal? Quelle serait la meilleure façon d'optimiser cela et supprimer les opérations appelant NumPy?

Était-ce utile?

La solution

Pour multiplications simples de la matrice, le code NumPy est déjà fait que la boucle et en multipliant de manière native, il serait donc difficile de battre en Cython. Cython est idéal pour les situations où vous remplacez des boucles en Python avec ceux cython. L'une des raisons pour lesquelles votre code est plus lent que NumPy est parce que chaque fois que vous faites une recherche d'index dans votre tableau,

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

il fait plus de calculs comme la vérification des limites (l'indice est valide). Si vous lancez vos indices à ints non signés, vous pouvez utiliser le @cython.boundscheck(False) décorateur avant la fonction.

tutoriel pour plus de détails en accélérant le code Cython.

Autres conseils

Vous pourriez probablement accélérer ce en utilisant

for index1 from 0 <= index1 < max1:

au lieu d'utiliser une gamme Je ne sais pas tapés.

Avez-vous vérifié ceci et celui-ci ?

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top