Imparare a ottimizzare con Assembly [chiuso]


21

Sono uno studente del secondo anno di Computer Games Technology. Di recente ho terminato il mio primo prototipo del mio "tipo" di pathfinder personale (che non utilizza A * invece di un approccio geometrico / riconoscimento del modello, il pathfinder necessita solo della conoscenza del terreno che è nella sua visione per prendere decisioni, perché io voleva un'intelligenza artificiale che potesse effettivamente esplorare, se il terreno è già noto, allora camminerà facilmente nel modo più breve, perché il pathfinder ha una memoria di nodi).

Ad ogni modo la mia domanda è più generale: come posso iniziare a ottimizzare algoritmi / loop / for_each / etc. usando Assembly, anche se i suggerimenti generali sono ben accetti. In particolare cerco buoni libri, perché è davvero difficile trovare buoni libri su questo argomento. Ci sono alcuni piccoli articoli là fuori come questo , ma non c'è ancora abbastanza conoscenza per ottimizzare un algoritmo / gioco ...

Spero che ci sia un buon libro moderno là fuori, che non sono riuscito a trovare ...


1
Questo non risponde direttamente alla tua domanda, ma esplorativo (il cosiddetto adattivo) A * è stato studiato e ha prestazioni davvero buone (il che significa che non dovrai ottimizzarlo usando ASM). Dai un'occhiata a D * Lite .
Jonathan Dickinson,

Risposte:


21

Sarò quello che va controcorrente qui e dirò, non è mai troppo presto per conoscere le ottimizzazioni, in particolare le ottimizzazioni di assemblaggio e, soprattutto, il debug in assembly. Credo che ne trarrai il massimo beneficio se sei uno studente (perché allora hai molto poco da perdere [vale a dire tempo / denaro saggio]) e tutto da guadagnare.

Se sei nel settore e non hai il compito di armeggiare nel montaggio, allora non farlo. Altrimenti, se sei uno studente o hai tempo in generale, troverei il tempo per imparare a disassemblare i programmi e vedere se riesco a trovare una soluzione migliore rispetto al compilatore. Se non ci riesco, chi se ne frega! Ho appena imparato a scrivere così come il compilatore e questo è un GRANDE vantaggio quando ti trovi di fronte a un bug nel codice di rilascio (senza simboli di debug) e a fissare lo smontaggio perché è l'unica cosa che puoi guardare.

La risposta

Questa è una delle migliori risorse che ho trovato per conoscere le ottimizzazioni.

http://www.agner.org/optimize/

The rant

Se leggi alcuni articoli dei principali sviluppatori (ad esempio, il ragionamento dietro la creazione di EASTL e un'attenta ispezione del codice ti condurrà a commenti come questo perché GCC è terribile nel sottolineare questa dichiarazione if che ti dirà, che cosa la maggior parte di la gente ti dice che il compilatore non è sempre giusto, in particolare nello sviluppo di giochi) e poi metti piede nel settore scoprirai che le ottimizzazioni sono una cosa di tutti i giorni e sapere cosa significa l'output dell'assemblaggio è un grande vantaggio. Inoltre, le persone non sembrano rendersi conto (specialmente su StackOverflow) che i giochi di profilazione sono molto difficili e non sempre precisi.

C'è un avvertimento però. Puoi dedicare del tempo a ottimizzare qualcosa e in seguito renderti conto che è stato tempo perso. Ma cosa hai imparato? Hai imparato a non ripetere lo stesso errore in una circostanza simile.

Ciò che SO sta prendendo ora è secondo me una posizione religiosa verso l'affermazione che non si ottimizza fino a quando non si profila e non ti preoccupare, il compilatore lo sa meglio di te . Ostacola l'apprendimento. Conosco esperti del settore che sono pagati molto bene (e intendo MOLTO buoni soldi) per giocherellare in assemblea per ottimizzare il gioco ed eseguirne il debug perché il compilatore non funziona o semplicemente non può aiutarti, perché, beh, impossibile (arresti anomali relativi alla GPU, arresti anomali in cui è impossibile leggere i dati coinvolti in un debugger ecc. ecc.)!

Che cosa succede se qualcuno che ama farlo, non se ne è ancora reso conto, fa la domanda qui ed è respinto / spento dalle molte risposte che il compilatore conosce meglio di te! e non diventa mai uno di quei programmatori altamente pagati?

Un ultimo pensiero. Se inizi a farlo in anticipo, scoprirai che presto inizierai a scrivere il codice che è nel peggiore dei casi, non ha alcun miglioramento delle prestazioni perché il compilatore lo ha ottimizzato allo stesso modo o nella migliore delle ipotesi, ha alcuni miglioramenti delle prestazioni perché ora il compilatore può ottimizzarlo . In entrambi i casi, è diventata un'abitudine e non sei più lento a scrivere codice in questo modo rispetto a quello che hai fatto prima. Un paio di esempi sono (ce ne sono molti altri):

  1. Preincrementamento a meno che non si desideri veramente postincremento
  2. Scrittura di cicli per contenitori utilizzando una variabile di dimensione locale costante anziché chiamare size () sul contenitore all'interno del ciclo.

EDIT: aggiornamento dopo altri 8 anni nel settore. Impara l'assemblaggio. Scopri come funzionano gli ottimizzatori e l'assemblaggio che generano (CompilerExplorer è un ottimo strumento per questo). Ho riscontrato innumerevoli arresti anomali nelle build di test (build ottimizzate per i test interni) in cui non è possibile fare affidamento sul debugger anche con i simboli di debug. Il compilatore ha ottimizzato troppe cose e l'assemblaggio è l'unica fonte di informazioni preziose per trovare il bug dal dump dell'arresto anomalo. Ogni build richiede 30-40 minuti se sei fortunato e primo nella coda di build - quindi non puoi fare affidamento su alcune tecniche tradizionali per isolare il bug. Il multiplayer peggiora le cose. Conoscere l'assemblaggio e come leggere l'assemblaggio ottimizzato ti renderà semplicemente migliore e in definitiva più prezioso per il team.


1
Un buon punto sull'ottimizzazione dei compilatori. Sono fantastici da avere, ma sono tutt'altro che perfetti, e diversamente da ciò che alcune persone credono di solito non è difficile trovare una semplice ottimizzazione che un compilatore non ha fatto.
aaaaaaaaaaaa,

3
Va notato che esiste una differenza tra "imparare a leggere il montaggio" e "imparare a ottimizzare con il montaggio". I due non sono la stessa cosa e la tua risposta non tocca davvero l'utilizzo dell'assembly per implementare le ottimizzazioni. Leggere l'assemblaggio è un'abilità utile, poiché può aiutare a individuare e individuare i luoghi in cui il compilatore non sta facendo qualcosa di giusto. Ma questo è molto diverso dall'uso effettivo di assembly per scrivere routine ottimizzate, il che richiede una profonda conoscenza della pianificazione delle istruzioni per una CPU specifica. Ed è anche qualcosa che non hai trattato.
Nicol Bolas,

1
Inoltre, "Ho appena imparato a scrivere e compilatore" No, non l'hai fatto. Hai osservato come è stata compilata una routine specifica per una CPU specifica. Imparare come implementare routine di assemblaggio ottimizzate richiede più che guardare come il compilatore ha compilato una routine. Devi capire perché il compilatore ha scelto quei codici operativi in ​​quell'ordine per riprodurre quel codice C ++ specifico. Ciò richiede una conoscenza approfondita della CPU, la programmazione delle istruzioni e così via. Generalizzare questo richiede anni di esperienza; non lo capirai semplicemente decodificando un paio di routine.
Nicol Bolas,

7
Quindi, -1 per A: in realtà non risponde alla domanda su come scrivere routine ottimizzate per l'assemblaggio. B: travisare quanto sia facile imparare a battere il compilatore durante la scrittura di routine ottimizzate per l'assemblaggio. E C: incoraggiare un programmatore a esaminare le ottimizzazioni a livello di assembly prima delle ottimizzazioni a livello di algoritmo. Perfino quegli "esperti del settore" altamente pagati ti direbbero che sta mettendo il carro davanti al cavallo.
Nicol Bolas,

2
@Samaursa: nessuno ha detto che le persone non dovrebbero "comprendere lo smontaggio e come ottimizzare il codice". Questo non è un dibattito religioso; è un dato di fatto. Le persone hanno trascorso secoli umani ottimizzando a mano qualche routine solo per scoprire che non significa nulla per le prestazioni complessive. Imparare come ottimizzare gli algoritmi è uno skillset di grande valore. Imparare a leggere il montaggio è uno skillset semi-prezioso. Imparare a scrivere routine di assemblaggio è uno skillset che è raramente utile. E in questi giorni, le migliori ottimizzazioni derivano da un migliore utilizzo della cache, non dall'assemblaggio manuale.
Nicol Bolas,

22

Il primo consiglio che otterrai è questo: non farlo.

I compilatori moderni sono davvero molto bravi nell'ottimizzare il codice e saranno molto più propensi a fare un lavoro migliore di esso rispetto a qualsiasi linguaggio di assemblaggio a rotazione automatica che potresti scrivere.

L'eccezione sarebbe qualsiasi caso specifico in cui hai determinato con certezza che il compilatore sta facendo un pessimo lavoro di ottimizzazione, quindi questo è il secondo suggerimento. Non ci sono linee guida generali qui, devi conoscere il tuo codice, sapere cosa sta facendo, essere in grado di saltare in uno smontaggio di esso ed essere in grado di determinare con assoluta certezza che il compilatore sta facendo un cattivo lavoro.

Anche in questo caso potresti ancora non volerlo. È necessario essere certi che non ci saranno spese generali di manutenzione in corso per te. Potresti voler tornare a questo codice tra 6 mesi e modificarne una parte, oppure potresti trovare un bug estremamente sottile che sarà più difficile da correggere in una versione in linguaggio assembly. Anche se pensi di aver risolto tutti i bug, una volta che il tuo programma passa ai bug pubblici che non avresti mai pensato che potesse accadere diventerà una realtà per te. È una vera rivelazione (e un'esperienza umiliante).

E anche se sei felice di accettarlo, potresti ancora scoprire che non c'è assolutamente alcun miglioramento misurabile delle prestazioni poiché il tuo collo di bottiglia principale potrebbe essere completamente diverso nel tuo programma. Questo mi riporta al numero 1 di nuovo. Non farlo.


15

Di solito, l'ottimizzazione solida non dipende dall'uso di Assembly o dall'esecuzione di microottimizzazioni con codice in linguaggi di livello superiore. Se leggi molti articoli di ricerca (come faccio io - o provi a farlo!), Vedrai che spesso i miglioramenti apportati agli algoritmi sono a un più ampio livello concettuale, "qualitativo", piuttosto che più "quantitativo" livello di micro-ottimizzazione. Sottolineo che è più probabile che si ottengano guadagni dell'ordine di grandezza osservando gli algoritmi da questo punto di vista o vettorializzando / parallelizzando le soluzioni esistenti.

Detto questo, di recente mi sono imbattuto in questo , che potrebbe essere una buona strada verso l'apprendimento dell'ASM x86 appositamente per gli sviluppatori di giochi.


ADDENDUM

Due fonti dalla parte superiore della mia testa:

Inoltre, la lettura di articoli di ricerca è un modo eccellente per seguire i processi di pensiero dei saggi in quanto ottimizzano gli algoritmi per prestazioni migliori. Molto spesso, i guadagni sono visti da:

  • Riduzione dell'uso delle operazioni più costose (div, SQRT, trig op e condizionali, principalmente);
  • Miglioramento delle prestazioni della cache mediante l'uso di strutture dati più efficienti, allineamento della memoria e condizioni ridotte;
  • Ridurre la qualità della produzione in aree accettabili per migliorare le prestazioni;
  • Vettorializzazione (SIMD);
  • Parallelizzazione (threading, include lo spostamento delle attività verso la GPU);
  • E naturalmente (sempre più raramente) assemblaggio codificato a mano. Innanzitutto ispezionare gli assembly C / C ++ per vedere dove il compilatore sta facendo scelte non ottimali, ovviamente. Troverai di più su questo negli articoli più vecchi degli anni '80 e '90, l'IME.

Leggere la ricerca ti tiene anche all'avanguardia nel tuo campo, invece di aspettare che queste conoscenze filtrino nel settore.


parli dell'ottimizzazione dell'algoritmo ma non ci fornisci alcuna informazione, se dovessimo seguire i tuoi consigli e guardarli invece potresti dare qualche direzione?
Skeith,

In effetti, lo menziono; devi studiare algoritmi, capire cosa fanno gli informatici per migliorare qualitativamente le prestazioni. Immergiti in questo abbastanza, e col tempo, inizi a pensare in termini simili. Gli sforzi incrementali qui ripagano alla grande, al contrario di passare anni (e di recente ho visto questo citato in un forum ASM) padroneggiare i dettagli di (solo) ad es. architettura x86. Dai la caccia al grande gioco: impara a risolvere i problemi fino in fondo, quindi decidi cosa è superfluo per ottimizzare. Vedi i libri di riferimento sopra.
Ingegnere

@NickWiggill Qual è la tua solita fonte di articoli di ricerca?
kizzx2,

3

Penso che potrebbe essere troppo presto.

In ogni caso, è importante capire che il compilatore stesso non produce un codice più lento rispetto all'equivalente dell'assembly, non si ottiene alcuna prestazione semplicemente scrivendo lo stesso codice dell'assembly del compilatore.

Per cominciare, concentrati almeno sulle ottimizzazioni senza assemblaggio. Igor Ostrovsky ha alcuni buoni articoli che dimostrano alcune delle basi: http://igoro.com/archive/fast-and-slow-if-statements-branch-prediction-in-modern-processors/

Si noti che le cattive previsioni della filiale e le mancate cache sono ciò che dovresti principalmente ottimizzare, anche se devi pagare facendo alcune operazioni aritmetiche extra, di solito vale la pena evitare un ramo imprevedibile o leggere in modo casuale da troppa memoria.

E, soprattutto, ottimizza prima il tuo algoritmo. Un'implementazione lenta di un algoritmo veloce sarà quasi sempre più rapida di un'implementazione rapida di un algoritmo lento.


2

Questo libro è eccezionalmente buono per un libro di testo. Ma non è specificamente orientato all'ottimizzazione. Linguaggio di assemblaggio per processori x86, 6a edizione

Si tratta più di insegnare i fondamenti dell'assemblaggio, usando MASM. Quindi verso la fine del libro viene illustrato come incorporare assembly in c ++ e integrarlo in programmi più grandi.

L'ho messo qui perché ha senso imparare i fondamenti dell'assemblaggio prima di imparare come ottimizzare i programmi con esso.

Mi piace questo libro perché Irvine ti insegna come usare gli strumenti necessari per scrivere programmi masm. In particolare, spiega come utilizzare l'IDE (Visual Studio C ++) e il debugger. Ogni capitolo ha alcuni video dedicati alla risoluzione dei problemi. Alcune di queste informazioni sono disponibili gratuitamente sul sito Web elencato.


1
"ha senso imparare i fondamenti dell'assemblaggio prima di imparare come ottimizzare i programmi con esso" - un buon consiglio.
Maximus Minimus,
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.