Fila maggiore rispetto a colonna maggiore disposizione delle matrici


16

Nella programmazione di calcoli a matrice densa, c'è qualche motivo per scegliere un layout di riga maggiore del layout di colonna maggiore?

So che, a seconda del layout della matrice scelta, dobbiamo scrivere il codice appropriato per utilizzare le memorie cache in modo efficace per scopi di velocità.

Il layout delle righe principali sembra più naturale e più semplice (almeno per me). Ma le principali librerie come LAPACK che sono scritte in Fortran usano il layout principale delle colonne, quindi ci deve essere qualche motivo per aver fatto questa scelta.


Se consideriamo il calcolo di b = A * x con il vettore della colonna x, per la riga maggiore A possiamo usare i prodotti interni dei vettori, A (i,:) ^ T x per ottenere b (i); per la colonna maggiore potremmo aver bisogno solo di vettori moltiplicatori scalari, sum_i A (:, i) x (i). Mi sembra che la colonna maggiore sia molto meglio! Cosa pensi?
Hui Zhang,

Allenati per amare la colonna maggiore. È facile quando visualizzi i vettori come colonne o la loro trasposizione come righe. Rende molto semplice la visualizzazione della moltiplicazione di matrici e facilita il monitoraggio di molti calcoli matematici pubblicati.
Mike Dunlavey,

Risposte:


18

Il layout principale della colonna è lo schema utilizzato da Fortran ed è per questo che viene utilizzato in LAPACK e in altre librerie.

In generale, è molto più efficiente in termini di utilizzo della larghezza di banda della memoria e prestazioni della cache accedere agli elementi di un array nell'ordine in cui sono disposti in memoria. A seconda di come sono memorizzate le tue matrici, ti consigliamo di scegliere algoritmi che ne approfittano.

archiviazione interna Memoria interna del formato principale della colonna


11

Nel vuoto senza considerare alcun software esistente, non c'è motivo di preferire la colonna maggiore alla riga maggiore dal punto di vista del codice. Tuttavia, la maggior parte della letteratura matematica è scritta in un modo che raggruppa i vettori in una matrice memorizzandoli come colonne anziché righe. Ad esempio, quando si scrive l'equazione autovalore completa , la XUNX=XΛXla matrice contiene tutti gli autovettori scritti in colonne. Non lo vedi mai davvero scritto nell'altro modo (anche se ho sentito che la gente della statistica ama i vettori di riga). Pertanto, era naturale che il primo software assumesse il formato maggiore di colonna in modo che se si dispone di una matrice che è un insieme di vettori, la memorizzazione di ogni singolo vettore è contigua. Quindi, immagino che la tradizione sia stata portata avanti fino ai giorni nostri, e se vuoi interagire con la vecchia Fortran, vuoi usare la colonna maggiore. Quindi quasi tutta l'algebra lineare numerica altamente efficiente viene eseguita nella colonna maggiore.

Il motivo per cui C è la riga maggiore è in qualche modo una conseguenza della sua sintassi dell'array; si dichiara un array di 3 righe per 2 colonne come double a[3][2], e gli indici successivi variano più velocemente degli indici precedenti, il che per gli array 2D lo rende più importante. Combinalo con il naturale ordine di lettura occidentale da sinistra a destra, fa sembrare più naturale la riga maggiore.


2
Penso che questi siano scarsi argomenti. Il fatto che l'ultimo indice in '' 'raddoppi un [3] [2]' '' varia più velocemente non è una coincidenza: è stata una decisione di progettazione consapevole esattamente come è stata una decisione di progettazione consapevole in Fortran a fallo al contrario quando hai un array '' 'real (3,2)' ''.
Wolfgang Bangerth,

1
Inoltre, non è più vero che praticamente tutta l'algebra numerica lineare altamente efficiente è la colonna maggiore. Questo può ancora essere vero per BLAS e LAPACK, ma non lo è affatto per tutte le principali librerie di algebra lineare apparse negli ultimi 15 anni: ad esempio, sia PETSc che Trilinos utilizzano i principali formati di archiviazione a matrice sparsa.
Wolfgang Bangerth,

