2012-06-30 10 views
6

Piszę program C, w którym muszę opróżnić moją pamięć. Chciałbym wiedzieć, czy istnieje polecenie systemu UNIX do opróżnienia pamięci podręcznej procesora.Jak opróżnić pamięć podręczną procesora w systemie Linux z programu C?

Jest to wymaganie mojego projektu, które obejmuje obliczenie czasu potrzebnego do mojej logiki.

Przeczytałem o funkcji cacheflush(char *s, int a, int b), ale nie jestem pewien, czy będzie odpowiedni i co przekazać w parametrach.

+3

Dlaczego potrzeba * * opróżnić pamięć podręczną? –

+0

jest to wymóg mojego projektu, który wymaga obliczenia czasu potrzebnego do mojej logiki, dlatego muszę opróżnić pamięć podręczną. –

+0

Możliwy duplikat http://stackoverflow.com/questions/1756825/cpu-cache-flush – Tudor

Odpowiedz

6
  1. biorę go na myśli „cache procesora”, a nie pamięci podręcznej

  2. Powyższy link jest dobry: sugestia „pisać dużo danych za pomocą procesora” to nie Okna specyficzny

  3. Oto kolejna wariacja na ten sam temat:

  4. Oto artykuł o Linuksie i pamięci podręcznej procesora:

UWAGA:

Na to (bardzo, bardzo niskim) poziomie, "Linux" ! = "Unix"

+0

Dzięki za pomoc. Jest to naprawdę dobra społeczność z pomocnymi ludźmi ... możesz wyjaśnić, jak używać 'echo 3>/proc/sys/vm/drop_caches' w moim programie C z małym przykładowym kodem. –

+0

Jedną z najpiękniejszych części * nix (w szczególności dla Unixa i Linuksa) jest to, że można traktować "wszystko jak plik". W szczególności: 'fopen ("/proc/sys/vm/drop_caches "," w "); fprintf (fp, "3"); fclose (fp); '. PS: Jeśli to * jest * praca domowa, użyj tagu "praca domowa" w swoich pytaniach. – paulsm4

+0

Używam fopen ("proc/sys/vm.drop_caches", "w") .... ale jak mogę sprawdzić, czy moja pamięć podręczna została rzeczywiście wyczyszczona. @ Paulsm4 Dzięki za bycie miłym i pomoc we wcześniejszym. Mam nadzieję, że pomożesz również w tym czasie. :) –

2

Jeśli piszesz tryb użytkownika (nie w trybie jądra), a jeśli jest on jednowątkowy, to naprawdę nie ma powodu, aby kiedykolwiek zawracać sobie głowę opróżnianiem pamięci podręcznej. Twój program trybu użytkownika może po prostu zapomnieć, że on istnieje; jest po to, aby przyspieszyć wykonanie programu, a system operacyjny zarządza nim za pośrednictwem MMU procesora.

Istnieje tylko kilka powodów mogę myśleć, że może rzeczywiście chcesz opróżnić pamięć podręczną z aplikacji trybu użytkownika:

  1. Twoja aplikacja jest przeznaczona do pracy w symetrycznym układzie wieloprocesorowych lub ma transakcje danych z zewnętrznym sprzętem)
  2. Po prostu testujesz pamięć podręczną pod kątem jakiegoś testu wydajności (w takim przypadku powinieneś naprawdę powinien napisać test, aby działał w trybie jądra, być może jako sterownik).

W każdym razie, zakładając, że używasz Linuksa ...

#include <asm/cachectl.h> 

int cacheflush(char *addr, int nbytes, int cache); 

Zakłada masz blok pamięci po prostu napisał do i chcesz upewnić się, że usunięta z pamięci podręcznej z powrotem do pamięci głównej. Blok rozpoczyna się addr, a to nbytes długo, i to w jednym z dwóch skrytek (lub obu):

ICACHE Flush the instruction cache. 
    DCACHE Write back to memory and invalidate the affected valid cache lines. 
    BCACHE Same as (ICACHE|DCACHE). 

