2013-08-28 3 views
5

Questa osservazione non è così importante, poiché le prestazioni in termini di tempo sprecate nelle istruzioni loop probabilmente saranno molto più alte del loop stesso. Ma comunque, lo condividerò da quando ho cercato e non sono riuscito a trovare un argomento a riguardo. Ho sempre avuto l'impressione che la pre-allocazione dell'array in loop, e quindi il loop su di esso, sarebbe stata migliore del loop direttamente su di esso, e ho deciso di controllarlo. Il codice sarebbe quello di confrontare l'efficienza tra questi due Fors:Ripetizione degli statement di loop e pre-allocazione dell'istruzione looping stessa

disp('Pure for with column on statement:') 
tic 
for k=1:N 
end 
toc 

disp('Pure for with column declared before statement:') 
tic 
m=1:N; 
for k=m 
end 
toc 

Ma i risultati che ho ottenuto sono:

Pure for with column on statement: 
Elapsed time is 0.003309 seconds. 
Pure for with column declared before statement: 
Elapsed time is 0.208744 seconds. 

Perché diavolo è? La pre-allocazione non dovrebbe essere più veloce?

In realtà, il MATLAB help for dice:

cicli lunghi sono più efficiente della memoria quando viene visualizzata l'espressione colon nell'istruzione FOR poiché il vettore indice è mai creato.

Quindi, contraddicendo le mie aspettative l'espressione di colonna al di affermazione è meglio, perché non alloca il vettore e, per questo, è più veloce.

ho fatto il seguente script per testare altre occasioni che anche io penso che sarebbe più veloce:

% For comparison: 
N=1000000; 

disp('Pure for loop on cell declared on statement:') 
tic 
for k=repmat({1},1,N) 
end 
toc 

disp('Pure for loop on cell declared before statement:') 
tic 
mcell=repmat({1},1,N); 
for k=mcell 
end 
toc 

disp('Pure for loop calculating length on statement:') 
tic 
for k=1:length(mcell) 
end 
toc 

disp('Pure for loop calculating length before statement:') 
tic 
lMcell = length(mcell); 
for k=1:lMcell 
end 
toc 

disp('Pure while loop using le:') 
% While comparison: 
tic 
k=1; 
while (k<=N) 
    k=k+1; 
end 
toc 

disp('Pure while loop using lt+1:') 
% While comparison: 
tic 
k=1; 
while (k<N+1) 
    k=k+1; 
end 
toc 


disp('Pure while loop using lt+1 pre allocated:') 
tic 
k=1; 
myComp = N+1; 
while (k<myComp) 
    k=k+1; 
end 
toc 

E i tempi sono:

Pure for loop on cell declared on statement: 
Elapsed time is 0.259250 seconds. 
Pure for loop on cell declared before statement: 
Elapsed time is 0.260368 seconds. 
Pure for loop calculating length on statement: 
Elapsed time is 0.012132 seconds. 
Pure for loop calculating length before statement: 
Elapsed time is 0.003027 seconds. 
Pure while loop using le: 
Elapsed time is 0.005679 seconds. 
Pure while loop using lt+1: 
Elapsed time is 0.006433 seconds. 
Pure while loop using lt+1 pre allocated: 
Elapsed time is 0.005664 seconds. 

Conclusioni:

  • È possibile ottenere un po 'di prestazioni solo per ciclo su istruzioni virgola, ma che può essere trascurabile rispetto al tempo trascorso su th e for-loop.
  • Per le celle la differenza sembra essere trascurabile.
  • È preferibile pre-allocare la lunghezza prima di eseguire il ciclo.
  • Il tempo ha la stessa efficienza del per senza pre-allocare il vettore, che ha senso come indicato prima
  • Come previsto, è meglio calcolare le espressioni fisse prima dell'istruzione while.

Ma la domanda a cui non posso rispondere è, per quanto riguarda la cella, perché non c'è differenza di orario? Il sovraccarico potrebbe essere molto inferiore a quello osservato? O deve allocare le celle poiché non è un tipo di base come un doppio?

Se si conoscono altri trucchi relativi a questo argomento, riempire gratuitamente per aggiungere.


Basta aggiungere i tempi per mostrare i risultati di trasformare feature('accel','off') come detto in @ risposta di Magla.

Pure for with column on statement: 
Elapsed time is 0.181592 seconds. 
Pure for with column declared before statement: 
Elapsed time is 0.180011 seconds. 
Pure for loop on cell declared on statement: 
Elapsed time is 0.242995 seconds. 
Pure for loop on cell declared before statement: 
Elapsed time is 0.228705 seconds. 
Pure for loop calculating length on statement: 
Elapsed time is 0.178931 seconds. 
Pure for loop calculating length before statement: 
Elapsed time is 0.178486 seconds. 
Pure while loop using le: 
Elapsed time is 1.138081 seconds. 
Pure while loop using lt+1: 
Elapsed time is 1.241420 seconds. 
Pure while loop using lt+1 pre allocated: 
Elapsed time is 1.162546 seconds. 

I risultati ora zona come previsto ...

risposta

3

Questo risultato non ha nulla a che fare con preallocare o no: si tratta di MATLAB essendo abilitare o di non calcolare le cose con più nuclei. Quando si inserisce l'operatore dei due punti all'interno dell'istruzione for, dice a matlab di utilizzare diversi core (ad esempio il multithreading).

Se si imposta matlab su un core solo con feature('accel','off'), la differenza osservata con doubles scompare. Per quanto riguarda cells, matlab non utilizza il multithreading, pertanto non è possibile notare alcuna differenza (qualunque sia lo stato di accel).

Il ciclo for è multithreading quando si utilizzano due punti e solo se si utilizzano i due punti. I seguenti vettori di lunghezza simile non svolge più nuclei:

  • for k = randperm(N)
  • for k = linspace(1,N,N)

ma for k = 1:0.9999:N è multithreading.

Una spiegazione può essere trovata su questo matlab's support page. Afferma che l'elaborazione multi-core può essere eseguita quando "Le operazioni nell'algoritmo eseguite dalla funzione sono facilmente partizionate in sezioni che possono essere eseguite contemporaneamente.". Con un operatore del colon, Matlab sa che è possibile partizionare for.

+0

Ora ha senso ... grazie! – Werner

+3

In che modo Matlab può sapere in anticipo che è possibile eseguire il multi-thread su un ciclo 'for'? La mia comprensione è che Matlab eseguirà in modo nativo funzioni multi-thread come 'fft',' eig', 'svd' e' sort', ma per ottenere il multithreading su un loop richiede la toolbox di elaborazione parallela e un costrutto 'parfor' ... C'è qualche documentazione ufficiale che discute questa funzionalità? –

+0

@Colin T Bowers - vedere la modifica. Alla mia comprensione; la funzione 'parfor' è usata per multithreadare il contenuto di un blocco' for'. Qui, è solo la chiamata alla funzione ripetitiva che viene valutata. – marsei