2016-03-17 38 views
12

Ho una matrice grande A che è 1GB di valori doppi, quando la rimodella a dimensioni diverse, è incredibilmente veloce.Perché la rimodella è così veloce?

A=rand(128,1024,1024); 
tic;B=reshape(A,1024,128,1024);toc 

Elapsed time is 0.000011 seconds. 

Come può essere così veloce? Un'altra osservazione, MATLAB usa meno memoria del dovuto dopo l'esecuzione di tale codice e memorizzando due matrici di 1 GB ciascuna: Memory used by MATLAB: 1878 MB (1.969e+09 bytes)

risposta

21

Spiegazione delle buone prestazioni

Matlab usa copy-on-write quando possibile. Se si scrivono espressioni come B=A, MATLAB non copia A, invece entrambe le variabili A e B sono riferimenti alla stessa struttura dati. Solo se una delle due variabili sarà modificata, MATLAB creerà una copia.

Ora per il caso speciale di reshape. Qui sembra che A e B non siano gli stessi, ma in memoria lo sono. L'array sottostante che contiene i dati non è interessato dall'operazione reshape, non è necessario spostare nulla: all(A(:)==B(:)). Tutto ciò che MATLAB deve fare quando si chiama reshape è creare un nuovo riferimento e annotarlo con le nuove dimensioni della matrice. Rimodellare una matrice non è altro che creare un nuovo riferimento ai dati di input, annotato con le nuove dimensioni. Il runtime di reshape è inferiore a 1μs o all'incirca il tempo richiesto da due semplici assegnazioni come B=A. Per tutte le applicazioni pratiche un'operazione a tempo zero.

>> tic;for i=1:1000;B=reshape(A,1024,128,1024);end;toc 
Elapsed time is 0.000724 seconds. 
>> tic;for i=1:1000;B=A;end;toc 
Elapsed time is 0.000307 seconds. 

Non si sa quanto sia grande tale riferimento, ma si può supporre che si trovi entro pochi byte.

Altre operazioni zero cost

Funzioni noti per avere praticamente a costo zero (sia runtime e memoria):

  • B=reshape(A,sz)
  • B=A(:)
  • B=A.' - solo per vettori
  • B=A' - solo per Vettori di numeri reali, without the attribute complex. Utilizzare invece .'.
  • B=permute(A,p) - solo per i casi in cui all(A(:)==B(:)).
  • B=ipermute(A,p) - solo per i casi in cui all(A(:)==B(:)).
  • B=squeeze(A)
  • shiftdim - solo per i casi in cui all(A(:)==B(:)), che sono:
    • usato per rimuovere principali dimensioni singoletto.
    • utilizzato con secondo ingresso negativo
    • utilizzato senza secondo argomento di input.

funzioni che sono "costoso", a prescindere dal fatto che essi non toccano la rappresentazione in memoria (all(A(:)==B(:)) è vero)

  • sinistra si schierò indicizzazione: B(1:numel(A))=A;
  • Indicizzazione lato destro diverso da (:), incluso B=A(1:end); e B=A(:,:,:);

runtime notevolmente inferiore reshape tra 1μs e 1ms. Probabilmente a causa di alcuni overhead di calcolo costanti. Il consumo di memoria è praticamente pari a zero e il runtime è indipendente dalla dimensione di input. Le operazioni senza questa annotazione hanno un tempo di esecuzione inferiore a 1μs e approssimativamente equivalente a reshape.

Zero costo in OCTAVE