2013-03-12 3 views
2

J'ai une fonction qui calcule une matrice pour moi mais c'est vraiment lent. Même à Cython, il tourne lentement, alors je me demandais si on pouvait faire quelque chose pour améliorer le code ci-dessous.Un moyen efficace de créer une matrice avec Cython

EDIT: J'ai changé ou ajouté

des = np.zeros([n-m+1,m])-cdef np.ndarray des = np.zeros([n-m+1,m], dtype=DTYPE) (C'est plus rapide que np.empty... Au lieu de dire que je m/2 ai ajouté une cdef int m2 = m/2 mais cela n'a pas semblé aider quoi que ce soit

cimport numpy as np 
cimport cython 

DTYPE = float 
ctypedef np.float_t DTYPE_t 

@cython.boundscheck(False) 
@cython.cdivision(True) 
@cython.wraparound(False) 
cpdef map4(np.ndarray[DTYPE_t, ndim=1] s, int m): 

    cdef int n = len(s) 
    cdef int i 
    cdef int j 

    des = np.zeros([n-m+1,m]) 
    for j in xrange(m): 
     for i in xrange(m/2,n-m/2-1): 
      des[i-m/2,j] = s[i-j+m/2] 

    return des, s, m, n 
.

En général n~10000 et m=1001

+0

ne pas oublier de vérifier la sortie de 'cython -a' pour plus de détails. Le fichier html généré est extrêmement utile pour voir les points faibles du code – dmytro

+0

Oui, le fichier html est vraiment utile, quand on veut voir la partie lente (ou la partie qui nécessite beaucoup de conversion), mais ce n'est vraiment pas très utile si vous n'avez aucune idée de comment continuer à partir de là. Mais je suis d'accord avec toi. J'ai aussi commencé avec le fichier html. –

+0

Il semble que vous stockiez simplement des tranches simples du tableau 's'. Vous pourriez juste trancher 's' quand vous en avez besoin? –

Répondre

3

Essayez:.

cdef np.ndarray des = np.zeros([n-m+1,m]) 

Vous pouvez également rendre ceci plus spécifique comme vous l'avez fait pour les paramètres s. Vous pouvez également désactiver la vérification des limites. Découvrez le cython numpy tutorial.

Vous pouvez également faire une variable:

cdef int m_2 = m/2 

et l'utiliser partout où vous avez m/2 parce que je ne sais pas si Cython fera que l'optimisation pour vous.

+1

Au lieu de tmp var m_2, il peut être préférable de dire 'pour i dans xrange (nm):'/'des [i, j] = s [i-j + m]' et/ou une tranche de tableau –

+0

m un peu en retard à la fête, mais vous devriez vraiment ajouter '[DTYPE_t, ndim = 2]' à la déclaration de type statique de 'des' (~ 10x speedup). En outre, l'échange des 2 boucles for-help aide un peu, en alignant l'accès au tableau avec la disposition de la mémoire. Cela a fait descendre le temps d'exécution à 158 ms sur mon système à partir de 2,45 secondes pour le code original. –

2

Il pourrait également aider à utiliser np.empty au lieu de np.zeros, en supposant que vous assignez chaque élément:

des = np.empty([n-m+1,m]) 
+0

J'ai trouvé que 'np.empty' n'était pas le choix le plus rapide. –

+0

Hm, je me demande pourquoi – askewchan

+0

J'ai trouvé cela très utile. Réduit le temps de fonctionnement de 158 ms à 113 ms! –

0

Je ne vois pas m être mis partout. Au bas de votre code, vous mentionnez que n ~ 10 000, et m = 1001. Cela signifie-t-il que m est un entier constant de 32 bits? Ne voyant pas vos drapeaux de compilation, il est souvent utile de l'essayer avec et sans -ffast-math pour voir si cela fait une différence. Avec des matrices et matrices volumineuses, l'utilisation d'un type de données plus petit montre généralement une accélération significative, à condition que le plus petit type de données préserve la gamme et la précision dont votre programme a besoin, bien que je ne vois pas un grand avantage potentiel sur ce calcul.

Si vous pouviez nous montrer le code C généré par ceci, cela pourrait aussi aider.

Questions connexes