2013-04-26 12 views
6

Napisz program i spróbuj porównać (zmierzyć, jeśli możesz) czas dostępu do danych z pamięci głównej i pamięci podręcznej.Jak napisać program w C, aby zmierzyć szybkość pamięci podręcznej?

Jeśli możesz to zrobić, to jak zmierzyć szybkość każdego poziomu pamięci podręcznej?

+3

Czy to możliwe? Pamięć podręczna nie jest pod Twoją kontrolą, nie masz możliwości sprawdzenia, kiedy dane są ładowane skąd. (Okej, może uda ci się prześledzić cache, ale domyślam się, że śledzenie wyników może wprowadzić w błąd wyniki.) – millimoose

+0

może użyć rejestrów i mmap? Ale wydaje się to wysoce subiektywne (poza tym istnieją inne procesy uruchomione na komputerze). Brzmi jak coś, co należy zrobić na poziomie sprzętu; w przeciwnym razie inne wątki/procesy/OS-owskie staną się przeszkodą. – cegfault

+0

O ile widzę, jeśli definiuję dużą tablicę w C, kiedy uzyskuję dostęp do elementu w tej tablicy, dane wokół tego elementu wydają się być przechowywane w Pamięć podręczna. Więc jeśli dostęp do tablicy od początku do końca będzie szybszy niż losowy dostęp (dostęp do każdego elementu raz) --- to prawda, ale nie wiem, że to wynik przez buforowanie lub coś innego. – Sayakiss

Odpowiedz

3

To zwykle wymaga pewnej wiedzy o „geometrii” pamięci podręcznej i innych aspekty tego. Pomocne może być również kontrolowanie systemu poza prostym dostępem do niego i zależnymi od implementacji elementami, takimi jak dokładniejsze synchronizowanie czasu niż w przypadku standardowego mechanizmu C clock.

Oto początkowe podejście:

  • Napisz procedurę, która przyjmuje wskaźnik do pamięci, długość i liczbę powtórzeń i czyta wszystkie tej pamięci w kolejności, wielokrotnie.
  • Napisz procedurę, która kilkakrotnie pobiera wskaźnik do pamięci, długość oraz liczbę powtórzeń i zapisów do wszystkich pamięci w kolejnej kolejności.
  • Powyższe procedury mogą wymagać przekonwertowania ich wskaźników na volatile, aby uniemożliwić optymalizatorowi dostęp poza zasięgiem, który w przeciwnym razie nie przyniesie efektu.
  • Przydziel dużą ilość pamięci.
  • Zadzwoń do każdej z powyższych procedur, uzyskując aktualny czas przed i po każdym połączeniu, a także wywołując różne długości, aby zobaczyć czasy dla różnych długości.

Kiedy to zrobisz, zobaczysz zazwyczaj dużą szybkość (liczbę bajtów do odczytu/zapisu na sekundę) dla małych długości i mniejszych prędkości dla dłuższych odcinków. Spadek prędkości nastąpi, gdy przekroczone zostaną rozmiary różnych poziomów pamięci podręcznej. Prawdopodobnie widzisz rozmiary pamięci podręcznej L1 i L2 odzwierciedlone w danych zebranych za pomocą powyższej techniki.

Oto kilka powodów, które podejście jest niewystarczające:

  • To nie kontroluje instrukcje służące do odczytu lub zapisu pamięci podręcznej. Kompilator języka C może również generować instrukcje load-word i store-word, ale wiele współczesnych procesorów ma instrukcje, które mogą ładować i przechowywać 16 bajtów na raz, a czytanie i pisanie może być szybsze w przypadku tych instrukcji niż w przypadku instrukcji czterobajtowych.
  • Pamięć podręczna będzie zachowywać się inaczej, gdy uzyskasz dostęp sekwencyjnie, niż w przypadku dostępu do niej losowo. Większość pamięci podręcznych podejmuje próbę śledzenia, kiedy dane są używane, aby ostatnio używane dane były przechowywane w pamięci podręcznej, podczas gdy inne dane są odrzucane. Części dostępu rzeczywistych programów zasadniczo różnią się od kolejnych operacji opisanych powyżej.
  • W szczególności, kolejne zapisy do pamięci mogą być w stanie wypełnić całą linię pamięci podręcznej, tak że nic nie musi być odczytywane z pamięci, podczas gdy rzeczywisty wzorzec użycia, który zapisuje tylko jedno słowo do konkretnej lokalizacji, może wymagać realizowane przez odczytanie linii pamięci podręcznej z pamięci i scalenie w zmienionych bajtach.
  • Konkurencja z innych procesów w systemie będzie zakłócać pamięć podręczną i pomiar.
