Una risposta un po 'più lunga che spiega perché è più efficiente far variare più rapidamente l'indice più a sinistra. Ci sono due cose chiave che devi capire.
In primo luogo, MATLAB (e Fortran, ma non C e la maggior parte degli altri linguaggi di programmazione) memorizza gli array in memoria in "ordine maggiore di colonna". ad es. se A è una matrice 2 per 3 per 10, le voci verranno memorizzate nell'ordine
A (1,1,1)
A (2,1,1)
A (1,2,1)
A (2,2,1)
A (1,3,1)
A (2,3,1)
A (1,1,2)
A (2,1,2)
...
A (2,3,10)
Questa scelta di ordine maggiore di colonna è arbitraria, potremmo semplicemente adottare una convenzione di "ordine maggiore di riga", e in effetti è ciò che viene fatto in C e in altri linguaggi di programmazione.
La seconda cosa importante che devi capire è che i moderni processori non accedono alla memoria una posizione alla volta, ma piuttosto caricano e memorizzano "linee di cache" di 64 o addirittura 128 byte contigui (8 o 16 numeri in virgola mobile a precisione doppia) alla volta dalla memoria. Questi blocchi di dati vengono temporaneamente archiviati in una cache di memoria veloce e riscritti secondo necessità. (In pratica l'architettura della cache è ora piuttosto complicata con fino a 3 o 4 livelli di memoria cache, ma l'idea di base può essere spiegata con una cache a un livello del tipo che i computer avevano ai miei tempi più giovani.)
Supponiamo ora che sia un array con 10.000 righe e colonne e che sto eseguendo il ciclo su tutte le voci. A
Se i loop sono nidificati in modo tale che il loop più interno aggiorni il pedice di riga, si accederà alle voci dell'array nell'ordine A (1,1), A (2,1), A (3,1), ... Quando si accede alla prima voce A (1,1), il sistema porterà una cache contenente A (1,1), A (2,1), ..., A (8,1) nella cache dalla memoria principale . Le successive 8 iterazioni del ciclo più interno funzionano su questi dati senza ulteriori trasferimenti di memoria principale.
Se in alternativa, strutturiamo i loop in modo che l'indice di colonna vari nel ciclo più interno, si accederà alle voci di A nell'ordine A (1,1), A (1,2), A (1,3 ), ... In questo caso, il primo accesso porterebbe A (1,1), A (2,1), ..., A (8,1) nella cache dalla memoria principale, ma 7/8 di queste voci non sarebbero state utilizzate. L'accesso ad A (1,2) nella seconda iterazione porterebbe quindi ulteriori 8 voci dalla memoria principale e così via. Quando il codice inizia a funzionare sulla riga 2 della matrice, la voce A (2,1) potrebbe essere eliminata dalla cache per lasciare spazio ad altri dati necessari. Di conseguenza, il codice sta generando 8 volte il traffico necessario.
Alcuni compilatori ottimizzati sono in grado di ristrutturare automaticamente i loop per evitare questo problema.
Molti algoritmi di algebra lineare numerica per la moltiplicazione e la fattorizzazione delle matrici possono essere ottimizzati per funzionare in modo efficiente con lo schema di ordinamento riga maggiore o colonna maggiore in base al linguaggio di programmazione. In questo modo nel modo sbagliato può avere un impatto negativo significativo sulle prestazioni.
For
i loop sono molto lenti in MATLAB. Dovresti evitare cicli espliciti in MATLAB quando possibile. Invece, di solito un problema può essere espresso in termini di operazioni matrice / vettoriale. Questo è il modo MATLABic. Ci sono anche molte funzioni integrate per inizializzare le matrici, ecc. Ad esempio, esiste una funzione, ones () , che imposta tutti gli elementi di una matrice su 1 (per estensione, su qualsiasi valore per moltiplicazione (uno scalare moltiplicato per la matrice di tutti)). Funziona anche su array 3D (che a mio avviso copre l'esempio qui).