2011-09-27 8 views
7

stavo programmando qualcosa in MATLAB e, come raccomandato, io sono sempre cercando di utilizzare vettorializzazione. Ma alla fine il programma è stato piuttosto lento. Così ho scoperto che in un punto il codice è significativamente più veloce quando si usano i loop (esempio sotto).'per' ciclo vs vettorializzazione in MATLAB

Mi piacerebbe sapere se ho interpretato male qualcosa o ho fatto qualcosa di sbagliato, perché le prestazioni sono importanti in questo caso, e non voglio continuare a indovinare se la vettorizzazione oi cicli saranno più veloci.

% data initialization 

k = 8; 
n = 2^k+1; 
h = 1/(n-1); 
cw = 0.1; 

iter = 10000; 

uloc = zeros(n); 
fploc = uloc; 
uloc(2:end-1,2:end-1) = 1; 
vloc = uloc; 
ploc = ones(n); 

uloc2 = zeros(n); 
fploc2 = uloc2; 
uloc2(2:end-1,2:end-1) = 1; 
vloc2 = uloc2; 
ploc2 = ones(n); 

%%%%%%%%%%%%%%%%%%%%%% 
% vectorized version % 
%%%%%%%%%%%%%%%%%%%%%% 
tic 
for it=1:iter 
    il=2:4; 
    jl=2:4; 
    fploc(il,jl) = h/6*(-uloc(il-1,jl-1) + uloc(il-1,jl)... 
     -2*uloc(il,jl-1)+2*uloc(il,jl+1)... 
     -uloc(il+1,jl) + uloc(il+1,jl+1)... 
     ... 
     -vloc(il-1,jl-1) - 2*vloc(il-1,jl)... 
     +vloc(il,jl-1) - vloc(il,jl+1)... 
     + 2*vloc(il+1,jl) + vloc(il+1,jl+1))... 
     ... 
     +cw*h^2*(-ploc(il-1,jl)-ploc(il,jl-1)+4*ploc(il,jl)... 
     -ploc(il+1,jl)-ploc(il,jl+1)); 
end 
toc 


%%%%%%%%%%%%%%%%%%%%%% 
% loop version % 
%%%%%%%%%%%%%%%%%%%%%% 
tic 
for it=1:iter 
    for il=2:4 
     for jl=2:4 
      fploc2(il,jl) = h/6*(-uloc2(il-1,jl-1) + uloc2(il-1,jl)... 
       -2*uloc2(il,jl-1)+2*uloc2(il,jl+1)... 
       -uloc2(il+1,jl) + uloc2(il+1,jl+1)... 
       ... 
       -vloc2(il-1,jl-1) - 2*vloc2(il-1,jl)... 
       +vloc2(il,jl-1) - vloc2(il,jl+1)... 
       + 2*vloc2(il+1,jl) + vloc2(il+1,jl+1))... 
       ... 
       +cw*h^2*(-ploc2(il-1,jl)-ploc2(il,jl-1)+4*ploc2(il,jl)... 
       -ploc2(il+1,jl)-ploc2(il,jl+1)); 
     end 
    end 
end 
toc 

risposta

6

non sono andato attraverso il vostro codice, ma il compilatore JIT nelle versioni recenti di Matlab è migliorata al punto in cui la situazione si sta affrontando è abbastanza comune - loop può essere più veloce di codice vectorized. E 'difficile sapere in anticipo quale sarà più veloce, quindi l'approccio migliore è quello di scrivere il codice nel modo più naturale, il profilo e poi se v'è un collo di bottiglia, prova a passare dal loop per vettorializzare (o viceversa).

2

Forse una matrice di alcuni elementi non è un buon test per l'efficienza vettorizzazione. Alla fine dipende dall'applicazione su ciò che funziona bene.

Inoltre, il codice di solito vettorializzare sembra migliore (più fedele al modello di base), ma molti casi non è così e si finisce per danneggiare l'attuazione. Quello che hai fatto è fantastico, ora sai cosa funziona meglio per te.

6

del just in time compilatore (JIT) è stata migliorata in modo significativo nel corso degli ultimi due anni MATLAB. E anche se hai ragione che generalmente si dovrebbe vettorializzare il codice, dalla mia esperienza questo è vero solo per certe operazioni e funzioni e dipende anche da quanti dati le tue funzioni stanno gestendo.

Il modo migliore per voi per scoprire ciò che funziona meglio, è quello di profile your MATLAB code con e senza vettorizzazione.

+0

quando dici "dipende da quanti dati hai", ti dispiace essere un po 'più specifico su cosa intendevi? Intendevi che i loop di solito peggiorano con set di dati più grandi? –

0

Non direi questo vettorizzazione.

in cui sembra stia facendo una sorta di operazione di filtraggio. Una versione veramente vettorizzata di tale filtro è il dato originale, moltiplicato per la matrice del filtro (cioè una matrice che rappresenta l'intero ciclo).

Problemi con queste matrici è che sono così sparse (solo alcuni elementi non nulli intorno alla diagonale) che è quasi mai efficace per usarli. È possibile utilizzare il comando sparse ma anche in questo caso, l'eleganza della notazione probabilmente non giustifica la memoria aggiuntiva richiesta.

Matlab utilizzato per i loop non validi perché anche i contatori di loop ecc erano ancora trattati come matrici complesse, quindi tutti i controlli per tali matrici venivano valutati ad ogni iterazione. La mia ipotesi è che all'interno del ciclo for, tutti questi controlli vengono comunque eseguiti ogni volta che si applicano i coefficienti del filtro.

Forse le funzioni MATLAB filter e filter2 sono utili qui? Puoi anche scrivere questo post: Improving MATLAB Matrix Construction Code : Or, code Vectorization for begginers

0

Una spiegazione possibile è l'overhead di avvio. Se una matrice temporanea viene creata dietro la scena, preparatevi per le allocazioni di memoria. Inoltre, suppongo che MATLAB non possa dedurre che la tua matrice sia piccola, quindi ci sarà un overhead del ciclo.Così il vostro vettorizzati versione può finire in codice come

double* tmp=(double*)malloc(n*sizeof(double)); 
for(size_t k=0;k<N;++k) 
    { 
// Do stuff with elements 
    } 
free(tmp); 

Confronta questo per un numero limitato di operazioni:

double temp[2]; 
temp[0]=...; 
temp[1]=...; 

Così JIT può essere più veloce quando il tempo-libera malloc-loopcounter è lunga rispetto al carico di lavoro per ogni calcolo.