
\chapter{Speicher in Computern} \index{Speicher}

\section{Speicherhierarchie}
\autoref{tbl:speicherhierarchie} zeigt die Speicherhierarchie in modernen Universalrechnern

\begin{table}[ht]
	\centering
	\begin{tabular}{p{29mm}|p{36mm}|p{17mm}|p{34mm}|p{23mm}}
		Speicher                             & von-Neumann-Rechner                      & Persistenz     & Größe                                                                                       & Zugriffszeit                                                                                                          \\ \midrule
		\acs{CPU}-Register                   & Zentraleinheit (Rechen- und Steuerwerk)  & flüchtig       & $<1kB$ Byte                                                                                 & $\approx$ 200ps                                                                                                       \\ \midrule
		Cache \newline (\enquote{CPU-Cache}) & nicht vorhanden                          & flüchtig       & \circa{4}MB \newline L1$\approx$64KB \newline L2$\approx$512KB                              & $\approx$ 10ns                                                                                                        \\ \midrule
		Hauptspeicher/ Primärspeicher        & Speicherwerk                             & flüchtig       & \circa{8}GB                                                                                 & $\approx$ 100ns \newline L1 schneller                                                                                 \\ \midrule
		Sekundärspeicher                     & Peripheriegeräte an Ein- und Ausgabewerk & nicht flüchtig & HDD: 3T \newline SSD: 512GB \newline opt.~\acs{LW}: bis~100GB \newline \acs{BLW}: wenige TB & HDD~$\approx10ms$ \newline SSD~$\approx 10\mu s$\newline opt.~\acs{LW}~$\approx 1s$ \newline \acs{BLW}~$\approx 1min$
	\end{tabular}
	\caption{Speicherhierarchie und -Daten}
	\label{tbl:speicherhierarchie}
\end{table}

\section{Sekundärspeicher}
Motivation für Sekundärspeicher: nicht-flüchtig, \dash der Speicherinhalt bleibt auch bei Stromausfall erhalten.

\textbf{Anwendungen:}

\begin{itemize}[noitemsep]
	\item Programmcode (Betriebsystem, Anwendungsprogramme)
	\item Nutzdaten
	\item virtuelle Erweiterung des Speicherwerks (Swap-Datei/-Partition)
	\item Hibernation (\enquote{Ruhezustand})
\end{itemize}

\section{CPU-Cache}

Temporärer, flüchtiger, schneller Zwischenspeicher, um auf Informationen aus dem Hauptspeicher schneller zugreifen zu können.

Eigenschaften des Cache:
\begin{itemize}[noitemsep]
	\item flüchtig
	\item kleiner als das zu cachende Medium (Hauptspeicher)
	\item schneller als das zu cachende Medium (Hauptspeicher)
	\item transparent, \dash es wird nicht auf den Cache, sondern auf das zu cachende Medium logisch zugegriffen (die \acs{CPU} adressiert den Hauptspeicher und nicht den Cache)
	\item konsistent, \dash alle Instanzen derselben \acf{HSA} haben denselben Wert
	\item kohärent, \dash beim Zugriff auf eine \acs{HSA} wird immer der aktuelle Wert geliefert
\end{itemize}

\bigskip
\begin{Hinweis}[frametitle={Anmerkung: Kohärenz und Konsistenz}]
	Kohärenz ist Pflicht und Konsistenz ist Wunsch, da aus Konsistenz Kohärenz folgt. Zeitweise kann aber auf Konsistenz verzichtet werden.
\end{Hinweis}

\subsection{Lokalität des Zugriffmusters} \index{Lokalität}
Verantwortlich dafür, dass der Cache Geschwindigkeitsvorteile bringen kann.
\begin{description}
	\item[räumliche Lokalität] Wenn auf eine Adresse zugegriffen wird, wird auch auf naheliegende Adressen zugegriffen.
	\item[zeitlich Lokalität] Die Zugriffe (auf nahe beieinanderliegene Adressen) erfolgen in relativ geringem zeitlichen Aufwand
\end{description}
\medskip
\begin{Hinweis}
	Hinweis: Insbesondere die räumliche Lokalität ist beim Zugriff auf Programmcode und Nutzdaten sehr unterschiedlich (Programmcode: sequentiell, Nutzdaten zufällig innterhalb von Speicherblöcken).

	$\Rightarrow$ Moderne \acsp{CPU} weisen getrennte Caches für Programmcode und Nutzdaten auf!
\end{Hinweis}


