Bene, ovviamente il primo ciclo è più lento. Senza nemmeno approfondire gli errori di pagina e le pagine del sistema operativo in memoria all'accesso, il passo del ciclo è lungo 8200 byte (supponendo 32 bit di padding) per passare da un campo di dati n
al successivo.
In genere la macchina recupera tutti i dati dei campi circostanti in ind_vec
quando si caricano pagine (ad esempio 4k pagine) in righe di cache (ad esempio 64 byte) in un registro (ad esempio 64 bit), solo per accedere al campo n
(ad esempio 4 byte) e quindi sprecare l'intero tempo di paging in 4 kilobyte di memoria e spostarsi verso il basso della gerarchia con 64 linee di cache di byte fino a un registro generale solo per elaborare 4 dei 64 byte di dati in la linea della cache e 4 dei 4 kilobyte di dati nella pagina. In pratica stai facendo perdere tempo alla macchina spostando la memoria non rilevante per il tuo loop (accedendo solo a 4/8200 byte del tuo ind_vec
struct ogni iterazione) lungo la gerarchia. Questo cancellerà la località spaziale.
Nel frattempo con il secondo ciclo, si accede generalmente a tutti i dati caricati in una pagina e in una linea della cache prima dello sfratto. Il secondo ciclo attraversa una serie di interi molto densi in cui non si sta causando perdite di tempo per l'hardware e il sistema operativo che spostano la memoria verso il basso nella gerarchia solo per elaborare una minima frazione di esso prima dello sfratto.
Gerarchia di memoria
L'hardware ha una gerarchia di memoria che va dal più piccolo (registro) al più grande (disco seguito da DRAM) e allo stesso modo dal più veloce al più lento (il più piccolo è il più veloce, il più grande è il più lento).
Per evitare di accedere alla memoria grande ma lenta troppo spesso, le macchine caricano in memoria da regioni lente in blocchi contigui (es: 4 kilobyte per una pagina, 64 byte per una linea cache). Afferra la memoria dai tipi lenti di memoria a mano a mano, per così dire. Lo fa ogni volta che si richiede di fare qualsiasi cosa con uno specifico indirizzo di memoria se la memoria intorno all'indirizzo non è già cercata o già in una linea di cache. Per ottenere il massimo beneficio con questo processo, si desidera scrivere il codice in un modo tale che quando hardware e sistema operativo stanno acquisendo dati dalla memoria lenta in blocchi contigui di grandi dimensioni (a mano a mano) e spostandosi verso il basso nella gerarchia di memoria, non si è sprecare quel costoso processo semplicemente accedendo a pochi byte di quei blocchi prima di tentare di accedere a molta memoria altrove da un indirizzo distante totalmente diverso (che è ciò che fa il primo loop).
M & M Analogy
Ilcodicechehaioriginariamenteconilprimociclostafacendopassarel'hardwareattraversoicerchisolopersprecarelamaggiorpartedellosforzo.ÈcomeusareuncucchiaiogiganteperscavareinunaciotoladiM&MssoloperpoiscegliereemangiaresoloilM&MsverdeepoilanciareilrimanenteM&Maparte.ÈmoltoinefficienteinvecedimangiaretuttiicoloridiM&MsinunacucchiaiataallavoltaoavereunaciotolacheconsistesolodiM&Msverde,quellicheinrealtàsimangeranno,inmododapotermangiareintericucchiaidiM&verde;Mssubito.
NelfrattempoilsecondocicloècomemangiaredaunaciotoladisoloM&Msverde.Conquelsecondociclo,puoimangiareinterecucchiaiatediM&Msverdecontemporaneamentedatochestaiaccedendoatuttiidatinell'arrayenonsaltaretroppesezioniconunepicopassoda8kilobyte.
Scissionecampicaldi/freddi
Q2)Isthereanyworkaroundhere?
Larispostapiùdirettaalproblemaconcettualeneltuocasodiesempioèladivisionedelcampocaldo/freddo.Noncaricareunabarcadidatichenonsiaccedeapercorsicriticinellastessastrutturaoclassedeidatiacuisiaccedefrequentemente.Memorizzalosullatoinparallelo,inquestomodo:
structind_vec_cold{//Coldfieldsnotaccessedfrequently.floatind_1[4096];floatind_2[4096];};structind_vec_hot{//Hotfieldsaccessedfrequently.intn;};structind_vec{ind_vec(intn):hot(n),cold(n){}vector<ind_vec_hot>hot;vector<ind_vec_hot>cold;};ind_vecdata(NT);for(inti=0;i<100;i++){//Notslowanymore!data.hot[i].n=1;}
Usando l'analogia di M & M sopra, questo approccio di divisione del campo caldo / freddo raggiunge efficacemente l'effetto di avere una ciotola di solo M & Ms verde così che ora possiamo consumarli rapidamente con il cucchiaio. Usiamo una ciotola diversa per memorizzare gli altri colori M & M. Precedentemente hai avuto una mescolanza di M & Ms e stavi costringendo la macchina ad afferrare M & Ms dal cucchiaio solo per scegliere i pochi M & Ms verdi in quel cucchiaio e poi gettare il resto da parte.