Domanda

Mi è stato chiesto di misurare le prestazioni di un programma fortran che risolve equazioni differenziali su un sistema multi-CPU. Il mio datore di lavoro insiste sul fatto che misuro FLOP / s (operazioni mobili al secondo) e confronti i risultati con i benchmark ( LINPACK ) ma non sono convinto che sia la strada da percorrere, semplicemente perché nessuno può spiegarmi cos'è un FLOP.

Ho fatto qualche ricerca su cosa sia esattamente un FLOP e ho ottenuto risposte piuttosto contraddittorie. Una delle risposte più popolari che ho ricevuto è stata "1 FLOP = Un'aggiunta e un'operazione di moltiplicazione". È vero? In tal caso, di nuovo, fisicamente, cosa significa esattamente?

Qualunque sia il metodo che utilizzo, deve essere scalabile. Alcune versioni del codice risolvono i sistemi con milioni di incognite e richiedono giorni per l'esecuzione.

Quali sarebbero alcuni altri modi efficaci per misurare le prestazioni nel mio caso (il sommario del mio caso è 'codice fortran che esegue molti calcoli aritmetici ripetutamente per giorni su diverse centinaia di CPU)?

È stato utile?

Soluzione

È una misura abbastanza decente delle prestazioni, purché tu capisca esattamente cosa misura.

FLOPS è, come suggerisce il nome OPerazioni in punti flottanti al secondo, esattamente ciò che costituisce un FLOP potrebbe variare in base alla CPU. (Alcune CPU possono eseguire addizioni e moltiplicazioni come un'operazione, altre no, ad esempio). Ciò significa che come misura delle prestazioni, è abbastanza vicino all'hardware, il che significa che 1) devi conoscere il tuo hardware per calcolare i FLOPS ideali sull'architettura data e devi conoscere l'algoritmo e l'implementazione per capire come molte operazioni in virgola mobile in cui consiste effettivamente.

In ogni caso, è uno strumento utile per esaminare quanto bene usi la CPU. Se conosci le prestazioni di picco teoriche della CPU in FLOPS, puoi capire con quale efficienza usi le unità a virgola mobile della CPU, che sono spesso difficili da utilizzare in modo efficiente. Un programma che esegue il 30% dei FLOP di cui è capace la CPU, ha spazio per l'ottimizzazione. Uno che funziona al 70% probabilmente non diventerà molto più efficiente se non cambi l'algoritmo di base. Per gli algoritmi matematici pesanti come il tuo, questo è praticamente il modo standard per misurare le prestazioni. Potresti semplicemente misurare il tempo necessario per l'esecuzione di un programma, ma questo varia notevolmente a seconda della CPU. Ma se il tuo programma ha un utilizzo della CPU del 50% (rispetto al conteggio FLOPS di picco), questo è un valore un po 'più costante (varierà comunque tra architetture CPU radicalmente diverse, ma è molto più coerente del tempo di esecuzione).

Ma sapendo che " La mia CPU è in grado di X GFLOPS, e in realtà sto solo raggiungendo un throughput, diciamo, del 20% di quello " sono molto preziose informazioni in software ad alte prestazioni. Significa che qualcosa diverso oltre alle operazioni in virgola mobile ti sta trattenendo e impedisce alle unità FP di funzionare in modo efficiente. E poiché le unità FP costituiscono la maggior parte del lavoro, ciò significa che il tuo software ha un problema.

È facile misurare " Il mio programma funziona in X minuti " ;, e se ritieni che sia inaccettabile, certo, puoi andare " Mi chiedo se posso tagliare il 30% di sconto su " ;, ma non < em> know se ciò è possibile a meno che non si riesca a capire esattamente quanto lavoro è stato fatto ed esattamente di cosa è capace la CPU al massimo. Quanto tempo vuoi dedicare all'ottimizzazione di questo, se non sai nemmeno se la CPU è fondamentalmente in grado di eseguire ulteriori istruzioni al secondo?

È molto facile impedire che l'unità FP della CPU venga utilizzata in modo efficiente, avendo troppe dipendenze tra le operazioni FP o avendo troppe filiali o simili che impediscono una pianificazione efficiente. E se questo è ciò che impedisce l'implementazione, devi saperlo. Devi sapere che "non sto ottenendo il throughput FP che dovrebbe essere possibile, quindi chiaramente altre parti del mio codice stanno impedendo la disponibilità delle istruzioni FP quando la CPU è pronta a emetterne uno".

Perché hai bisogno di altri modi per misurare le prestazioni? Cosa c'è di sbagliato nel calcolare i conteggi FLOPS come ti ha chiesto il tuo capo? ;)

Altri suggerimenti

Vorrei solo aggiungere un paio di punti più fini:

  • divisione è speciale. Poiché la maggior parte dei processori può eseguire un'aggiunta, un confronto o una moltiplicazione in un singolo ciclo, questi vengono tutti considerati come un flop. Ma la divisione richiede sempre più tempo. Quanto più a lungo dipende dal processore, ma esiste una sorta di standard defacto nella comunità HPC per contare una divisione come 4 flop.

  • Se un processore ha un'istruzione moltiplica-aggiungi fusa che esegue una moltiplicazione e un'aggiunta in una singola istruzione - generalmente A + = B * C - che conta come 2 operazioni .

  • Fai sempre attenzione a distinguere tra flop a precisione singola e flop a precisione doppia . Un processore capace di così tanti gigaflop a precisione singola può essere in grado di produrre solo una piccola parte di quei gigaflop a precisione doppia. I processori AMD Athlon e Phenom possono generalmente fare la metà del numero di flop a doppia precisione rispetto alla precisione singola. I processori ATI Firestream possono generalmente eseguire 1/5 ° numero di flop a doppia precisione come precisione singola. Se qualcuno sta cercando di venderti un processore o un pacchetto software e citano semplicemente i flop senza dire quale, dovresti chiamarli su di esso.

  • I termini megaflop, gigaflop, teraflop, ecc. sono di uso comune. Questi si riferiscono a fattori di 1000 , non 1024 . Ad esempio, 1 megaflop = 1.000.000 di flop / sec non 1.048.576. Proprio come con le dimensioni dell'unità disco, c'è un po 'di confusione su questo.

"confronta i risultati con i benchmark" e fare cosa?

FLOPS significa che è necessario

1) FLOP per alcune unità di lavoro.