Normalnie że wystarczy przepłukać DCACHE ponieważ przy zapisywaniu danych na „MEMORY "(tj. do pamięci podręcznej), to zwykle dane, a nie instrukcje.

Jeśli chcesz opróżnić "całą pamięć podręczną" z jakiegoś dziwnego powodu testowania, możesz zrobić malloc() duży blok, o którym wiesz, że jest większy niż pamięć podręczna procesora (strzelaj, spraw, żeby była 8 razy większa!), napisz do niego wszystkie stare śmieci i spłucz cały blok.

Zobacz także: How to perform cache operations in C++?

+0

Dzięki za bycie tak pomocnym. Skąd mam wiedzieć rozmiar pamięci podręcznej procesora w ubuntu/unix/linux ... Czy chcę wyczyścić całą pamięć podręczną? –

+0

Zobacz http://superuser.com/questions/48505/how-to-find-virtual-memory -size-and-cache-size-of-a-linux-system Zobacz także moją drugą odpowiedź, która moim zdaniem jest prawdopodobnie bardziej zgodna z tym, czego szukasz ... Powiedziałbym "bardziej na wzór czego potrzebujesz ", ale myślę, że twój cel spłukiwania pamięci podręcznej do testowania wydajności jest błędny. To, co wydaje mi się bardziej sensowne w testowaniu wydajności, to testowanie wydajności kodu PO jego załadowaniu do pamięci podręcznej, przez uruchomienie go raz, aby przejść do pamięci podręcznej, a następnie użycie timera do przetestowania go może 10 000 razy i podzielenie czasu przez 10 000. – phonetagger

+0

'error: asm/cachectl.h: Brak takiego pliku lub katalogu' kompilator gnu-gcc na Linuksie zgłasza ten błąd. Każdy pomysł jak go rozwiązać ... tak, że akceptuje cachectl.h jako plik nagłówkowy. –

1

Ok, przepraszam o mojej pierwszej odpowiedzi. Później przeczytałam twoje komentarze poniżej twojego pytania, więc teraz zdaję sobie sprawę, że chcesz opróżnić INSTRUCTION CACHE, aby uruchomić swój program (lub jego części) z pamięci podręcznej, tak aby podczas testowania jego wydajności, również testowałeś początkowy czas ładowania z pamięci głównej do pamięci podręcznej instrukcji. Czy musisz również przepłukać wszelkie dane, które twój kod wykorzysta w pamięci głównej, tak aby dane i kod były świeżymi ładunkami?

Zanim cokolwiek innego, chciałbym wspomnieć, że sama pamięć główna jest również formą pamięci podręcznej, z dysku twardego (albo program na dysku, lub zamiana miejsca na dysku) jest najniższa, najwolniejszy miejsce Twojego programu instrukcje mogą pochodzić od. To powiedziawszy, kiedy pierwszy raz wykonujesz procedurę, jeśli nie została ona wcześniej wczytana do głównej pamięci z dysku, ponieważ znajduje się w pobliżu innego kodu, który już został wykonany, wtedy jego instrukcje procesora będą musiały być najpierw załadowane z dysku. To zajmuje rząd wielkości lub dłużej, niż ładowanie z pamięci głównej do pamięci podręcznej. Następnie, gdy zostanie załadowany do pamięci głównej, trwa gdzieś o rząd wielkości dłuższy, aby załadować z pamięci głównej do pamięci podręcznej, niż ładowanie z pamięci podręcznej do modułu pobierania instrukcji procesora. Jeśli więc chcesz przetestować zimny start swojego kodu, musisz zdecydować, co oznacza zimny start ... wyciągając go z dysku lub wyciągając go z pamięci głównej. Nie znam żadnego polecenia, aby "przepłukać" instrukcje/dane z pamięci głównej, aby zamienić przestrzeń, więc wypłukanie jej do głównej pamięci jest o tyle, ile możesz zrobić (o czym wiem), ale pamiętaj że twoje wyniki testu mogą się różnić od pierwszego uruchomienia (kiedy może być ściągnięcie dysku) do kolejnych serii, nawet jeśli opróżnisz pamięć podręczną instrukcji.

