W przeszłości pisałem dużo asemblerów. Nie tylko kompilatory stały się lepsze, ale większość sprzętu ma teraz dużo logiki poświęconej wykonywaniu kodu poza kolejnością. Prawdziwym mikro-problemem jest planowanie, większość instrukcji komputerowych potrzebuje kilku zegarów maszyny, aby wygenerować wynik - a obciążenie pamięci, które nie uzupełnia pamięci podręcznej, może zająć kilkaset! Pomysł polegał więc na zaplanowaniu innych instrukcji, aby zrobiły coś pożytecznego, zamiast czekać na wynik. Nowoczesne maszyny mogą wydawać kilka instrukcji na okres czasu. Kiedy zaczęliśmy dostawać sprzęt poza kolejnością, okazało się, że próba uzyskania doskonałej wydajności dzięki ręcznemu kodowaniu stała się grą kubków. Po pierwsze, HW z poza zamówieniem nie wykona instrukcji w starannie wykonanej kolejności, wymyślna nowa architektura sprzętu obniżyła karę za nieoptymalne planowanie oprogramowania na tyle, że kompilator zwykle mieścił się w granicach kilku procent wydajności. Dowiedziałem się również, że kompilatory wdrażają teraz dobrze znane, ale generujące złożoność sztuczki, takie jak rozwijanie, ładowanie od dołu, tworzenie potoków oprogramowania itp. Najważniejsze jest, aby naprawdę ciężko pracować, pomiń niektóre z tych sztuczek, a kompilator cię pokona. Skorzystaj z nich wszystkich, a liczba instrukcji asemblera, których potrzebujesz, zwiększy się kilkakrotnie!
Prawdopodobnie jeszcze ważniejsze, większość problemów z wydajnością, nie dotyczy tempa wydawania instrukcji, ale wprowadzania danych do procesora. Jak wspomniałem powyżej, opóźnienie pamięci wynosi teraz setki cykli, a procesor może wykonać kilka instrukcji na okres taktowania, więc chyba że program - a zwłaszcza struktury danych są zaprojektowane w taki sposób, że współczynnik trafień w pamięci podręcznej jest wyjątkowo wysoki, mikrotuning na polecenie poziom nie będzie miał żadnej wypłaty. Tak jak wojskowi mówią, że amatorzy mówią taktyki, profesjonaliści mówią o logistyce. Programowanie wydajności obejmuje teraz ponad 90% logistyki (przenoszenie danych). Jest to trudne do oszacowania, ponieważ nowoczesne zarządzanie pamięcią zwykle ma wiele poziomów pamięci podręcznej, a strony pamięci wirtualnej są obsługiwane przez jednostkę sprzętową zwaną TLB. Ważne jest również wyrównanie adresów na niskim poziomie, ponieważ rzeczywiste transfery danych nie są w jednostkach bajtów, lub nawet 64-bitowe długie, ale występują w jednostkach linii pamięci podręcznej. Wówczas większość nowoczesnych maszyn ma sprzęt, który próbuje przewidzieć, które linie pamięci podręcznej nie będą potrzebne w najbliższej przyszłości, i automatycznie wykona wstępne pobranie danych, aby dostać się do pamięci podręcznej. Tak więc rzeczywistość jest taka, że przy nowoczesnych procesorach modele wydajności są tak złożone, że są prawie niezrozumiałe. Nawet szczegółowe symulatory sprzętowe nigdy nie są w stanie dopasować dokładnej logiki układów, więc dokładne dostrojenie jest po prostu niemożliwe.
Wciąż jest miejsce na ręczne kodowanie. Biblioteki matematyczne (jak powiedzmy funkcję exp), podobnie jak ważniejsze operacje algebry liniowej (takie jak mnożenie macierzy) są nadal zwykle ręcznie kodowane przez ekspertów pracujących dla dostawcy sprzętu (tj. Intel, AMD lub IBM), ale prawdopodobnie tylko potrzebuję kilku najwyższej klasy programistów zajmujących się asemblerem na gigantyczną korporację.