5

Musisz wymyślić heurystykę wymuszającą 100% (lub bardzo bliską) pamięć podręczną (mając nadzieję, że masz kod operacji unieważniania pamięci podręcznej?) I 100% trafienie w pamięci podręcznej. Hurra, który działa na 1 poziomie pamięci podręcznej. Teraz, jak zrobić to samo dla poziomu 2 i 3?

Z całą powagą, zapewne nie jest sposobem, aby to zrobić w 100% wiarygodny bez specjalnego sprzętu i śladów podłączonych do procesora i pamięci, ale tutaj jest to, co chciałbym zrobić:

napisać „kilka” z rzeczy do 1 lokalizacji w pamięci - wystarczy, że możesz być pewny, że uderza on w pamięć podręczną L1 i nagrywać czas (co wpływa na pamięć podręczną, więc uważaj). Powinieneś zrobić ten zestaw zapisów bez gałęzi, aby spróbować pozbyć się niekonsekwencji przewidywania gałęzi. To najlepszy czas. Teraz, co jakiś czas, zapisuj dane wartości pamięci podręcznej w losowej, odległej lokalizacji w pamięci RAM na końcu swojej znanej lokalizacji i zapisz nowy czas. Mamy nadzieję, że trwa to dłużej. Rób to nagrywając różne czasy i miejmy nadzieję, że zobaczysz kilka czasów, które mają tendencję do grupowania się. Każda z tych grup "mogła" pokazywać taktowanie dla czasów synchronizacji L2, L3 i pamięci. Problem polega na tym, że wiele innych przeszkadza. System operacyjny może zmienić kontekst i zepsuć pamięć podręczną. Przerwanie może nadejść i przez twój czas wolny. Będzie dużo rzeczy, które mogą wyrzucić te wartości. Ale, miejmy nadzieję, dostaniesz wystarczająco dużo sygnału w swoich danych, aby sprawdzić, czy to działa.

Prawdopodobnie byłoby to łatwiejsze do zrobienia w prostszym, wbudowanym systemie typu, w którym system operacyjny (jeśli jest zainstalowany) nie będzie przeszkadzał.

+0

Ale jak zmierzyć czas odczytywania danych jeden raz? Jest tak krótki i może być tylko kilka ns! – Sayakiss

+0

Robiąc to wystarczająco dużo razy. Powinieneś być w stanie policzyć do milisekundy. Nadal nie powiedziałem, że to będzie łatwe :) –

+0

Ale po zrobieniu tego jeden raz, może być załadowany do pamięci podręcznej (załóżmy, że nie jest wcześniej). – Sayakiss

2

Spójrz na cachegrind-valgrind:

Cachegrind symuluje jak program współdziała z urządzenia pamięci podręcznej hierarchii i (opcjonalnie) oddział prognostyk. Symuluje on komputer z niezależnymi buforami instrukcji pierwszego poziomu i danych (I1 i D1), wspieranymi przez ujednoliconą pamięć podręczną drugiego poziomu (L2). To dokładnie odpowiada konfiguracji wielu nowoczesnych maszyn.

Zobacz tese ładne pytania są jakoś powiązane:

  1. How do I programmatically disable hardware prefetching?
  2. How would you generically detect cache line associativity from user mode code?
  3. How to invalidate cache when benchmarking?
+1

Ah, emulacja może być lepszą opcją, jeśli jakość emulacji jest wystarczająco dobra. Dobry pomysł. –

Powiązane problemy