Teraz, jak można by przepłukać pamięć podręczną instrukcji, aby upewnić się, że ich własny kod zostanie przepuszczony do pamięci głównej?

Gdybym musiał to zrobić (bardzo dziwna rzecz do zrobienia w mojej opinii), prawdopodobnie zacznę od znalezienia długości & przybliżonego umieszczenia moich funkcji w pamięci. Ponieważ używam Linuksa, wydaję polecenie "objdump -d {myprogram}> myprogram.dump.txt", a następnie otworzę plik myprogram.dump.txt w edytorze i wyszukuję funkcje, które chcę spłukać i dowiedzieć się, ile czasu zajmuje odejmowanie adresu końcowego od adresu początkowego za pomocą kalkulatora heksadecymalnego. Zapisałbym rozmiary każdego z nich. Później dodałem wywołania cacheflush() w moim kodzie, podając adres każdej funkcji, którą chcę wypróżnić jako "addr" i długość, którą znalazłem jako "nbytes" i ICACHE. Dla bezpieczeństwa pewnie kusiłabym trochę & dodać około 10% do rozmiaru, na wypadek, gdyby zrobiłem kilka poprawek do kodu i zapomniałem dostosować nbytes. Chciałbym wywołać funkcję cacheflush() w ten sposób dla każdej funkcji, którą chcę przepłukać. Następnie, jeśli muszę przepłukać dane również, jeśli używają danych globalnych/statycznych, mogę je również przepłukać (DCACHE), ale jeśli są to dane stosu lub sterty, to naprawdę nic realistycznego, co mogę (lub powinienem zrobić), aby spłukać to z pamięci podręcznej. Próba zrobienia tego byłaby ćwiczeniem głupoty, ponieważ tworzyłby warunek, który nigdy nie byłby bardzo rzadki w normalnej realizacji. Zakładając, że używasz Linuksa ...

#include <asm/cachectl.h> 

int cacheflush(char *addr, int nbytes, int cache); 

...where cache is one of: 
    ICACHE Flush the instruction cache. 
    DCACHE Write back to memory and invalidate the affected valid cache lines. 
    BCACHE Same as (ICACHE|DCACHE). 

BTW, jest to praca domowa dla klasy?

+0

P: Ta opcja ma zastosowanie tylko w trybie jądra, prawda? – paulsm4

+0

@ paulsm4 - Strona podręcznika systemu Linux nic o tym nie mówi. Hmmm. Czytanie na stronie man ... (Zakładam, że korzystasz z Linuksa, prawda? Jeśli tak, czy wypróbowałeś polecenie "man cacheflush"?) ... w dolnej części widzę dwie rzeczy w mojej wersji strony man, które są powodem do niepokoju ... "BŁĘDY - Obecna implementacja ignoruje argumenty addr i nbytes, dlatego cała pamięć podręczna jest zawsze opróżniana." I dalej w dół ... "UWAGA - Ta funkcja systemowa jest dostępna tylko w systemach opartych na MIPS i nie powinna być używana w programach przeznaczonych do przenoszenia." – phonetagger

+1

@ paulsm4 error: asm/cachectl.h: Brak takiego pliku lub katalogu kompilator gnu-gcc na Linuksie zgłasza ten błąd. Każdy pomysł jak go rozwiązać ... tak, że akceptuje cachectl.h jako plik nagłówkowy. –

1

ten sposób Intel sugeruje spłukiwania cache:

mem_flush(const void *p, unsigned int allocation_size){ 
    const size_t cache_line = 64; 
    const char *cp = (const char *)p; 
    size_t i = 0; 

    if (p == NULL || allocation_size <= 0) 
      return; 

    for (i = 0; i < allocation_size; i += cache_line) { 
      asm volatile("clflush (%0)\n\t" 
         : 
         : "r"(&cp[i]) 
         : "memory"); 
    } 

    asm volatile("sfence\n\t" 
       : 
       : 
       : "memory"); 
} 
+0

jakie jest twoje źródło? – horro

Powiązane problemy