Po przeczytaniu tych dwóch pytań widzę, że zrozumienie zachowania pamięci podręcznej procesora może być ważne, gdy mamy do czynienia z dużą ilością danych w pamięci. Chciałbym zrozumieć sposób działania buforowania, aby dodać kolejne narzędzie do mojego zestawu narzędzi optymalizacji.
Jakie są podstawowe punkty dotyczące sposobu działania pamięci podręcznej procesora, aby móc rozsądnie pisać kod, który z niego korzysta? Czy istnieje sposób na profilowanie kodu, aby sprawdzić, czy słabe użycie pamięci podręcznej spowalnia działanie?
c
optimization
caching
Timothy Jones
źródło
źródło
Odpowiedzi:
źródło
Skomplikowanie tej kwestii jest obecnie poza ludzkim zrozumieniem. (Tak było od ostatnich 5 lat.) Połącz to z równoległością krótkich wektorów (SIMD) i masz poczucie beznadziejności, że ręczna optymalizacja kodu nie jest już ekonomicznie wykonalna - nie, że nie jest to możliwe, ale byłoby nie są już opłacalne.
Obecne podejście polega na uczeniu komputerów, jak optymalizować - poprzez wprowadzanie odmian kodu, które obliczają te same odpowiedzi w różnych strukturach (pętle, struktura danych, algorytmy) i automatyczną ocenę wydajności. Reguły transformacji kodu są określone za pomocą bardzo rygorystycznego modelu matematycznego, dzięki czemu jest to coś, co obaj informatycy mogą zrozumieć, a komputery mogą wykonać.
Poniżej znajduje się link opublikowany przez Larry'ego OBriena w jednej z jego odpowiedzi .
http://onward-conference.org/2011/images/Pueschel_2011_AutomaticPerformanceProgramming_Onward11.pdf
źródło
Całkiem możliwe jest zrozumienie i optymalizacja pamięci podręcznych. Zaczyna się od zrozumienia sprzętu i kontynuuje kontrolę nad systemem. Im mniej masz kontroli nad systemem, tym mniejsze prawdopodobieństwo, że odniesiesz sukces. Linux lub Windows z uruchomionymi pakietami aplikacji / wątków, które nie pracują na biegu jałowym.
Większość pamięci podręcznych jest nieco podobnych pod względem właściwości. Użyj części pola adresu do wyszukiwania trafień, mają głębokość (sposoby) i szerokość (linia pamięci podręcznej). Niektóre mają bufory zapisu, niektóre można skonfigurować tak, aby zapisywały lub omijały pamięć podręczną zapisów itp.
Musisz być bardzo świadomy wszystkich transakcji pamięciowych, które dochodzą do tej pamięci podręcznej (niektóre systemy mają niezależne pamięci podręczne instrukcji i danych, co ułatwia zadanie).
Możesz łatwo uczynić pamięć podręczną bezużyteczną, nie starannie zarządzając pamięcią. Na przykład, jeśli masz wiele bloków danych, które przetwarzasz, mając nadzieję na zachowanie ich w pamięci podręcznej, ale są one w pamięci pod adresami, które są nawet wielokrotnościami względem sprawdzania trafień / braków w pamięci podręcznej, powiedzmy 0x10000 0x20000 0x30000, a masz więcej te niż sposoby w pamięci podręcznej mogą bardzo szybko spowodować, że coś będzie działało dość wolno przy włączonej pamięci podręcznej, wolniej niż przy wyłączonej pamięci podręcznej. Ale zmień to na być może 0x10000, 0x21000, 0x32000 i to może wystarczyć, aby w pełni wykorzystać pamięć podręczną, zmniejszając eksmisje.
Podsumowując, kluczem do optymalizacji pod kątem pamięci podręcznej (cóż, oprócz znajomości systemu całkiem dobrze) jest utrzymanie wszystkich rzeczy, dla których potrzebujesz wydajności w pamięci podręcznej w tym samym czasie, uporządkowanie tych danych w taki sposób, aby możliwe było posiadanie wszystko w pamięci podręcznej naraz. I zapobieganie eksmisji znacznych części tych danych, których używasz, takich jak wykonywanie kodu, przerwania i inne regularne lub losowe zdarzenia.
To samo dotyczy kodu. Jest to jednak trochę trudniejsze, ponieważ musisz kontrolować lokalizacje, w których żyje kod, aby uniknąć kolizji z innym kodem, który chcesz przechowywać w pamięci podręcznej. Podczas testowania / profilowania dowolnego kodu, który przechodzi przez pamięć podręczną, dodając tu i tam jeden wiersz kodu lub nawet pojedynczy nop, wszystko, co przesuwa lub zmienia adresy, w których kod znajduje się z jednej kompilacji na drugą dla tego samego kodu, zmienia się, gdy wiersze pamięci podręcznej mieszczą się w tym kodzie i zmieniają to, co zostanie eksmitowane, a co nie w przypadku sekcji krytycznych.
źródło
Odpowiedzi zarówno Nwonga, jak i Michaela Borgwardta dają dobrą radę.
Najpierw zaufaj optymalizacjom kompilatora dotyczącym tych problemów.
Jeśli używasz najnowszego kompilatora GCC, możesz użyć (z parsimony) jego
__builtin_prefetch
funkcji. Zobacz tę odpowiedź na stackoverflow.źródło