\subsection{Begriffe}
\begin{description}
	\item[Hit]\index{Hit-Rate} Zugriff auf \acl{HS}-Daten, welcher aus dem Cache bedient werden kann
	\item[Miss]\index{Miss-Rate} Zugriff auf \acl{HS}-Daten, welcher \textit{nicht} aus dem Cache bedient werden kann und deshalb der Cache die Daten erst aus dem \acl{HS} holen muss.
	\item[Hit-Rate] Anteil der \enquote{erfolgreichen} Zugriffe an allen Zugriffen. \newline
		Hit-Rate=$\frac{\text{\#Hits}}{\text{\#Zugriffe}}$
	\item[Miss-Rate] Anteil der \enquote{nicht erfolgreichen} Zugriffe an allen Zugriffen. \newline
		Miss-Rate=$\frac{\text{\#Misses}}{\text{\#Zugriffe}}$
	\item[Zugriffe] Anzahl der Misses plus der Hits
\end{description}

\columnratio{0.5}
\begin{paracol}{2}
	\begin{tabular}{@{}ll}
		\textbf{Anwendung}: & $0\leq$ Hit-Rate $\leq 1$  \\
		                    & $0\leq$ Miss-Rate $\leq 1$ \\
		                    & Hit-Rate + Miss-Rate $= 1$
	\end{tabular}
	\switchcolumn
	\begin{tabular}{ll}
		\textbf{Ziel}: & Hit-Rate $\rightarrow 1$ (nicht realistisch)   \\
		               & Hit-Rate $\rightarrow 0$                       \\
		               & Hit-Rate $\rightarrow$ systembedingtes Maximum \\
		               & \qquad (realistisch)
	\end{tabular}
\end{paracol}


systembedingtes Maximum hängt ab von
\begin{itemize}[noitemsep]
	\item Lokalität des Zugriffsmusters
	\item Größe (und Größenverhältnis) von Cache und \acl{HS}
\end{itemize}

Hinweis: $\text{Hit-Rate}_\text{erreicht} \geq \frac{\text{Größe (Cache)}}{\text{Größe HS}}$ (Wahrscheinlichkeit, das ein beliebiger Zugriff eine bereits im Cache gespeicherte Adresse betrifft)

$\Rightarrow$ sobald das Zugriffsmuster Lokalität aufweist, ergibt sich eine bessere Hit-Rate


\subsection{Betriebszustände des Cache}
\begin{description}
	\item[kalter Cache]\index{Cache!kalter Cache} bei Betriebsbeginn ist der Cache leer
	\item[sich erwärmender Cache]\index{Cache!erwärmender Cache} Während des Betriebs wird der Cache mit immer mehr Daten geladen und die Hit-Rate steigt.
	\item[heißer Cache]\index{Cache!heißer Cache} Der Cache ist (nahezu) voll nach einer gewissen Betriebszeit. Die Hit-Rate erreicht das systembedingte Maximum.
\end{description}

\subsection{Cachearchitekturen}\index{Cache!Architektur}
\begin{figure}[!htb]
	\medskip
	\minipage{0.5\textwidth}
		\begin{tikzpicture}
			% CPU
			\draw (-3, -0.5) rectangle ++(6,1);
			\node at (0, 0) (SW) {Speicherwerk};

			\draw (-2.5, 1.5) rectangle ++(5,1);
			\node at (0, 2) (Ca) {CPU-Cache};

			\draw (-2, 3.5) rectangle ++(4,1);
			\node at (0, 4) (CPU) {Zentraleinheit (CPU)};

			\draw ($(CPU)+(0,-0.5)$) -- ($(Ca)+(0,0.5)$) ($(Ca)+(0,-0.5)$) -- ($(SW)+(0,0.5)$);
		\end{tikzpicture}
		\caption{Look-Through-Cache}
		\label{fig:cpu_cache_look_through}
	\endminipage\hfill
	\minipage{0.5\textwidth}
		\begin{tikzpicture}
			% CPU
			\draw (-2.5, -0.5) rectangle ++(5,1);
			\node at (0, 0) (SW) {Speicherwerk};

			\draw (1.5, 1.5) rectangle ++(3,1);
			\node at (3, 2) (Ca) {CPU-Cache};

			\draw (-2, 3.5) rectangle ++(4,1);
			\node at (0, 4) (CPU) {Zentraleinheit (CPU)};

			\draw ($(CPU)+(0,-0.5)$) -- ($(SW)+(0,0.5)$);
			\draw (0, 2) -- ($(Ca)+(-1.5,0)$);
		\end{tikzpicture}
		\caption{Look-Aside-Cache}
		\label{fig:cpu_cache_look_aside}
	\endminipage
\end{figure}

\columnratio{0.5}
\begin{paracol}{2}
	\textsf{\textbf{Look-Through-Cache}}\index{Cache!Look-Through}

	Wie in \autoref{fig:cpu_cache_look_through} zu sehen, ist die CPU nur mit dem Cache und der \acl{HS} ebenfalls nur mit dem Cache verbunden.

	CPU greift über den Cache auf den \acl{HS} zu:

	\begin{itemize}[leftmargin=5mm]
		\item[$\ominus$] $t_\text{Miss}=t_\text{Cache}+t_\text{HS}$ \newline
				Zugriffszeit bei Miss größer als ohne Cache
		\item[$\oplus$] optimale Konsistenz
	\end{itemize}

	\switchcolumn
	\textsf{\textbf{Look-Aside-Cache}}\index{Cache!Look-Aside}

	In  \autoref{fig:cpu_cache_look_aside} sind \acs{CPU}, Cache und \acs{HS} über einen Bus miteinander verbunden. Die Anfrage durch die CPU geht auf dem Bus an beide und ggf. antworten beide, \dash die schnellere Antwort gewinnt.

	\begin{itemize}[leftmargin=5mm]
		\item[$\oplus$] $t_\text{Miss} > t_\text{HS}$ \newline
				Zugriffszeit bei einem Miss genauso wie ohne Cache $\Rightarrow$ immer \enquote{beste} Zugriffszeit
		\item[$\ominus$] Bus braucht Zugriffsprotokoll mit Overhead $\Rightarrow$ langsamer als 1:1 Verbindung
		\item[$\ominus$] Konsistenz durch zweite Antwort potentiell gefährdet
	\end{itemize}
\end{paracol}

\subsection{Schreibstrategie}
\columnratio{0.5}
\begin{paracol}{2}
	\textsf{\textbf{Write-Back}}

	Schreibzugriff durch die \acs{CPU} findet im Cache statt und der Cache aktualisiert die Daten bei nächster Gelegenheit im \acl{HS}.
	\bigskip
	\medskip
	\begin{itemize}[leftmargin=5mm]
		\item[$\ominus$] zeitwertige Inkonsistenz der Daten
		\item[$\oplus$] Schreiben in Cache-Geschwindigkeit möglich
	\end{itemize}

	\switchcolumn
	\textsf{\textbf{Write-Through}}

	Schreibzugriffe durch die \acs{CPU} findet im \acl{HS} statt. Parallel dazu müssen die Daten im Cache invalidiert (schlecht) oder ebenfalls geschrieben werden (gut).
	\begin{itemize}[leftmargin=5mm]
		\item[$\oplus$] optimale Konsistenz der Daten
		\item[$\ominus$] Schreiben nur in  \acl{HS}-Geschwindigkeit möglich
	\end{itemize}
\end{paracol}

\begin{tabular}{p{32mm}|p{62mm}|p{62mm}}
	\textbf{Cachearchitektur} \newline \newline \textbf{Schreibstrategie}
	& \textbf{Write-Bac}k
	& \textbf{Write-Through} \\
	\midrule

	\textbf{Look-Through}
	& $\oplus$ gute klassische Kombination, da die physische Gegebenheit  vorhanden sind, um direktes Schreiben in Cache und Rückschreiben vom Cache in \acs{HS} zu ermöglichen
	& $\ominus$ Kombination nicht möglich, da kein direkter Zugriff der \acs{CPU} auf \acs{HS} physisch gegeben ist.
	\\ \midrule

	\textbf{Look-Aside}
	& $\ominus$ schlechte Kombination, da bei jedem Schreibzugriff der Bus zweimal belastet wird
	& $\oplus$ gute klassische Kombination, da Schreibzugriffe parallel im \acs{HS} und Cache physisch gut machbar
\end{tabular}

\subsection{Cache-Aufbau}

\begin{figure}[ht]
	\centering
	\includegraphics[width=\textwidth]{./Bilder/Cache_Aufbau.png}
	\caption{Aufbau des Caches}
	\label{fig:cache_aufbau}
\end{figure}

\begin{description}
	\item[\acf{HSS}] gleich große Speicheranteile des Hauptspeichers. Eine \acs{HSS} sollte $2^m$ \acs{HSA} beinhalten, um eine einfache Umrechung von \acs{HSS}-Nummern und \acs{HSA} zu ermöglichen.
	\item[\acf{CL}] Kopie einer \acl{HSS} im Cache
	\item[Tag] Die um $m$ niederwertigsten Bit gekürzte \acs{HSA}, welche der \acs{HSS}-Nummer entspricht.
	\item[Status] Zustandsinfo zur Cache-Line, \zB Valid-Flag und weiter Zustandsinfos abhängig von Verdrängungsstrategie
	\item[Valid-Flag] Die Daten werden im Cache geändert und müssen noch in den \acs{HS} zurückgeschrieben werden (nur bei Write-Back-Schreibstrategie)
\end{description}

\subsection{vollassoziativer Cache}
Jede \acl{HSS} kann in jeder \acl{CL} eingelagert werden (nicht gleichzeitig!)
\begin{itemize}[noitemsep]
	\item[$\Rightarrow$] bei jedem Zugriff auf eine \acf{HSA} muss überprüft werden, ob die gekürzte \acs{HSA} einem der Tags von validen \acl{CL} entspricht!
	\item[$\Rightarrow$] Vergleichen der gekkürzten \acs{HSA} mit allen Tags (von validen \acs{CL})
\end{itemize}

Wie kann verglichen werden? Welche Möglichkeiten des Vergleichs gibt es?

\begin{itemize}[noitemsep]
	\item sequentiell $\Rightarrow$ Nachteil: erhöhte Zugriffszeit
	\item Parallel $\Rightarrow$ gleichzeitiges Vergleichen der angelegten (gekürzten) \acs{HSA} mit allen Tags über jeweils einen eigenen Komparator in jeder \acs{CL}. \newline
		Nachteil: \acl{HW}-Aufwand für Komparator in jeder \acs{CL}.
\end{itemize}


\textsf{\textbf{Einschub: Schaltungssynthese Komparator}} \newline
Hier: Schaltnetz, welches zwei Zahlen auf Gleichheit, Größer und Kleiner vergleicht.

\begin{figure}[!ht]
	\centering
	\includegraphics[width=6cm]{./Bilder/Cache_Komparator_1.png}
	\caption{$n$-Bit-Komparator}
	\label{fig:cache_komparator_1}
\end{figure}

Möchte man eine Wertetabelle für einen $n$-Bit-Komparator erstellen, sieht man, dass zu viele Zeilen in der Wertetabelle ($2^{2n}$\ldots) sind $\Rightarrow$ besser mit kaskadierbaren 1-Bit-Komparatoren

\textsf{\textbf{Komparator für Gleichheit}} \newline
\textit{Hinweis}: im Cache reicht der Vergleich auf Gleichheit. \autoref{fig:cache_komparator_3} zeigt 1-Bit-Komparatoren für einen Gleichheits-Komparator.
\begin{figure}[!ht]
	\centering
	\includegraphics[width=9cm]{./Bilder/Aufwand_Komparator.png}
	\caption{Aufbau des Gleichheits-Komparators im Cache}
	\label{fig:cache_komparator_3}
\end{figure}

\subsubsection{Komparator}

\begin{figure}[!h]
	\centering
	\includegraphics[width=\textwidth]{./Bilder/Cache_Komparator.png}
	\caption{Aufbau des $n$-Bit-Komparator aus kaskadierbaren 1-Bit-Komparatoren}
	\label{fig:cache_komparator_2}
\end{figure}

Aus \autoref{fig:cache_komparator_2} ergibt sich folgende Tabelle:
\begin{center}
	\ttfamily
	\begin{tabular}{ccccc|ccc}
		$b_n$ & $a_n$ & $a>b_{in}$ & $a=b_{in}$ & $a<b_{in}$ & $a>b_{out}$ & $a=b_{out}$ & $a<b_{out}$ \\ \midrule
		  0   &   0   &     0      &     0      &     1      &      0      &      0      &      1      \\
		  0   &   0   &     0      &     1      &     0      &      0      &      1      &      0      \\
		  0   &   0   &     1      &     0      &     0      &      1      &      0      &      0      \\
		  0   &   1   &     x      &     x      &     x      &      1      &      0      &      0      \\
		  1   &   0   &     x      &     x      &     x      &      0      &      0      &      1      \\
		  1   &   1   &     0      &     0      &     1      &      0      &      0      &      1      \\
		  1   &   1   &     0      &     1      &     0      &      0      &      1      &      0      \\
		  1   &   1   &     1      &     0      &     0      &      1      &      0      &      1
	\end{tabular}
\end{center}

Somit ergibt sich als Schaltnetz für einen 4-Bit-Komparator die \autoref{fig:n_komparator}

\begin{figure}[!ht]
	\centering
	\includegraphics[width=8cm]{./Bilder/n-bit-Komparator.png}
	\caption{kaskadierbarer 4-Bit-Komparator}
	\label{fig:n_komparator}
\end{figure}

\acs{HW}-Aufwand für einen kaskadierbaren 1-Bit-Komparator
\begin{itemize}[noitemsep]
	\item[] HW: 42 Transistoren
	\item[] Zeit: 2\acs{GLZ}
\end{itemize}


Im Cache reicht der Vergleich auf Gleichheit aller Ziffern parallel:

\begin{itemize}[noitemsep]
	\item 2 $n$-Bit-Zahlen: $n$ Äquivalenzgatter und 1 \code{UND} mit $n$ Eingängen. (vergleiche \autoref{fig:cache_komparator_3})

		$\Rightarrow$ 7n Transistoren HW-Aufwand

		$\Rightarrow$  3\acs{GLZ} Zeitaufwand
\end{itemize}\todo{Formatieren, etc}