Sono consapevole che la convenzione C è stata una decisione consapevole, probabilmente basata sul naturale ordine di lettura. Intendevo dire che probabilmente non è stato progettato pensando all'algebra lineare numerica, il che rende una coincidenza il fatto che sia importante. In secondo luogo, non intendevo sostenere l'argomento per le matrici sparse, solo denso. Per quanto riguarda gli sparsi, è un po 'un mix di back out là fuori, con entrambi i formati di riga e colonna compressi.
Victor Liu,

5
Non per ribadire il punto, ma C era originariamente un linguaggio di sistema, basato su lingue precedenti B e BCPL, in esecuzione su sistemi come il PDP-11 che in origine non aveva numeri in virgola mobile. Dire che l'hanno progettato pensando ai numeri è abbastanza lungo.
Victor Liu,

7
Ci sono stato, ecc. Il motivo per cui le matrici in C spostano più velocemente l'ultimo indice è perché C non ha matrici. Ha vettori di vettori, che possono essere implementati in modo trasparente come solidi blocchi di memoria o come matrici di puntatori a matrici. Rendere compatibile l'indice con Fortran era (immagino) nemmeno sul radar di Dennis Ritchie.
Mike Dunlavey,

2

L'ordine delle colonne principali sembra essere più naturale. Ad esempio, supponiamo che se si desidera salvare un filmato su file immagine per immagine, si sta utilizzando l'ordine delle colonne, e questo è molto intuitivo e nessuno lo salverebbe nell'ordine delle righe principali.

Se sei programmatore in C / C ++ dovresti usare alcune librerie di livello superiore per le matrici (Eigen, Armadillo, ...) con l'ordine principale delle colonne predefinito. Solo il maniaco userebbe i puntatori C grezzi con l'ordine delle righe maggiori, sebbene C / C ++ offra qualcosa che ricordi l'indicizzazione della matrice.

Per semplicità, tutto con un ordine maggiore deve essere considerato come almeno strano. Slice per slice è semplicemente un ordine naturale e significa un ordine di colonna maggiore (come Fortran). I nostri padri / madri avevano ottime ragioni per cui l'avevano scelto.

Sfortunatamente, prima che diventasse chiaro, diverse librerie interessanti furono create in ordine di fila, probabilmente a causa della mancanza di esperienza.

Per chiarire il richiamo della definizione di ordine maggiore di riga in cui l'indice destro varia più rapidamente in un passaggio attraverso la memoria, ad esempio A (x, y, z) è indice z, significa che in memoria pixel di sezioni diverse sono adiacenti, ciò che vorremmo voglio. Per il film A (x, y, t) l'ultimo indice è il tempo t. Non è difficile immaginare che sia semplicemente impossibile salvare un film in modalità fila maggiore.


2

m×n

  • mio,jio×m+j
  • mio,jj×n+io

Ora immagina il seguente algoritmo:

for i from 1 to m
   for j from 1 to n
      do something with m(i,j)

io×m+j

conclusioni:

  1. sì, ha un'importanza, ma la scelta dipende dal modo in cui i dati sono accessibili. Per l'esempio precedente, se viene utilizzato l'ordine delle colonne, ciò che è possibile fare è semplicemente scambiare i due loop.

  2. regola empirica: l'indice a variazione rapida deve essere mappato su posizioni successive in memoria.

  3. ancora più importante, misurare / confrontare l'impatto della scelta è fondamentale, poiché dipende da molti parametri (la dimensione dei dati, la dimensione della cache, il modo in cui la lingua utilizzata mappa più indici su un indice lineare, il modo in cui il funzionamento il sistema gestisce la memoria virtuale, il modo in cui i loop sono nidificati nella libreria di algebra lineare che usi ...)

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.