
Cache, czyli pamięć podręczna, służy do tego, aby przechowywać tymczasowo dane dla procesora. Dostęp do pamięci, jak wiadomo, jest wolny, ale pamięć jest pojemna. Z drugiej strony, rejestry są szybkie, ale małe. Cache stara się połączyć zalety obu tych elementów, gdyż z jednej strony ma dość dużą pojemność, z drugiej jest na tyle blisko procesora, że wydajność jest zadowalająca. Oczywiście, jeśli chodzi o pojemność, to nie jest ona znowu zbyt wielka (na slajdzie jest napisane - byłaby droga, zajmowała dużo miejsca, i czas przeglądu byłby długi), jednak cała idea polega na tym, że cache przechowuje ostatnio używane dane z „dużej” pamięci, dzięki czemu ich późniejszy odczyt bądź zapis do nich odbędzie się szybciej, niż gdyby procesor musiał sięgać bezpośrednio do pamięci.
Warto zauważyć, że cache jest kompletnie przezroczyste dla procesora - procesor sięga pod dany adres pamięci i nie interesuje się tym, czy dane przyjdą z cache, czy z pamięci.
Istnieje coś takiego jak hit ratio i miss ratio. Są to współczynniki, odpowiednio, trafień w cache i chybień w cache. Trafienie w cache następuje wtedy, gdy procesor sięga po coś do pamięci, ale owo „coś” znajduje się już w cache, więc w ostateczności zostaje do procesora wysłane z cache, a nie z samej pamięci. Chybienie - wiadomo, danych nie ma w cache, więc muszą zostać pobrane z pamięci.
Działanie cache jest ładnie wytłumaczone na schemacie blokowym na slajdzie zatytułowanym Cache - kak rabotajet w kalhozie?.


Mamy trzy sposoby organizacji. Najłatwiej jest to zrozumieć według rysunków, ale postaram się je jeszcze trochę opisać:
Direct Mapping Cache - Zakładając, że mamy 10 linii w cache, to w linii 0 znajdą się elementy znajdujące się w pamięci pod adresami 0,10,20,1230, w linii 1 elementy z pamięci z adresów 1,11,21,1231 itd. Proste, łatwe i skuteczne, dodatkowo mamy zachowaną zasadę lokalności1). Problem polega na tym, że często kod aplikacji znajduje się w pamięci w zupełnie innym miejscu, niż dane. Co za tym idzie, może się zdarzyć tak, że sięgamy po kod i ładujemy go do cache. Sięgamy po dane, i nadpisujemy to, co przed chwilą władowaliśmy do cache. Potem znów sięgamy po kod, znów nadpisujemy i tak dalej. Dzieje się tak, ponieważ w jednej linii w cache może znajdować się tylko jedna linia z pamięci głównej.
Fully Associative Cache - tutaj w każdej linii cache mogą się znaleźć dane z dowolnego miejsca w pamięci. Unikamy problemu wcześniejszego, ale pojawia się problem przeszukiwania cache, które znacząco się wydłuża. Ciężej bowiem sprawdzić, czy w cache znajdują się już dane z danego adresu w pamięci, czy też nie.
Set Associative Cache - podobny sposób do Direct Mapping Cache, ale jedna „linia” w cache może przyjąć więcej niż jedną linię z pamięci (bo tak naprawdę składa się z kilku linii). Dzięki temu eliminujemy oba problemy, na które napotkaliśmy w poprzednich metodach, tzn:
x, to za chwilę najprawdopodobniej użyjemy jakiejś danej znajdującej się w pobliżu x.