2) tempo per quell'unità di lavoro.

Supponiamo che tu abbia un file di input che esegue 1.000 iterazioni attraverso un ciclo. Il ciclo è una pratica unità di lavoro. Viene eseguito 1.000 volte. Ci vuole un'ora.

Il ciclo ha alcune aggiunte e moltiplicazioni e alcune divisioni e una radice quadrata. Puoi contare aggiunte, moltiplicazioni e divisioni. Puoi contarlo nella fonte, cercando +, * e /. Puoi trovare l'output in linguaggio assembler dal compilatore e contarli anche lì. Potresti ottenere numeri diversi. Qual è giusto? Chiedi al tuo capo.

Puoi contare le radici quadrate, ma non sai cosa fa realmente in termini di moltiplicazioni e aggiunte. Quindi, dovrai fare qualcosa come moltiplicare il benchmark rispetto alla radice quadrata per avere un'idea di quanto tempo impiega una radice quadrata.

Ora conosci i FLOP nel tuo loop. E conosci il tempo per eseguirlo 1.000 volte. Conosci FLOPS al secondo.

Quindi guardi LINPACK e scopri che sei più lento. E adesso? Il tuo programma non è LINPACK ed è più lento di LINPACK. Le probabilità sono davvero buone che il tuo codice sarà più lento. A meno che il tuo codice non sia stato scritto e ottimizzato nello stesso numero di anni un LINPACK, sarai più lento.

Ecco l'altra parte. Il tuo processore ha una valutazione FLOPS definita rispetto a vari benchmark. Il tuo algoritmo non è uno di quei benchmark, quindi non sei all'altezza dei benchmark. È male? O è questa l'ovvia conseguenza di non essere un punto di riferimento?

Quale sarà il risultato attuabile?

La misurazione in base a una base di codice di riferimento ti dirà solo che il tuo algoritmo non è l'algoritmo di riferimento. È scontato che sarai diverso; di solito più lento.

Ovviamente, il risultato della misurazione rispetto a LINPACK sarà (a) sei diverso e quindi (b) devi ottimizzare.

La misurazione è davvero preziosa solo se eseguita contro te stesso . Non un ipotetico mix di istruzioni, ma il tuo mix di istruzioni. Misura la tua performance. Fare un cambiamento. Verifica se le tue prestazioni, rispetto a te, migliorano o peggiorano.

