2014-09-29 9 views
9

Ho appena letto uno article di Rico Mariani che riguarda le prestazioni dell'accesso alla memoria a seconda della località, dell'architettura, dell'allineamento e della densità.Cosa causa questo strano calo delle prestazioni con un numero * medio * di articoli?

L'autore ha creato un array di dimensioni variabili contenente un elenco doppiamente collegato con un payload int, che è stato mischiato a una certa percentuale. Ha sperimentato questo elenco e ha trovato risultati coerenti sulla sua macchina.

Citando uno della tabella dei risultati:

Pointer implementation with no changes 
sizeof(int*)=4 sizeof(T)=12 
    shuffle 0% 1% 10% 25% 50% 100% 
    1000 1.99 1.99 1.99 1.99 1.99 1.99 
    2000 1.99 1.85 1.99 1.99 1.99 1.99 
    4000 1.99 2.28 2.77 2.92 3.06 3.34 
    8000 1.96 2.03 2.49 3.27 4.05 4.59 
    16000 1.97 2.04 2.67 3.57 4.57 5.16 
    32000 1.97 2.18 3.74 5.93 8.76 10.64 
    64000 1.99 2.24 3.99 5.99 6.78 7.35 
    128000 2.01 2.13 3.64 4.44 4.72 4.80 
    256000 1.98 2.27 3.14 3.35 3.30 3.31 
    512000 2.06 2.21 2.93 2.74 2.90 2.99 
1024000 2.27 3.02 2.92 2.97 2.95 3.02 
2048000 2.45 2.91 3.00 3.10 3.09 3.10 
4096000 2.56 2.84 2.83 2.83 2.84 2.85 
8192000 2.54 2.68 2.69 2.69 2.69 2.68 
16384000 2.55 2.62 2.63 2.61 2.62 2.62 
32768000 2.54 2.58 2.58 2.58 2.59 2.60 
65536000 2.55 2.56 2.58 2.57 2.56 2.56 

L'autore spiega:

Questa è la misurazione di riferimento. Puoi vedere che la struttura è un bel giro di 12 byte e si allinea bene su x86. Guardando la prima colonna, senza shuffling, come previsto le cose peggiorano e peggiorano man mano che la matrice diventa più grande fino a che la cache non aiuta molto e si ha il peggio che si ottiene, che è di circa 2,55ns su media per articolo.

Ma qualcosa di molto strano può essere visto in giro 32k articoli:

I risultati per rimescolamento non sono esattamente quello che mi aspettavo. A piccole dimensioni, non fa differenza. Mi aspettavo questo perché fondamentalmente l'intera tabella è rimasta calda nella cache e quindi la località non conta. Poi, man mano che la tabella cresce, vedi che il mescolamento ha un grande impatto a circa 32000 elementi. Sono 384k di dati. Probabilmente perché abbiamo superato il limite di 256k.

Ora la cosa bizzarra è questa: dopo di ciò il costo dello shuffling in realtà scende, al punto che in seguito difficilmente conta nulla. Ora posso capire che a un certo punto mescolato o non mescolato in realtà non dovrebbe fare alcuna differenza perché la matrice è così grande che il runtime è ampiamente controllato dalla larghezza di banda della memoria, indipendentemente dall'ordine. Tuttavia ... ci sono punti nel mezzo in cui il costo della non-località è in realtà molto peggiore di quello che sarà nel finale.

Quello che mi aspettavo di vedere era che il rimescolamento ci ha indotti a raggiungere il massimo disagio prima e rimanere lì. Quello che succede in realtà è che le medie dimensioni non località sembrano causare cose molto pessime ... E non so perché :)

Quindi la domanda è: cosa potrebbe aver causato questo comportamento inaspettato?

Ci ho pensato per un po 'di tempo, ma non ho trovato nessuna spiegazione. Il codice di prova mi sta bene. Non credo che la predizione del ramo CPU sia il colpevole in questo caso, in quanto dovrebbe essere osservabile molto prima di 32k e mostrare un picco molto più basso.

Ho confermato questo comportamento sul mio box, sembra praticamente lo stesso.

Ho pensato che potrebbe essere causato dall'inoltro dello stato della CPU, quindi ho cambiato l'ordine di righe e/o generazione di colonne - quasi nessuna differenza nell'output. Per essere sicuro, ho generato i dati per un campione continuo più grande.Per facile di visualizzazione, l'ho messo in Excel:

enter image description here

And another independent run for good measure, negligible difference

risposta

9

ho messo la mia migliore teoria qui: http://blogs.msdn.com/b/ricom/archive/2014/09/28/performance-quiz-14-memory-locality-alignment-and-density-suggestions.aspx#10561107 ma è solo una supposizione, non l'ho confermato.


Mistero risolto! Dal mio blog:

Ryan Lun 29 Set, 2014 09:35 #

Wait - stai giungendo alla conclusione che l'accesso completamente randomizzato è la stessa velocità sequenziale per molto grandi casi? Sarebbe molto sorprendente !!

Qual è l'intervallo di rand()? Se è 32k ciò significherebbe che stai solo mischiando i primi 32k e facendo letture fondamentalmente sequenziali per la maggior parte degli articoli nel caso di grandi dimensioni, e il vg per-item sarebbe molto vicino al caso sequenziale. Questo corrisponde ai tuoi dati molto bene.


Mon, 29 settembre 2014 10:57 #

Questo è esattamente!

La funzione rand restituisce un numero intero pseudocasuale nell'intervallo da 0 a RAND_MAX (32767). Usa la funzione srand per seminare il generatore di numeri pseudocasuali prima di chiamare rand.

Ho bisogno di un generatore di numeri casuali diverso!

Lo rifarò!

Problemi correlati