812 lines
No EOL
39 KiB
TeX
812 lines
No EOL
39 KiB
TeX
|
|
\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}
|
|
\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.
|
|
|
|
\newpage % Für's Layout
|
|
|
|
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[zeitliche Lokalität] Die Zugriffe (auf nahe beieinanderliegende 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) \\
|
|
& Miss-Rate $\rightarrow 0$ \\
|
|
& Hit-Rate $\rightarrow$ systembedingtes Maximum \\
|
|
& \qquad (realistisch)
|
|
\end{tabular}
|
|
\end{paracol}
|
|
|
|
Das systembedingte 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 nach einer gewissen Betriebszeit (nahezu) voll. 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.
|
|
|
|
Die \acs{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}}
|
|
|
|
Schreibzugriff 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 \acs{HS}-Geschwindigkeit möglich
|
|
\end{itemize}
|
|
\end{paracol}
|
|
|
|
\hspace*{-5mm}
|
|
\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 ist, 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 sind
|
|
\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$ \acfp{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} \index{Cache!Vollassoziativ}
|
|
Jede \acl{HSS} kann in jeder \acl{CL} eingelagert werden (nicht gleichzeitig!)
|
|
|
|
\begin{itemize}
|
|
\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 gekü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}
|
|
\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 \acs{HW}-Aufwand
|
|
|
|
$\Rightarrow$ 3 \acs{GLZ} Zeitaufwand
|
|
\end{itemize}
|
|
|
|
\subsection{Direct-Mapped Cache}\index{Cache!Direct-Mapped}
|
|
|
|
\begin{wrapfigure}[8]{r}[15mm]{78mm}
|
|
\centering
|
|
\vspace*{-15mm}
|
|
\begin{tikzpicture}
|
|
\draw (0.5, 0) rectangle ++(2,1);
|
|
\node at (1.5, 0.5) (Tag) {Tag};
|
|
\draw [decorate,decoration={brace,amplitude=6pt,raise=4pt},yshift=0pt]
|
|
(0.5,1) -- (4,1) node [black,midway,yshift=0.7cm,font=\footnotesize] {
|
|
Nummer der \acs{HSS}};
|
|
|
|
\draw (2.5, 0) rectangle ++(1.5,1);
|
|
\node at (3.25, 0.5) (mBit) {$m$-Bit};
|
|
\draw[->,very thick] (3.25,0) -- ++(0,-1.5);
|
|
\node[font=\footnotesize,align=center] at (3.25, -2) (mBesc) {Nummer der\\ \acs{CL} im \acs{DMC}};
|
|
|
|
\draw (4, 0) rectangle ++(1.5,1);
|
|
\node at (4.75, 0.5) (kBit) {$k$-Bit};
|
|
\draw[->,very thick] (4.75,0) -- ++(0,-0.6);
|
|
\node[font=\footnotesize,align=center] at (4.75, -1.1) (kBesch) {Position innerhalb\\einer \acs{HSS}};
|
|
\end{tikzpicture}
|
|
\caption{Direct-Mapped-Cache-Line}
|
|
\label{fig:direct_mapped_cache_line}
|
|
\end{wrapfigure}
|
|
|
|
Beim \acf{DMC} gibt es für jede \acs{HSS} nur/genau eine \acs{CL}, in welche diese \acs{HSS} eingelagert werden kann. \newline
|
|
$\Rightarrow$ es ist nur ein Komparator nötig
|
|
|
|
Es ist eine Hash-Funktion notwendig, welche die gekürzte \acs{HSA} auf die \acs{CL}-Nummer abbildet. Die einfachste Hash-Funktion ist \enquote{Modulo} (Rest einer Ganzzahldivision).
|
|
|
|
Modulo ist besonders einfach, falls der Divisor eine Zweierpotenz (\zB $2^m$) an Bits ist, denn dann stellen die niederwertigsten $m$ Bit den gesuchten Rest dar! Nachteil ist, dass dadurch nur Zweierpotenzen an \acsp{CL} möglich sind.
|
|
|
|
Viele Paare von \acs{HSS} können nicht gleichzeitig im Cache gehalten werden (bei gleichem Ergebnis der Hash-Funktion). Eine mögliche Problemlösung: Ausweichfunktion (wird aus Zeitgründen beim Cache nicht verwendet).
|
|
|
|
\textbf{Abhilfe}: \acf{nWAC}
|
|
|
|
\subsection{$n$-Wege-Assoziativ-Cache} \index{Cache!$n$-Wege-Assoziativ-Cache}
|
|
Für jede \acs{HSS} gibt es genau $n$ \acl{CL}, in welche die \acs{HSS} eingelagert werden kann.
|
|
Realisierung über $n$ \acs{DMC}, welche alle jeweils gleich aufgebaut sind.
|
|
|
|
|
|
\subsection{Kollision}
|
|
Falls beim Einlagern einer \acl{HSS} in den Cache bereits alle für diese \acs{HSS} in Frage kommenden \aclp{CL} belegt sind, handelt es sich um eine Kollision.
|
|
|
|
Eine Kollision kann frühestens auftreten:
|
|
\begin{itemize}[noitemsep]
|
|
\item beim \acs{VAC}: bei vollem (heißen) Cache
|
|
\item beim \acs{DMC}: beim zweiten Zugriff
|
|
\item beim $n$-Wege-\acs{AC}: beim $(n+1)$-ten Zugriff
|
|
\end{itemize}
|
|
|
|
Wie groß ist die Kollisionswahrscheinlichkeit?
|
|
|
|
\begin{tabular}{c@{}llccl}
|
|
\textbullet~ & \acs{DMC}: & $p_\text{Kollision beim 2. Zugriff}$ & $=$ & $\frac{1}{\text{Anzahl \acs{CL}}}$ & $=\frac{1}{2^m}$ \\[1.5ex]
|
|
\textbullet~ & $n$-Wege-\acs{AC}: & $p_\text{Kollision beim n+1 Zugriff}$ & $=$ & $(\frac{1}{2^m})^n$ & $=(\frac{1}{2^{mn}})$
|
|
\end{tabular}
|
|
|
|
\bigskip
|
|
Beispiel: Vergleich \acs{DMC} mit 2-Wege-\acs{AC}
|
|
|
|
\begin{tabular}{c@{}l@{}ll}
|
|
\textbullet~ & \acs{DMC}: & Anzahl \acs{CL} $= 16 \Rightarrow m=4: p_\text{Kollision 2. Zugriff}$ & $=\frac{1}{2^4}=0,0625=6,25\%$ \\[1.5ex]
|
|
\textbullet~ & 2-Wege-\acs{AC}:~ & Anzahl \acs{CL} je 8~ $\Rightarrow m=3: p_\text{Kollision 2. Zugriff}$ & $=\frac{1}{2^{3\cdot 2}}=\frac{1}{2^6}=1,5625$
|
|
\end{tabular}
|
|
|
|
\subsection{Verdrängung} \index{Cache!Verdrängung}
|
|
Wenn eine \acs{HSS} in den Cache eingelagert werden soll, muss eine andere aus dem Cache entfernt werden. Eine Kollision ist Voraussetzung für Verdrängung. Mit einer Verdrängungsstrategie wird darüber entschieden, welche der möglichen \acs{HSS} verdrängt wird. In \autoref{sec:verdraengungsstrategie} wird auf die Verdrängungsstrategie eingegangen.
|
|
|
|
\begin{Hinweis}
|
|
Eine Verdrängungsstrategie ist nur notwendig beim \acs{VAC} und beim $n$-Wege-\acs{AC}. Beim \acs{DMC} braucht man \textit{keine} Verdrängungsstrategie!
|
|
\end{Hinweis}
|
|
|
|
\subsection{Adressrechnen mit Cache}
|
|
|
|
\columnratio{0.6}
|
|
\begin{paracol}{2}
|
|
\begin{tabular}{c@{}ll}
|
|
\textbullet~ & 2-Wege-\acs{AC}: & $n=2$ \\[1ex]
|
|
\textbullet~ & 2 \acs{DMC} mit jeweils 8 \acs{CL}: & $m=3$ \\[1ex]
|
|
\textbullet~ & jede \acs{CL} beinhaltet 16 Worte: & $k=4$ \\[1ex]
|
|
\textbullet~ & \acs{HS} beinhaltet $4096$ \acs{HSA}: & $2^{12}$ Speicherwerte
|
|
\end{tabular}
|
|
\switchcolumn
|
|
Der Tag ist $12-4-3=5$ Bit groß, siehe \autoref{fig:5_Bit_Tag}.
|
|
\end{paracol}
|
|
|
|
\bigskip
|
|
\begin{Hinweis}
|
|
Die Größe eines Speicherwertes in Bit wird nicht definiert und ist auch unerheblich für die folgenden Überlegungen
|
|
\end{Hinweis}
|
|
|
|
\begin{figure}[!ht]
|
|
\centering
|
|
\begin{tikzpicture}
|
|
\draw (-0.5, 0) rectangle ++(3.5,1.5);
|
|
\node[align=center] at (1.25, 0.75) (Tag) {$12-m-k$ \\$=5$ Bit Tag};
|
|
\draw [decorate,decoration={brace,amplitude=6pt,raise=4pt},yshift=0pt]
|
|
(-0.5,1.5) -- (9,1.5) node [black,midway,yshift=0.7cm] {\acs{HSA} - 12 Bit};
|
|
|
|
\draw (3, 0) rectangle ++(3,1.5);
|
|
\node[align=center] at (4.5, 0.75) (mBit) {$m$ (3) Bit\\\acs{CL}-Nummer};
|
|
|
|
\draw (6, 0) rectangle ++(3,1.5);
|
|
\node[align=center] at (7.5, 0.75) (kBit) {$k$ (4) Bit\\ Pos. in \acs{CL}};
|
|
\end{tikzpicture}
|
|
\caption{Cache-Line mit $5$-Bit Tag}
|
|
\label{fig:5_Bit_Tag}
|
|
\end{figure}
|
|
|
|
\autoref{fig:adressrechnen} zeigt Cache A (links) und Cache B (rechts), mit denen im folgenden gerechnet wird. Die angefragten \aclp{HSA} müssen auf 12-Bit erweitert werden, denn hier ist eine \acl{HSA} 12-Bit groß, wie in \autoref{fig:5_Bit_Tag} zu sehen ist.
|
|
|
|
\begin{figure}[!h]
|
|
\centering
|
|
\hspace*{-2cm}
|
|
\includegraphics[width=\textwidth+4cm]{./Bilder/Adressrechnen.png}
|
|
\caption{2-Wege-\acs{AC} - Beispiel für Adressrechnen}
|
|
\label{fig:adressrechnen}
|
|
\end{figure}
|
|
|
|
\columnratio{0.5}
|
|
\begin{paracol}{2}
|
|
\textbf{angefragte \acs{HSA}}: $42_{10}=101010_2$
|
|
\begin{center}
|
|
$\underbrace{0~0~0~0~0}_\text{Tag}\underbrace{~0~~~1~~~0~}_{\text{\acs{CL}-Nr (2)}}\underbrace{~1~~~~0~~~~1~~~~0~}_{\text{Pos. in \acs{CL} (10)}}$
|
|
\end{center}
|
|
|
|
Cache A \acs{CL}-Nr. 2 ist nicht valide
|
|
|
|
Cache B \acs{CL}-Nr. 2 ist nicht valide
|
|
|
|
$\Rightarrow$ ein Miss
|
|
|
|
$\Rightarrow$ Einlagern der \acs{HSS} (von \acs{HSA} 32 bis 47) \newline
|
|
\phantom{$\Rightarrow$} in \acs{CL}-Nr. 2
|
|
|
|
\switchcolumn
|
|
\textbf{angefragte \acs{HSA}}: $0815_{10}=1100101111_2$
|
|
\begin{center}
|
|
$\underbrace{0~0~1~1~0}_\text{Tag}\underbrace{~0~~1~~0~}_\text{\acs{CL}-Nr. (2)}\underbrace{~1~~~1~~~1~~~1~}_\text{Pos. in \acs{CL} (15)}$
|
|
\end{center}
|
|
|
|
Cache-A \acs{CL}-Nr. 2 ist valide, aber falscher Tag.
|
|
|
|
Cache-B \acs{CL}-Nr. 2 ist nicht valide.
|
|
|
|
$\Rightarrow$ insgesamt ein Miss
|
|
|
|
$\Rightarrow$ Einlagern der \acs{HSS} (von \acs{HSA} 800 bis 815) \newline
|
|
\phantom{$\Rightarrow$} in \acs{CL}-Nr. 2 in Cache B \newline
|
|
\phantom{$\Rightarrow$} (Cache A nicht möglich)
|
|
\end{paracol}
|
|
\bigskip
|
|
|
|
\columnratio{0.5}
|
|
\begin{paracol}{2}
|
|
\textbf{angefragte \acs{HSA}}: $0271_{10}$
|
|
|
|
\begin{center}
|
|
$\underbrace{~0~0~0~1~0~}_\text{Tag}\underbrace{~0~~~0~~~0~}_\text{\acs{CL}-Nr. 0}\underbrace{~1~1~1~1~}_\text{Pos. in \acs{CL} (15)}$
|
|
\end{center}
|
|
|
|
Cache A \acs{CL}-Nr. 0 ist nicht valide
|
|
|
|
Cache B \acs{CL}-Nr. 0 ist nicht valide
|
|
|
|
$\Rightarrow$ Miss
|
|
|
|
$\Rightarrow$ Einlagen der \acs{HSS} von (\acs{HSA} 256 bis 271) \newline
|
|
\phantom{$\Rightarrow$} in \acs{CL}-Nr. 0
|
|
\switchcolumn
|
|
\textbf{angefragte \acs{HSA}}: $37_{10}$
|
|
|
|
\begin{center}
|
|
$\underbrace{~0~0~0~0~0~}_\text{Tag}\underbrace{~0~~~1~~~0~}_\text{\acs{CL}-Nr. 2}\underbrace{~0~1~0~1~}_\text{Pos. in \acs{CL} (5)}$
|
|
\end{center}
|
|
|
|
\acs{CL}-Nr. 2 in Cache A ist valide, der Tag stimmt überein, also
|
|
|
|
$\Rightarrow$ Hit in Cache A \acs{CL}-Nr. 2
|
|
\end{paracol}
|
|
|
|
\columnratio{0.5}
|
|
\begin{paracol}{2}
|
|
\textbf{angefragte \acs{HSA}}: $0675_{10}$
|
|
\begin{center}
|
|
$\underbrace{~0~0~1~0~1~}_\text{Tag}\underbrace{~0~~~1~~~0~}_\text{\acs{CL}-Nr. 2}\underbrace{~0~0~1~1~}_\text{Pos. in \acs{CL} (3)}$
|
|
\end{center}
|
|
Tag in \acs{CL}-Nr. 2 von Cache A und Cache B sind verschieden vom angefragten Tag.
|
|
|
|
$\Rightarrow$ Miss $\Rightarrow$ sogar Kollision
|
|
|
|
$\Rightarrow$ Verdrängung notwendig
|
|
\switchcolumn
|
|
\end{paracol}
|
|
|
|
|
|
\subsection{Verdrängungsstrategie} \label{sec:verdraengungsstrategie} \index{Cache!Verdrängungsstrategie}
|
|
|
|
\subsubsection{Random}
|
|
Die zu verdrängende Seite wird zufällig aus den möglichen \acs{HSS} ausgewählt.
|
|
|
|
\textit{Bewertung}:\newline
|
|
Erwartete Hit-Rate $=\frac{\text{Größe (Cache)}}{\text{Größe (\acs{HS})}}$ (bei zufällig verteilten Zugriffen, also ziemlich schlecht)
|
|
|
|
$\Rightarrow$ nur für Benchmark-Zwecke
|
|
|
|
notwendiger Aufwand: Zufallszahlengenerator
|
|
\begin{itemize}[noitemsep]
|
|
\item[$\Rightarrow$] echter Zufall ist sehr teuer \& aufwändig.
|
|
\item[$\Rightarrow$] für Benchmarks reichen (meist) Pseudozufallszahlen aus
|
|
\end{itemize}
|
|
|
|
\subsubsection{Optimale Strategie}
|
|
Es wird die \acl{HSS} verdrängt, welche in der Zukunft gar nicht mehr oder am längsten nicht mehr gebraucht wird.
|
|
|
|
\textit{Bewertung}: \newline
|
|
Erwartete Hit-Rate = \enquote{systembedingtes Maximum}
|
|
|
|
\textit{Aufwand}: \newline
|
|
\enquote{Blick in die Zukunft} bzw. \enquote{Kristallkugel} $\Rightarrow$ nicht möglich!
|
|
|
|
\textit{Realisierung für Benchmarking}: \newline
|
|
Zweimaliger Durchlauf für genau dieselben Parameter. Der erste Durchlauf für Logfile und zweiter Durchlauf mit optimaler Strategie anhand des Logfiles.
|
|
|
|
\subsubsection{First-In-First-Out (FIFO)}
|
|
Bei der \acf{FIFO}-Strategie wird die \acs{HSS}, welche sich am längsten im Cache befindet, verdrängt (klassische Warteschlangenbedienstrategie).
|
|
|
|
\textit{Aufwand}:\newline
|
|
Timestamp in jeder \acl{CL}. Bei Verdrängung: Suche nach dem Minimum der Timestamps (sehr aufwändig!).
|
|
|
|
\textit{Besser}:\newline
|
|
Verwaltung der \acsp{CL} als einfach verwaltete Liste, \dash Zeiger auf den Nachfolger in jeder \acs{CL}. Globalen Zeiger auf den ersten und letzten Eintrag für Verdrängung und Einlagerung.
|
|
|
|
\textit{Schlecht unterstützte, aber häufige Zugriffsmuster}: \newline
|
|
Ständig genutzte Datenstücke werden genauso schnell verdrängt wie Daten, die nur ein einziges Mal gebraucht werden. Anders gesagt: Daten, die lange nicht benötigt wurden, werden auch nicht schneller verdrängt, als Daten, die genauso lange im Cache sind, aber erst kürzlich gebraucht wurden.
|
|
|
|
\subsubsection{Least-Recently-Used (LRU)}
|
|
Bei der \acf{LRU} Strategie wird die \acl{HSS}, auf welche am längsten nicht zugegriffen wurde, verdrängt.
|
|
|
|
\textit{Aufwand}: \newline
|
|
Timestamp mit Update bei jedem Zugriff $\Rightarrow$ Die Suche bei Verdrängung ist zu aufwändig
|
|
|
|
\textit{Besser}:\newline
|
|
Verwaltung als \textit{doppelt} verkettete Liste, \dash Zeiger auf Vorgänger \textit{und} Nachfolger in jeder \acs{CL}. Globalen Zeiger auf ersten und letzten Eintrag.
|
|
|
|
\textit{Schlecht unterstützte Zugriffsmuster}: \newline
|
|
Häufigkeit der Zugriffe wird nicht berücksichtigt, \dash vielfach genutzte \aclp{HSS} werden genauso verdrängt wie \acs{HSS} mit nur einem Zugriff)
|
|
|
|
\subsubsection{Least-Frequently-Used (LFU)}
|
|
Bei der \acf{LFU} Strategie wird die \acl{HSS} verdrängt, welche bisher am seltensten (\enquote{am wenigsten häufig}) verwendet wurde.
|
|
|
|
\columnratio{0.35}
|
|
\begin{paracol}{2}
|
|
\textit{Aufwand (für Statusinfo):}
|
|
\begin{itemize}[noitemsep]
|
|
\item Benutzungszähler
|
|
\item Einlagerungszeit
|
|
\end{itemize}
|
|
\switchcolumn
|
|
\medskip
|
|
Häufigkeit=$\frac{\text{Zugriffe}}{\text{Zeit}}$
|
|
|
|
$\Rightarrow$ Bei Verdrängung aufwändige Berechnung und Suche
|
|
\end{paracol}
|
|
|
|
\newpage % Nur für's Layout
|
|
|
|
\textit{Problem (Zugriffsmuster)}: \newline
|
|
Neu eingelagerte Seiten werden schnell wieder verdrängt, wenn sich der Zugriffszähler am Anfang nicht schnell genug erhöht und andere etablierte Seiten eine höhere Häufigkeit aufgrund vieler \enquote{alter} Zugriffe aufweisen.
|
|
|
|
\textit{Lösungsansatz}: \newline
|
|
Zugriffe müssen \enquote{altern}, \dash alte Zugriffe werden weniger stark gewichtet als neue Zugriffe.
|
|
|
|
\textit{Mögliche Implementierung}: \newline
|
|
Mehrere Zugriffszähler in jeder \acs{CL} für die letzten $i$ Zeitscheiben.
|
|
Dividieren ist damit überflüssig (alle Zeitscheiben sind gleich lang): Addition der mit $2^j$ gewichteten Zähler als \enquote{Häufigkeit} ($j=i-1$ für jüngste Zeitscheiben, $j=0$ für älteste Zeitscheibe).
|
|
|
|
\textit{Weiterhin}: \newline
|
|
Bei der Verdrängung gibt ein Problem bei der Suche nach der niedrigsten \enquote{Häufigkeit}. \newline
|
|
$\Rightarrow$ evtl. Lösung über eine bei Beginn jedes Zeitslots neu aufzubauende verkettete Liste. \newline
|
|
\phantom{$\Rightarrow$ }Hier gibt es viel Platz für Optimierungen der \acs{CPU}-Hersteller.
|
|
|
|
\subsection{Cache bei Mehrprozessor-/Mehrkernsystemen} \index{Mehrkernprozessor}
|
|
In \autoref{fig:cpu_mehrprozessor} besitzt jeder Kern einen eigenen Cache. Möglich wäre auch ein gemeinsamer Cache. Verglichen werden diese beiden Möglichkeiten in \autoref{tbl:mehrprozessor_cache}.
|
|
|
|
\begin{figure}[!ht]
|
|
\centering
|
|
\includegraphics[width=\textwidth-3cm]{./Bilder/CPU_Mehrprozessor.png}
|
|
\caption{Mehrprozessor-/Mehrkernsystem}
|
|
\label{fig:cpu_mehrprozessor}
|
|
\end{figure}
|
|
|
|
\begin{table}[ht]
|
|
\hspace*{-5mm}
|
|
\begin{tabular}{@{}cp{7.6cm}|cp{7.6cm}}
|
|
& \textbf{gemeinsamer Cache} & & \textbf{getrennter Cache} \\ \midrule
|
|
|
|
$\oplus$ & dieselben Daten für beide Kerne benötigt bedeutet nur einmaliges Einlagern im Cache (Platzvorteil).
|
|
& $\ominus$ & Dieselben Daten müssen ggf. mehrfach in den Caches gehalten werden.
|
|
\\ [4ex]
|
|
|
|
$\ominus$ & komplexer Bus mit Zugriffsprotokoll\newline(Zeitverlust zumindest bei Zugriffskollision)
|
|
& $\oplus$ & einfache 1:1-Verbindungen (kein komplexes Zugriffsprotokoll)
|
|
\\ [2ex]
|
|
|
|
& & $\ominus$ & keine Konsistenz trotz Write-Through Strategie gewährleistet\\
|
|
\end{tabular}
|
|
\caption{Vergleich von getrennten/gemeinsamen Caches bei Mehrkernsystemen}
|
|
\label{tbl:mehrprozessor_cache}
|
|
\end{table}
|
|
|
|
Abhilfe für Inkonsistenzen bei mehreren Caches und Mehrprozessorsystemen:
|
|
|
|
\begin{itemize}[noitemsep]
|
|
\item gemeinsamer Cache (ungünstige Performance aufgrund eines Bus)
|
|
\item Snoop-Logik, \dash jeder Cache schnüffelt bei den anderen Caches bzw. beim \acs{HS}, welche Daten geschrieben wurden und invalidiert diese ggf. im eigenen Cache.
|
|
\end{itemize}
|
|
|
|
Tatsächlich haben moderne \acsp{CPU} beim L1-Cache getrennte Caches für jeden Kern und beim L3-Cache einen gemeinsamen Cache. Ob eine Snoop-Logik verwendet wird, ist davon abhängig, ob es für das Level notwendig ist oder nicht.
|
|
|
|
\section{Hauptspeicher-Organisation}
|
|
Ein \acl{HS}-Wort wird über eine \acl{HSA} (binäre, ganze, nicht negative Zahl) angesprochen.
|
|
Jedes \acl{HS}-Wort hat eine feste Wortbreite (im besten Fall gleich der \acs{CPU}-Wortbreite, also 64-Bit).
|
|
|
|
Im folgenden gehen wir von 1-Bit-Worten aus:
|
|
\begin{center}
|
|
$0\leq \text{\acs{HSA}} \leq (\text{\acs{HS}-Größe in Worten}) - 1$
|
|
\end{center}
|
|
|
|
Ein 1-Bit-Kondensatorspeicher wird in \autoref{fig:hs_kondensator} gezeigt. Für jedes \acl{HS}-Wort gibt es eine Select-Leitung. Für jedes Bit des Wortes gibt es einen Kondensator und einen Transistor. Diese werden dann parallel geschaltet.
|
|
|
|
Mehrere 1-Bit-Worte hängen an der selben Datenleitung, werden aber über unterschiedliche Select-Leitungen angesteuert.
|
|
|
|
\begin{figure}[!ht]
|
|
\centering
|
|
\includegraphics[width=\textwidth-4cm]{./Bilder/HS_Kondensator.png}
|
|
\caption{Hauptspeicher -- 1-Bit-Kondensatorspeicher}
|
|
\label{fig:hs_kondensator}
|
|
\end{figure}
|
|
|
|
Um aus der $n$-Bit-\acs{HSA} $2^n$ Select-Leitungen zu erzeugen, welche die Bits abfragen, ist ein $n:2^n$-Decoder notwendig.
|
|
|
|
In \autoref{fig:4_16_dekoder} wird ein 4:16-Decoder mit entsprechender Wertetabelle gezeigt.
|
|
|
|
\begin{figure}[!ht]
|
|
\centering
|
|
\includegraphics[width=7cm]{./Bilder/4_16_Dekoder.png}
|
|
\medskip
|
|
\begin{tabular}{cccc|cccccccccccccccc}
|
|
$a_3$ & $a_2$ & $a_1$ & $a_0$ & $s_{15}$ & $s_{14}$ & $s_{13}$ & $s_{12}$ & $s_{11}$ & $s_{10}$ & $s_{9}$ & $s_{8}$ & $s_{7}$ & $s_{6}$ & $s_{5}$ & $s_{4}$ & $s_{3}$ & $s_{2}$ & $s_{1}$ & $s_{0}$ \\ \midrule
|
|
0 & 0 & 0 & 0 & & & & & & & & & & & & & & & & 1 \\
|
|
0 & 0 & 0 & 1 & & & & & & & & & & & & & & & 1 & \\
|
|
0 & 0 & 1 & 0 & & & & & & & & & & & & & & 1 & & \\
|
|
0 & 0 & 1 & 1 & & & & & & & & & & & & & 1 & & & \\
|
|
0 & 1 & 0 & 0 & & & & & & & & & & & & 1 & & & & \\
|
|
0 & 1 & 0 & 1 & & & & & & & & & & & 1 & & & & & \\
|
|
0 & 1 & 1 & 0 & & & & & & & & & & 1 & & & & & & \\
|
|
0 & 1 & 1 & 1 & & & & & & & & & 1 & & & & & & & \\
|
|
1 & 0 & 0 & 0 & & & & & & & & 1 & & & & & & & & \\
|
|
1 & 0 & 0 & 1 & & & & & & & 1 & & & & & & & & & \\
|
|
1 & 0 & 1 & 0 & & & & & & 1 & & & & & & & & & & \\
|
|
1 & 0 & 1 & 1 & & & & & 1 & & & & & & & & & & & \\
|
|
1 & 1 & 0 & 0 & & & & 1 & & & & & & & & & & & & \\
|
|
1 & 1 & 0 & 1 & & & 1 & & & & & & & & & & & & & \\
|
|
1 & 1 & 1 & 0 & & 1 & & & & & & & & & & & & & & \\
|
|
1 & 1 & 1 & 1 & 1 & & & & & & & & & & & & & & &
|
|
\end{tabular}
|
|
\caption{Hauptspeicher -- 1-Bit-Kondensatorspeicher}
|
|
\label{fig:4_16_dekoder}
|
|
\end{figure}
|
|
|
|
Es müssen alle Minterme gebildet werden.
|
|
Die \acs{DNF} ist für jedes $s_i$ gleichzeitig die \acs{DMF} (da sie aus nur einem Minterm besteht). \newline
|
|
Somit besteht der $n:2^n$ Decoder aus genau $2^n$ Mintermen mit jeweils $n$ Literalen.
|
|
|
|
\begin{tabular}{@{}ll}
|
|
\textsf{\textbf{Zeitaufwand}}: & 1~\acs{GLZ} ($O(1)$) und damit perfekt \\ [1ex]
|
|
\textsf{\textbf{Hardwareaufwand}}: & $n\cdot 2^n$ Transistoren
|
|
\end{tabular}
|
|
|
|
\textbf{\textsf{Hardwareaufwand für Speicher und Decoder}}: \newline
|
|
Am Beispiel vom Apple \RNum{2}/C64/\ldots: 16~Bit~\acs{HSA}, 8~Bit~Worte
|
|
\begin{itemize}
|
|
\item[$\Rightarrow$] $2^{16}$ 8-Bit-Worte: 65536~Byte = 512~kBit Speicher
|
|
\item[$\Rightarrow$] für Speicher: 1 Mio. Bauelemente \newline
|
|
für $16:2^{16}$ Decoder: $16\cdot 2^{16}$ Transistoren $\approx$ 1 Mio. Transistoren
|
|
\item[$\Rightarrow$] der Decoder hat denselben Aufwand wie der Speicher!
|
|
\end{itemize}
|
|
|
|
\newpage % Nur für's Layout
|
|
|
|
\acs{PC} mit 32~Bit~\acs{CPU}:
|
|
\begin{itemize}[noitemsep]
|
|
\item[] 32~Bit = 4~Byte \acl{HS}-Wertgröße
|
|
\item[] 32~Bit-\acs{HSA}: $2^{32}$ \acs{HS}-Werte $\approx$ 4~Mrd. \acs{HS}-Werte
|
|
\end{itemize}
|
|
\bigskip
|
|
|
|
\begin{Tipp}
|
|
Intel-\acsp{CPU} adressieren nach wie vor jedes einzelne Byte und nicht \acl{HS}-Werte der Größe 4 oder 8~Byte.
|
|
\end{Tipp}
|
|
|
|
Eine Ideale 32~Bit~\acs{CPU} hätte $2^{32}$ Werte je 32~Bit:
|
|
\begin{itemize}[noitemsep]
|
|
\item[$\Rightarrow$] $2^{32}\cdot 32$~Bit $\approx$ 128~Mrd.~Bit Speicher
|
|
\item[$\Rightarrow$] 256 Mrd. Bauelemente Hardwareaufwand für \acl{HS}
|
|
\item[$\Rightarrow$] Hardwareaufwand für einen $32:2^{32}$ Decoder: $32\cdot 2^{32}$ Tr. = 128~Mrd. Transistoren.
|
|
\end{itemize}
|
|
|
|
Ideale 64~Bit~\acs{CPU} hätte $2^{64}$ Werte je 64~Bit:
|
|
\begin{itemize}[noitemsep]
|
|
\item[$\Rightarrow$] $2^{64}\cdot 64$~Bit $=2^{70}$ $\approx$ 1~Trilliarde~Bit
|
|
\item[$\Rightarrow$] 2 Trilliarden Bauelemente Hardwareaufwand für \acs{HS}.
|
|
\item[$\Rightarrow$] $64:2^{64}$ Decoder: $64\cdot 2^{64}$ Transistoren $\approx$ 1 Trilliarde Transistoren
|
|
\end{itemize}
|
|
|
|
In jedem Fall ist der Hardwareaufwand für den Decoder in derselben Größenordnung wie für den eigentlichen Hauptspeicher und damit sehr (zu) groß!
|
|
|
|
\textit{Abhilfe}: matrixförmige Speicherorganisation
|
|
|
|
\section{Matrixförmige Speicherorganisation}
|
|
Eine matrixförmige Speicherorganisation: zweidimensionale Anordnung der Speicherwerte in Zeilen und Spalten, siehe \autoref{fig:matrix_decoder} auf \autopageref{fig:matrix_decoder}.
|
|
|
|
\begin{figure}[!ht]
|
|
\centering
|
|
\includegraphics[width=\textwidth-5cm]{./Bilder/Matrix_Decoder.png}
|
|
\caption{Matrixdecoder}
|
|
\label{fig:matrix_decoder}
|
|
\end{figure}
|
|
|
|
$a_3a_2$ gibt die Zeilennummer an und $a_1a_0$ die Spaltennummer. Somit reicht es statt eines 4:16-Decoder einen 2:4 Zeilen- und einen 2:4 Spalten-Decoder zu verwenden.
|
|
|
|
\textbf{Aufwand} \newline
|
|
Anstatt eines 4:16-Decoder mit 64 Transistor, zwei 2:4-Decoder mit $2\cdot 8$ Transistoren = 16 Transistoren.
|
|
|
|
64-Bit \acs{HSA}: als $64:2^{64}$ Decoder: $2^{70}$ Transistoren \newline
|
|
als Matrix mit $2^{32}$ Zeilen und $2^{32}$ Spalten: \newline
|
|
$32:2^{32}$ Decoder mit jeweils $32\cdot 2^{32}$ Transistoren=$2^{37}$ Transistoren \newline
|
|
2 Stück: $2^{38}$ Transistoren: 256 Mrd. Transistoren
|
|
|
|
In linearer Organisation betrüge der Decoder-Aufwand das 4-Mrd.-fache! Damit ergibt sich eine große Einsparung beim Decoder-Aufwand!
|
|
|
|
\textit{Aber}: für die Realisierung des 2. Select-Eingangs wird ein weiterer Transistor je Bit benötigt \newline
|
|
$\Rightarrow$ dieselbe Größenordnung Zusatzaufwand wie Einsparung?
|
|
|
|
Statt eines Spalten-Decoders werden die Datenleitungen aller Speicherbits einer Spalte zusammengeschaltet (als jeweils eine Spalten-Datenleitung). Von diesen wird aber über einen Spalten-Multiplexer ein Spalten-Daten-Signal ausgewählt. Dies wird in \autoref{fig:matrix_multiplexer} dargestellt.
|
|
|
|
\begin{figure}[ht]
|
|
\centering
|
|
\includegraphics[width=\textwidth-4cm]{./Bilder/Matrix_Multiplexer.png}
|
|
\caption{Matrixmultiplexer}
|
|
\label{fig:matrix_multiplexer}
|
|
\end{figure}
|
|
|
|
\begin{description}
|
|
\item[$2^n:1$-MUX] Baustein, welcher aus $2^n$-Dateneingängen anhand einer $n$-stelligen Adresse eine Datenleitung auswählt und ausgibt.
|
|
\end{description}
|
|
|
|
$2^4:1$-MUX: Hat 4 Adresseingänge und $2^4=16$ Dateneingänge
|
|
|
|
\begin{figure}[!ht]
|
|
\centering
|
|
\includegraphics[width=\textwidth-2cm]{./Bilder/Schaltnetz_MUX.png}
|
|
\caption{Schaltnetz eines $4:1$-MUX}
|
|
\label{fig:schaltnetz_MUX}
|
|
\end{figure}
|
|
|
|
Realisierung über $2:4$ Decoder sowie 4 \code{UND} mit jeweils 2 Eingängen und ein \code{ODER} mit 4 Eingängen
|
|
|
|
$2^n:1$ MUX: \newline
|
|
\hspace*{5mm}ein $n:2^n$ Decoder \newline
|
|
\hspace*{5mm}$2^n$ \code{UND} mit jeweils 2 Eingängen \newline
|
|
\hspace*{5mm}ein \code{ODER} mit $2^n$ Eingängen \newline
|
|
\hspace*{5mm}Gesamtaufwand: \newline
|
|
\hspace*{5mm}$n\cdot 2^n+2\cdot 2^n+2^n$ Transistoren \newline
|
|
\hspace*{5mm}$=(n+3)\cdot 2^n$ Transistoren \newline\todo{Formatieren}
|
|
|
|
Insgesamt braucht man für einen kleinen Decoder und einem kleinen Multiplexer immer noch deutlich weniger Hardwareaufwand wie für einen großen Decoder.
|
|
|
|
Vor den Multiplexer kann ein Cache geschaltet werden, sodass eine ganze \acs{HSS} (=Matrixzeile) eingelesen werden kann.
|
|
|
|
\subsection{Gründe für Matrixorganisation}
|
|
\begin{enumerate}
|
|
\item weniger Aufwand für Adresscodecodierung
|
|
\item Einlesen einer ganzen \acs{HSS} (=Matrixzeile) in den Cache
|
|
\item zeilenweiser Refresh des \acs{HS} (wortweiser Refresh-Zyklus dauert viel zu lange)
|
|
\end{enumerate} |