I FLOP non contano. Ciò che conta è il tempo per unità di lavoro. Non abbinerai mai i parametri di progettazione del tuo hardware perché non stai eseguendo il benchmark che i tuoi progettisti hardware si aspettavano.

LINPACK non ha importanza. Ciò che conta è la tua base di codice e le modifiche che stai apportando per cambiare le prestazioni.

Vecchia domanda con risposte vecchie, se popolari, che non sono proprio grandiose, IMO.

A & # 8220; FLOP & # 8221; è un'operazione matematica a virgola mobile. & # 8220; FLOPS & # 8221; può significare una delle due cose:

  • Il semplice plurale di & # 8220; FLOP & # 8221; (ad es. & # 8220; l'operazione X richiede 50 FLOP & # 8221;)
  • La frequenza dei FLOP nel primo senso (ovvero operazioni matematiche in virgola mobile al secondo)

Laddove non sia chiaro dal contesto, quale di questi si intende è spesso chiarito scrivendo il primo come & # 8220; FLOPs & # 8221; e quest'ultimo come & # 8220; FLOP / s & # 8221 ;.

I FLOP sono così chiamati per distinguerli da altri tipi di operazioni della CPU , come operazioni matematiche intere, operazioni logiche, operazioni bit a bit, operazioni di memoria e operazioni di ramificazione, che hanno costi diversi (leggi & # 8220; impiegano diversi periodi di tempo & # 8221;) ad essi associati.

La pratica di & # 8220; conteggio FLOP & # 8221; risale ai primissimi tempi dell'informatica scientifica, quando i FLOP erano, relativamente parlando, estremamente costosi, prendendo molti cicli della CPU ciascuno. Un coprocessore matematico 80387, ad esempio, impiegava qualcosa come 300 cicli per una singola moltiplicazione. Questo avveniva in un momento prima del pipelining e prima che il divario tra le velocità di clock della CPU e le velocità di memoria si fosse davvero aperto: le operazioni di memoria richiedevano solo un ciclo o due e la ramificazione (& # 8220; processo decisionale & # 8221;) era altrettanto economica. Allora, se potessi eliminare un singolo FLOP a favore di una dozzina di accessi alla memoria, hai ottenuto un guadagno. Se potessi eliminare un singolo FLOP a favore di una dozzina di filiali, hai ottenuto un guadagno. Quindi, in passato, aveva senso contare i FLOP e non preoccuparsi molto dei riferimenti e dei rami della memoria perché i FLOP dominavano fortemente i tempi di esecuzione perché erano individualmente molto costosi rispetto ad altri tipi di operazioni.

Più recentemente, la situazione si è invertita. I FLOP sono diventati molto economici & # 8212; qualsiasi moderno core Intel può eseguire circa due FLOP per ciclo (sebbene la divisione rimanga relativamente costosa) & # 8212; e gli accessi e le filiali di memoria sono relativamente più costosi: un hit della cache L1 costa forse 3 o 4 cicli, un recupero dalla memoria principale costa 150 & # 8211; 200. Data questa inversione, non è più il caso che l'eliminazione di un FLOP a favore di un accesso alla memoria comporti un guadagno ; in effetti, è improbabile. Allo stesso modo, spesso è più economico & # 8220; basta fare & # 8221; un FLOP, anche se ridondante, piuttosto che decidere se farlo o meno. Questo è praticamente l'opposto completo della situazione 25 anni fa.

Sfortunatamente, la pratica del conteggio FLOP cieco come metrica assoluta di merito algoritmico è persistita ben oltre la sua data di scadenza. Il moderno calcolo scientifico riguarda molto di più la gestione della larghezza di banda della memoria & # 8212; cercando di mantenere le unità di esecuzione che fanno i FLOP alimentano costantemente con i dati & # 8212; di quanto si tratti di ridurre il numero di FLOP. Il riferimento a LINPACK (che era sostanzialmente obsoleto da LAPACK 20 anni fa) mi porta a sospettare che il tuo datore di lavoro sia probabilmente di una scuola molto vecchia che non ha interiorizzato il fatto che stabilire le aspettative di prestazione non è più solo una questione di conteggio FLOP. Un solutore che fa il doppio di FLOP potrebbe essere venti volte più veloce di un altro se ha un modello di accesso alla memoria e un layout dei dati molto più favorevoli.

Il risultato finale di tutto ciò è che la valutazione delle prestazioni di software ad alta intensità di calcolo è diventata molto più complessa di quanto non fosse in passato . Il fatto che i FLOP siano diventati economici è enormemente complicato dalla massiccia variabilità dei costi delle operazioni di memoria e delle filiali. Quando si tratta di valutare algoritmi , il semplice conteggio FLOP semplicemente non informa le aspettative complessive sulle prestazioni

Un FLOPS è, come hai detto, un'operazione in virgola mobile al secondo. Ad esempio, se impieghi esattamente un secondo per un'operazione (come aggiungere, sottrarre, moltiplicare o dividere due valori e restituire il risultato), la tua performance è semplicemente 1 FLOPS. Una CPU recente raggiungerà facilmente diversi GigaFLOPS, ovvero diversi miliardi di operazioni in virgola mobile al secondo.

Vorrei solo provare a farlo andare il più velocemente possibile, e questo richiede di scoprire dove sta spendendo tempo, specialmente se ci sono chiamate di funzione che potrebbero essere evitate.

Lo faccio con il semplice metodo di interromperlo alcune volte mentre è in esecuzione e vedere cosa sta facendo. Ecco i tipi di cose che trovo:

  • Gran parte del tempo è in procinto di calcolare il derivato e / o il giacobino. Gran parte di questo tempo può andare in chiamate di funzioni matematiche come exp () , log () e sqrt () . Spesso questi vengono ripetuti con argomenti identici e possono essere memorizzati. (Massiccia velocità.)

  • Gran parte del tempo viene impiegato per calcolare le derivate troppe volte perché le tolleranze di integrazione sono più rigorose del necessario. (Faster)

  • Se viene utilizzato un algoritmo di integrazione implicita (come DLSODE Gear) perché si ritiene che le equazioni siano rigide, è probabile che non lo siano e che potrebbe essere usato qualcosa come Runge-Kutta. (DVERK). (Ancora più veloce)

  • Forse un algoritmo matrice-esponente potrebbe essere usato se il modello è lineare (DGPADM). Questa è una grande vittoria sia per le prestazioni che per la precisione ed è immune alla rigidità. (Molto più veloce)

  • Più in alto nello stack di chiamate, potrebbe essere che le stesse integrazioni vengano eseguite ripetutamente con parametri leggermente diversi, in modo da determinare un gradiente in avanti o di differenza centrale della soluzione rispetto a tali parametri. Se le equazioni differenziali sono esse stesse differenziabili, potrebbe essere possibile ottenere quei gradienti analiticamente o aumentando le equazioni con equazioni di sensibilità. Questo non è solo molto più veloce, ma molto più preciso, che può accelerare le cose ancora più in alto nello stack.

Puoi considerare ogni livello dello stack come un'opportunità per trovare cose da ottimizzare, e le accelerazioni aumenteranno. Quindi, quando vai in multi-cpu, supponendo che sia parallelizzabile, ciò dovrebbe fornire il suo fattore moltiplicativo.

Quindi torniamo ai FLOP. Potresti provare a massimizzare FLOP / secondo , ma può anche essere molto più utile minimizzare FLOP / eseguire , ottimizzando a tutti i livelli dello stack. In ogni caso, solo misurandoli non ti dice quasi nulla.

Il tuo datore di lavoro ha ragione.
L'unico modo per misurare l'efficacia del tuo programma Fortran (o di qualsiasi altro programma, tra l'altro) è testarlo rispetto a benchmark standard, se esistenti.

E, per quanto riguarda i FLOP, sta per "operazioni in virgola mobile al secondo" - vedi la definizione su Wikipedia.

Non penso che misurare FLOPS sia molto utile.

Il numero di FLOPS raggiunti ti dirà quanto è impegnato il tuo algoritmo a mantenere la CPU, ma non ti dirà quanto sta funzionando l'algoritmo stesso.

Potresti trovare due diversi algoritmi che fanno sì che il processore esegua lo stesso numero di FLOPS ma uno ti fornisce il risultato desiderato in metà tempo.

Penso che faresti meglio a guardare una statistica molto di "livello superiore" come il numero di equazioni differenziali risolte per unità di tempo (che è, dopo tutto, lo scopo del tuo algoritmo).

D'altra parte, misurare il numero di FLOPS raggiunti può aiutarti a migliorare il tuo algoritmo in quanto ti dirà quanto sei impegnato a mantenere la CPU.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top