Gdy procesor z pamięcią podręczną L1 dokonuje zapisu, zwykle dzieje się tak, że (zakładając, że linia pamięci podręcznej, do której pisze, jest już w pamięci podręcznej L1) pamięć podręczna (oprócz aktualizacji danych) oznacza tę linię pamięci jako brudną , i wypisze wiersz ze zaktualizowanymi danymi w późniejszym czasie.
Jedną z możliwych optymalizacji byłoby porównanie pamięci podręcznej z treścią zapisu i poprzednią zawartością pamięci podręcznej, a jeśli są takie same, nie zaznaczaj linii jako brudnej. Ponieważ może to pozwolić pamięci podręcznej na uniknięcie czasami zapisów zwrotnych, widzę, jak producent procesora może uznać to za warte bramek potrzebnych do wykonania tej logiki.
Moje pytanie: czy są procesory, które przeprowadzają tę optymalizację?
Tło, dlaczego pytam: piszę kod, który musi mieć stały dostęp do pamięci; to znaczy, ktoś, kto jest w stanie wsłuchać się w zachowanie pamięci podręcznej, nie powinien być w stanie wydedukować tego, co robię. Niektóre z moich dostępów to zapisy i w oczywisty sposób, aby wdrożyć ten kod, wiele zapisów będzie zapisywać te same dane, które już tam są. Muszę robić zapisy, ponieważ w zależności od danych dane, które piszę, mogą, ale nie muszą być takie same, i ważne jest, aby wykonać tę samą akcję niezależnie od tego. Jeśli procesor optymalizuje się, nie pisząc „zapisu bez zmian”, oznaczałoby to, że zachowanie pamięci podręcznej będzie się różnić w zależności od tego, co robię, co podważyłoby mój cel.
Czy jest więc procesor, który próbuje zoptymalizować zapis w ten sposób?
Odpowiedzi:
Po wielu godzinach poszukiwań nie byłem w stanie znaleźć procesora, który korzysta z tej konkretnej optymalizacji. Większość wspomnianych optymalizacji dotyczy zwykle trafień / braków z operacjami odczytu / zapisu i dostępu do danych:
(strony 7 i) https://cseweb.ucsd.edu/classes/fa14/cse240A-a/pdf/08/CSE240A-MBT-L15-Cache.ppt.pdf
Nie oznacza to jednak, że nie można przeprowadzić tej optymalizacji. Zasadniczo możliwy jest programowy dostęp do wielkości linii pamięci podręcznej procesora. Możliwe jest również uzyskanie dostępu do bieżących wartości w rejestrach pamięci podręcznej - ale jest to nieco niebezpieczne. Jeśli uzyskasz dostęp do niewłaściwych rejestrów w złym momencie, możesz manipulować przy rejestrach związanych z uruchomionym programem. Lub możesz przypadkowo zmodyfikować zawartość wierszy, które próbujesz odczytać.
Uzyskiwanie bieżącej wartości w pamięci podręcznej rejestru
Ponadto wszystkie teoretyczne rozwiązania wymagają pewnej formy implementacji oprogramowania (asemblera). Najbliższe, jakie znalazłem, dotyczy architektury ARM, która wydaje się pozwalać na manipulację pamięcią podręczną. Oprócz tego musisz także znać rozmiar linii pamięci podręcznej dla żądanego procesora. Możesz ostrożnie odczytać zawartość pamięci podręcznej do drugiej lokalizacji w pamięci, w przyrostach wielkości wiersza, i porównać ją z danymi, które mają zostać zapisane w rejestrach (w tym przypadku liniami pamięci podręcznej L1).
Czytaj zawartość pamięci podręcznej procesora
Stamtąd możesz opracować system oparty na oprogramowaniu, który zapobiega identycznym przepisywaniu. Chociaż jest to nieco uproszczone, dzieje się tak, ponieważ rozwiązanie musi mieć zastosowanie do każdego istniejącego procesora.
Inna możliwość, którą znalazłem, była związana ze spójnością pamięci podręcznej:
Odpowiedni fragment artykułu z Wikipedii na temat spójności
Głównym punktem, który zwrócił moją uwagę, w związku z tym problemem, był opis Snarfing:
Innymi słowy, prawdopodobnie istnieją już mechanizmy. Tyle, że mogą nie zostać użyte do optymalizacji, którą zasugerowałeś. Będziesz musiał wdrożyć oprogramowanie, które przeprowadziło porównanie odczytu / zapisu.
źródło
if (mem != x) { mem = x; }
zamiastmem = x;
. Jest to tylko czasami optymalizacja współdzielonych linii pamięci podręcznej w programie wielowątkowym, ponieważ zapis zakłóca odczyt innych wątków.Zapisywanie do pamięci podręcznej L1 jest operacją bardzo krytyczną pod względem czasu.
Zapisywanie dokładnie tych samych danych wydaje się raczej rzadkie. Optymalizacja, która przyspiesza rzeczy w tym konkretnym przypadku, nie da w sumie dużo przyspieszenia.
Z drugiej strony ta optymalizacja wymaga porównania starych danych i nowych danych przy każdym zapisie do pamięci podręcznej. Co gorsza, to fakt, że dane, które mają być zapisane, muszą być faktycznie dostępne w momencie zapisu!
Zazwyczaj tak nie jest w przypadku nowoczesnego procesora. Dane, które należy zapisać, wciąż mogą być na przykład obliczane. Pamięć podręczna może nadal działać, w razie potrzeby załadować linię pamięci podręcznej, oznaczyć linię pamięci podręcznej jako zmodyfikowaną itd., Nawet przed zakończeniem obliczeń. Wszystkie księgowanie można już wykonać, z wyjątkiem faktycznej modyfikacji linii pamięci podręcznej. Jeśli chcesz porównać nowo zapisane wyniki i stare dane linii pamięci podręcznej, nie jest to możliwe.
Na przykład, jeśli masz kod C a [i] = x / y; podział x / y zajmuje bardzo dużo czasu na większości procesorów. Jednak większość pracy potrzebnej do obsługi przechowywania wyniku w [i] miała miejsce na długo przed zakończeniem podziału; jedyne, czego brakuje, to przeniesienie ośmiu bajtów wyników do linii pamięci podręcznej. Operacja opróżnienia linii pamięci podręcznej automatycznie zaczeka na zakończenie podziału. Operacja odczytująca [i] prawdopodobnie zostanie przekierowana, aby uzyskać wynik bezpośrednio z dzielnika.
źródło
Czy taka optymalizacja nie zwiększy dwukrotnie czasu procesora potrzebnego na zapisanie czegoś w pamięci podręcznej? Ponieważ do każdego wiersza zapisu w pamięci podręcznej będzie teraz towarzyszyć operacja porównania, która nie jest wolna.
Tak więc optymalizacja będzie teraz zależeć od bardzo niejasnego czynnika: ile razy przeciętne oprogramowanie przepisuje swoją pamięć podręczną tymi samymi danymi.
źródło