Un giorno scrivevo molto assemblatore. Non solo i compilatori sono migliorati, ma la maggior parte dell'hardware ora ha molta logica dedicata all'esecuzione fuori codice del codice. Il vero micro-problema è la pianificazione, la maggior parte delle istruzioni del computer richiedono diversi clock di macchina per produrre un risultato e un carico di memoria che manca la cache può richiedere diverse centinaia! Quindi l'idea era di programmare altre istruzioni per fare qualcosa di utile, invece di aspettare un risultato. E le macchine moderne possono emettere diverse istruzioni per periodo di clock. Una volta che abbiamo iniziato a ottenere un'esecuzione fuori servizio HW, ho scoperto che cercare di ottenere grandi prestazioni con la codifica manuale è diventato un gioco di tazze. Innanzitutto l'HW non funzionante non eseguirà le istruzioni nel tuo ordine accuratamente realizzato, la nuova e stravagante architettura HW ha ridotto la penalità della pianificazione del software non ottimale abbastanza da consentire al compilatore di raggiungere una percentuale inferiore alle prestazioni. Ho anche scoperto che i compilatori stavano implementando trucchi noti ma che generavano complessità, come srotolare, caricare in basso, pipeline di software ecc. La linea di fondo, devi lavorare davvero molto, saltare alcuni di questi trucchi e il compilatore ti batte. Usali tutti e il numero di istruzioni dell'assemblatore necessarie aumenta di alcune volte!
Probabilmente ancora più importante, la maggior parte dei problemi di prestazioni, non riguarda le percentuali di emissione delle istruzioni, ma l'inserimento dei dati nella CPU. Come accennato in precedenza, la latenza della memoria è ora di centinaia di cicli e la CPU può eseguire diverse istruzioni per periodo di clock, quindi a meno che il programma, e in particolare le strutture di dati, siano progettati in modo tale che la frequenza di hit della cache sia eccessivamente elevata, microtuning su istruzione il livello non avrà alcun profitto. Proprio come i tipi militari dicono che i dilettanti parlano di tattiche, i professionisti parlano di logistica. La programmazione delle prestazioni è ora oltre il 90% della logistica (spostamento dei dati). E questo è difficile da quantificare, poiché la moderna gestione della memoria ha generalmente più livelli di cache e le pagine di memoria virtuale sono gestite da un'unità hardware chiamata TLB. Anche l'allineamento di indirizzi di basso livello diventa importante, poiché i trasferimenti di dati effettivi non sono in unità di byte, o anche 64 bit long-long, ma sono disponibili in unità di linee cache. Quindi la maggior parte delle macchine moderne ha hardware che tenta di prevedere quali mancano le linee della cache di cui potresti aver bisogno in un prossimo futuro ed emette prefetch automatici per metterli nella cache. Quindi la realtà è che con le moderne CPU i modelli di prestazioni sono così complessi da essere quasi incomprensibili. Anche i simulatori hardware dettagliati non possono mai eguagliare la logica esatta dei chip, quindi la messa a punto esatta è semplicemente impossibile.
C'è ancora posto per un po 'di codifica manuale. Le librerie matematiche (come ad esempio la funzione exp), così come le più importanti operazioni di algebra lineare (come la moltiplicazione della matrice) sono ancora generalmente codificate a mano da esperti che lavorano per il fornitore dell'hardware (cioè Intel o AMD o IBM), ma probabilmente solo bisogno di un paio di programmatori di assemblaggio di alto livello per mega-computer corp.