2010-07-25 14 views
2

Je suis le tissage mon code c en python pour accélérer la boucle:Comment accélérer l'accès au tableau multidimensionnel dans scipy.weave?

from scipy import weave 
from numpy import * 

#1) create the array 
a=zeros((200,300,400),int) 
for i in range(200): 
    for j in range(300): 
     for k in range(400):  
      a[i,j,k]=i*300*400+j*400+k 
#2) test on c code to access the array 
code=""" 
for(int i=0;i<200;++i){ 
for(int j=0;j<300;++j){ 
for(int k=0;k<400;++k){ 
printf("%ld,",a[i*300*400+j*400+k]);  
} 
printf("\\n"); 
} 
printf("\\n\\n"); 
} 
""" 
test =weave.inline(code, ['a']) 

Cela fonctionne tout bien, mais il est encore coûteuse lorsque le tableau est grand. Quelqu'un m'a suggéré d'utiliser a.strides au lieu du méchant "a [i * 300 * 400 + j * 400 + k]" Je ne comprends pas le document à propos .strides.

Toutes les idées

Merci à l'avance

Répondre

4

Vous pouvez remplacer les 3 pour boucles avec

grid=np.ogrid[0:200,0:300,0:400] 
a=grid[0]*300*400+grid[1]*400+grid[2] 

Ce qui suit suggère cela peut entraîner une ~ 68x (ou mieux? Voir ci-dessous) speedup:

% python -mtimeit -s"import test" "test.m1()" 
100 loops, best of 3: 17.5 msec per loop 
% python -mtimeit -s"import test" "test.m2()" 
1000 loops, best of 3: 247 usec per loop 

test.py:

import numpy as np 

n1,n2,n3=20,30,40 
def m1(): 
    a=np.zeros((n1,n2,n3),int) 
    for i in range(n1): 
     for j in range(n2): 
      for k in range(n3):  
       a[i,j,k]=i*300*400+j*400+k 
    return a 

def m2():  
    grid=np.ogrid[0:n1,0:n2,0:n3] 
    b=grid[0]*300*400+grid[1]*400+grid[2] 
    return b 

if __name__=='__main__': 
    assert(np.all(m1()==m2())) 

n1, n2, n3 = 200300400,

python -mtimeit -s"import test" "test.m2()" 

a pris 182 ms sur ma machine, et

python -mtimeit -s"import test" "test.m1()" 

n'a pas encore fini.

+0

Merci pour votre réponse: Mais je ne suis pas intéressé par la configuration ... Savez-vous comment accélérer la deuxième partie (code c)? Merci – Eminemya

+0

Hm, désolé, je ne connais pas la réponse à cette question. – unutbu

1

Le problème est que vous imprimez à 2,4 millions de numéros à l'écran dans votre code C. Cela va bien sûr prendre un certain temps parce que les nombres doivent être convertis en chaînes et ensuite imprimés à l'écran. Avez-vous vraiment besoin de les imprimer tous à l'écran? Quel est votre objectif final ici?

Pour une comparaison, j'essayé de placer tout autre tableau que chacun des éléments d'un. Ce processus a pris environ 0,05 secondes en tissage. J'ai abandonné le chronométrage de l'impression de tous les éléments à l'écran après 30 secondes environ.

0

Il n'y a pas moyen d'accélérer l'accès à un tableau multidimensionnel en C. Vous devez calculer l'indice de tableau et vous devez déréférencer, cela est aussi simple que cela.

0

J'espère vraiment, vous n'avez pas exécuté la boucle avec toutes les instructions d'impression, comme Justin a déjà noté. En outre:

from scipy import weave 
n1, n2, n3 = 200, 300, 400 

def m1(): 
    a = np.zeros((n1,n2,n3), int) 
    for i in xrange(n1): 
     for j in xrange(n2): 
      for k in xrange(n3): 
       a[i,j,k] = i*300*400 + j*400 + k 
    return a 

def m2():  
    grid = np.ogrid[0:n1,0:n2,0:n3] 
    b = grid[0]*300*400 + grid[1]*400 + grid[2] 
    return b 

def m3(): 
    a = np.zeros((n1,n2,n3), int) 
    code = """ 
    int rows = Na[0]; 
    int cols = Na[1]; 
    int depth = Na[2]; 
    int val = 0;  
    for (int i=0; i<rows; i++) { 
     for (int j=0; j<cols; j++) { 
      for (int k=0; k<depth; k++) { 
       val = (i*cols + j)*depth + k; 
       a[val] = val; 
      } 
     } 
    }""" 
    weave.inline(code, ['a']) 
    return a 

%timeit m1() 
%timeit m2() 
%timeit m3() 
np.all(m1() == m2()) 
np.all(m2() == m3()) 

Donne-moi:

1 loops, best of 3: 19.6 s per loop 
1 loops, best of 3: 248 ms per loop 
10 loops, best of 3: 144 ms per loop 

qui semble assez raisonnable. Si vous voulez accélérer encore, vous voulez probablement commencer à utiliser votre GPU, ce qui est parfait pour le calcul de nombres comme ça.

Dans ce cas particulier, vous pouvez même faire:

def m4(): 
    a = np.zeros((n1,n2,n3), int) 
    code = """ 
    int rows = Na[0]; 
    int cols = Na[1]; 
    int depth = Na[2]; 
    for (int i=0; i<rows*cols*depth; i++) { 
     a[i] = i; 
    }""" 
    weave.inline(code, ['a']) 
    return a 

Mais cela ne se beaucoup mieux plus, depuis np.zeros() prend déjà la plupart du temps:

%timeit np.zeros((n1,n2,n3), int) 
10 loops, best of 3: 113 ms per loop