2017-10-02 6 views
2

Je développe un code qui intègre un ODE en utilisant le complex_ode de scipy, où l'intégrand inclut une transformée de Fourier et un opérateur exponentiel agissant sur un large éventail de complexes valeurs.La méthode la plus rapide pour calculer la fonction exponentielle [exp()] du grand tableau complexe en Python

Pour optimiser les performances, j'ai profilées cela et trouvé le principal goulot d'étranglement est (après optimisation TFR à l'aide PyFFTW etc.) dans la ligne:

val = np.exp(float_value * arr) 

Je suis actuellement à l'aide numpy que je comprends les appels de code C - et devrait donc être rapide. Mais est-il possible d'améliorer encore les performances s'il vous plaît? J'ai cherché dans l'utilisation de Numba mais comme ma boucle principale inclut aussi des FFT, je ne pense pas qu'elle puisse être compilée (nopython = True flag mène à des erreurs) et donc, je suppose qu'elle n'offre aucun gain.

Voici un exemple de test pour le code que je voudrais optimiser:

arr = np.random.rand(2**14) + 1j *np.random.rand(2**14) 
float_value = 0.5 
%timeit np.exp(float_value * arr) 

Toute suggestion accueillie merci.

Répondre

3

Nous pourrions tirer parti numexpr module qui fonctionne vraiment efficacement sur de grandes données impliquant des opérations transcendantales -

In [91]: arr = np.random.rand(2**14) + 1j *np.random.rand(2**14) 
    ...: float_value = 0.5 
    ...: 

In [92]: %timeit np.exp(float_value * arr) 
1000 loops, best of 3: 739 µs per loop 

In [94]: import numexpr as ne 

In [95]: %timeit ne.evaluate('exp(float_value*arr)') 
1000 loops, best of 3: 241 µs per loop 

Cela semble être cohérent avec le expected performance comme indiqué dans la documentation.

+0

Merci - cette approche numexpr semble intéressante. Je n'avais pas vu cela dans les conseils en ligne habituels pour l'optimisation qui met généralement en évidence Numba, Cython, etc. Alors que le% temps indépendant montre une amélioration> 2x, lorsqu'il est utilisé dans mon integrand la performance du solveur ne montre aucune différence. Je vais enquêter plus et poster/accepter la réponse. – SLater01

+0

@ SLater01 Travaillez-vous avec de grandes données là-bas? En outre, lors de la synchronisation avec la configuration plus grande du problème de solveur, assurez-vous de ne chronométrer cette partie exponentielle que parce que d'autres parties du code prennent peut-être une plus grande part de l'exécution. – Divakar

+1

Habituellement seulement un petit pick-up, mais vous pouvez aussi utiliser le paramètre 'out =' de l'une ou l'autre de ces fonctions pour réutiliser des tableaux temporaires. – chrisb