Rechnerarchitektur Zusammenfassung

Eine schriftliche Zusammenfassung des Faches Rechnerarchitektur aus dem Wintersemester 2022/23 von Tobias Rempe im Studiengang Angewandte Informatik (PO20) der Ruhr Universität Bochum.

Turingmaschine

Aufbau

  • Hat ein unendlich langes Band
  • Hat einen Schreib- und Lesekopf
  • und das Programm was das steuert
    • Zustände
    • So wenn A passiert dann mach B und gehe in zustand C
  • In der Theorie kann man damit alles Berechenbare Berechnen

The Law's

Moore's Law

  • Besagt dass sich die Transistordichte jedes Jahr verdoppelt
  • Ja da hatte er lange recht mit nich
  • Allerdings wurden die Bestandteile dann irgendwann so klein, dass es physikalisch nicht mehr möglich war / nicht mehr sein wird alles so eng zusammen zu quetschen, weswegen morees law immer irrellevanter wird
  • THE END
  • Es wird kontinuierlich schwerer Moores law einzuhalten
    • Wir sind jetzt schon im faktor 15 hinterher
  • Zudem kommen immer mehr herausforderungen hinzu
  • Absturz ist also vorprogrammiert
    • Wir müssen also etwas tun!

Dennard Scaling

  • Besagt, dass wir trotz steigender Transistordichte einen Konstanten Energieverbrauch erwarten sollen
  • Da lag er aber leider falsch der Bre
  • ney hier ist nen krasser Graph um zu zeigen, dass der bre Falsch lag
  • Wie wir sehen haben wir die Energieeffizienz kontinuierlich gesteigert
  • Deswegen nur bis knapp 2000 anwendbar

Multicore und Amdahl's Law

  • Neue Prozessoren haben mehrere Prozessorkerne, damit arbeit paralellisiert werden kann
  • Allerdings ist hier der Performancegewinn begrezt, da nicht alle Programme paralellisiert werden können
  • Dementsprechend ist immer der Langsamste teil ausschlaggebend für die Geschwindigkeit des Programms
  • Noch nen sicker graph

In Anderen Aspekten der Prozessortechnik

  • Wir entwickeln immer mehr Flexiblere Sachen
  • Wie man z.b. auch an handys sieht, die immer effizienter und schneller werden.

Rechnersichten

Höhere Sicht eines Rechners.

  • Wenn wir uns als Programmierer einen Rechner anschauen sehen wir einen schwarzen kasten der das macht was wir von ihm wollen
  • Es gibt dementsprechend verschiedene Wege Einen Rechner zu sehen, und daher auch verschieden "genaue" Sichtweisen
  • Am besten stellen wir das mit sog. Schichtenmodellen da.
    • Diese sind der Abstraktion nach geordnet, also die "einfachste" ebene ist die ganz oben, und die technischste ganz unten

Modellierung eines RISC-Rechners

(RISC = Reduced Instruction Set Coputer)
Verschidene Ebenen und Sprachen

  • "Höhere" Programmiersprachen 99% des Marktanteils
    • C++, Java, Fortran, Rust
  • Assembler
    • Symbolische Notation der bisher vorhandenen Befehle direkt an den Computer
  • Betriebssystemebene
    • "Hintergrunddienste" wie Speicherorganisation, Dateiverwaltung etc.
  • Maschinensprache
    • Die unterste Sprache an die wir so dran kommen
    • Befehle sind folgen von 0, 1 also Stromimpulsen
  • Digitale Ebene
    • Also die Hardware Direkt

Modellierung eines CISC-Rechners

(Complex Instruction Set Computer) Bekanntester Vertreter x86 bzw. x86_64
Verschiedene Sprachen und Ebenen

  • Ein CISC Rechner bitete anstelle von "normalen" Instruktionen die in hardware Augewertet werden den sog. Mikrocode.
  • Mit diesem ist es möglich Komplexere Instruktionen wie mini-programme im Prozessor zu realisieren, sodass sie virtuell ohne kosten ausgeführt werden können und somit wie "in hardware laufen" ohne extra hardware zu konzipieren.
  • Dise Mikroprogramme sind aus direkten Instruktionen für das Steuerwerk zusammengesetzt und so vergleichbar mit einem "regulären programm", was allerdings tiefer im Prozessor aufbewahrt, und somit deutlich schneller evaluiert und ausgeführt werden kann..
  • Dadurch ist deutlich flexiberes Prozessorendesign möglich

Virtueller Rechner

  • Jede Ebene ist ein "virtueller Rechner" , zu dem eine Sprache gehört.
  • Programme der Sprache werden
    • Übersetzt in die Sprache übersetzt oder
    • In die Sprache Interpretiert
  • Die Virtuelle Maschine trollt den benutzer einfach richtig hart und tut so, als würden die Programme die er in geschrieben hat einfach direkt auf Hardware ausgeführt werden

Hirachie: Illustriert

BRE NE HIRACHIE SACHE DIE MAXIMAL DIAGRAMMATISCH IST

Übersetzung versus Interpretation

Übersetzung

  • Ein Compiler ist eine Software die einfach nen Programm was in der Sprache geschrieben wurde nimmt, da nen bissl drauf rum haut und dann ein equivalentes Programm ausspuckt welches in der sprache "geschrieben" wurde ausspuckt.
  • Wenn dann die maschinensprache, also das Binärformat ist, sprechen wir von einem -Vollcompiler

Ausführung eines -Programms

  • Wir Trainsformieren das originale Programm in ein äquivalentes -Programm
  • Dann führen wir dieses massiv krasse -Programm aus, nich?

Interpretation

  • Dat funktioniert nach einem Festen Schema, und das sieht so aus:

Abwägung

  • Interpreter sind einfacher zu Implementieren als Compiler
    • Deswegen auch oft einfacher auf andere Plattformen zu Übertragen
    • geeignet für z.b. Prototypen von Programmiersprachen
  • Compilation ist leider nicht immer möglich
  • Compilierte (Übersetzte) Programme sind aber (fast) immer schneller als interprätierte Programme
    • Es kann Codeoptimierung @ Compiletime verwendet werden
    • Und Binäranweisungen werden von hardware ausgewertet und sind dadurch radikal schneller
  • (vollständige) Compilation ist allerdings auch nicht immer erwünscht
    • Da das zu einer Systemabhängigkeit führt, und deswegen nicht einfach auf andere Systeme übertragen werden kann

Performanzmaße eines Rechners

Hierein bild mit sehr viel Performance

Rechnerorganisation: Aufbau und Funktionsweise

Kernbegriffe:

  • Hardware
    • Ja die hardware halt, dein Handy, dein PC, dein dummes Mainboard was vor 3 jahren mal nen stromschlag bekommen hat und deswegen immer weiter failed und deine smartwatch
  • Software
    • Das was die meissten Entwickler schreiben, also der kram der auf deinem Gerät läuft
  • Firmware
    • Der "kleber" der die verbindung zwischen Software und Hardware herstellt, also sowat wie das BIOS.
    • Meisstens in ROM (Read only Memory) gespeichert

Hardware VS Software

  • viel von dem was früher in Software gemacht werden musste kann heute in hardware gemacht werden
    • z.b. Ganzzahlige Multiplikation, Division, Floatingpointarithmatic
  • Allerdings gibt es auch neue Konzepte wie das oben genannte RISC-Konzept
    • Hier wird wieder mehr in Software ausgeführt
      • Damit das Instruktionsset so simpel wie möglich gehalten werden kann, um schnelle Übersetzung und Ausführung zu garantieren
    • z.b. Ganzzahlige Division

Der Kram zwischen Software und Hardware

  • Das instruktionsset (Instruction-Set)
  • Dieses Set bestimmt den befehlssatz mit dem später (wie der name schon sagt) Befehle an den Computer gesendet werden können
  • Dieses set entscheidet was in hardware direkt gelöst werden kann, und was nur in software gebaut werden kann
  • Hier ist es wichtig alles genau abzuwägen, weil es zu ineffizienzen und problemen führen kann wenn wir alles in eine richtung schieben.
  • hier ein bild von einem bre der iwie nen boden mit zwei anderen bres aufrecht erhält und auf dem boden steht instructionset

Exkurs: Hardware / Software Co-Design

  • Es gibt auch Orte an denen wir sehr spezifische goals haben und die erreichen müssen
  • z.b. Smart-Home geräte
  • Die dinger nennt man dann Embedded Devices
    • Die müssen ja am ende nicht frei programmierbar sein, deswegen können wir die hardware auf genau diese eine sache die die erledigen müssen zuschneiden
      • Sowas wurde z.b. auch bei alten videospielkonsolen gemacht
  • Was in Software und was In hardware implementiert wird muss ein sog. "Systemarchitekt" entscheiden, der dann anforderungen Stellt.
  • Die genaue Implementation wird dann (halb-) automatisch durch diverse Laufzeitanalysen erprobt und Entschieden
  • Aber insgesamt sollte alles was in software schwer ist weil es z.b. sehr rechenintensiv ist auf Hardware ausgelagert werden

Prinzipieller Aufbau eines Rechners

Hier wieder ein Extrem krasses bild was darstellt wie krass gut nen Computer aufgebaut ist

John von Neumann (1903-1957)

(es geht weiter mit Geschichte!!1!)

Der bre hat den aufbau von Modernen Rechnern sehr stark beeinflusst, u.a. weil er einfach nen krasser Mathematiker war
Das sog. von-Neumann-Prinzip was (schocker) er erfunden hat beruht auf den folgenden 4 Punkten:

  • voll-elektrischer Rechner
  • binäre Darstellung der Daten
  • Benutzung einer Arithmetischen Einheit
  • Benutzung eines Steuerwerkes
  • Interner Daten- und Programmspeicher

Falls ihr in der 1. Klasse aufgepasst habt merkt ihr, dass das da 5 Punkte sind. SUPER GEMACHT! 3 Bonus Gummi-Punkte!

Der Arbeitsspeicher (Hauptspeicher)

  • Ja in dem ding können wir sachen speichern an denen wir gerade arbeiten (ja was nen wunder nich)
  • der besteht aus (also praktisch beliebig vielen) Speicherzellen
  • Eine Speicherzelle

    • speichert immer Information bestehend aus Bit. wird dabei die Wortbreite des Speichers genannt.
      • kann 8, 16, 32, 64 oder noch viel mehr Bit groß sein
      • Allerdings arbeiten unsere Modernen rechner und geräte fast Exklusiv mit 64Bit Großen 's
    • Hat eine Adresse mit der sie identifizierbar ist.
      • Diese liegt im bereich
    • Nix kann kleiner sein als Wortbreite, also ist eine speicherzelle die kleinste adressierbare einheit des speichers

Der Prozessor (+ Cache)

Dat ding besteht in seiner Einfachsten Form aus

  • Steuerwerk (Control Unit)

    • indem das ding die richtigen Signale an die richtigen Sachen schickt bewegt sich der nächste Maschinenbefehl aus dem Hauptspeicher in eins der Arbeitsregister im Cache
    • Dann sendet der noch mehr von diesen Signalen um die gelesene Maschineninstruktion auszuwerten
    • Dann führt er diese Instruktion durch das senden weiterer Signale aus
  • Recheneinheit (Arithmethic Logic Unit - ALU, Datenpfad)

    • führt die Teilschritte (Vergleiche, Move, Addition, etc.) gemäß der Signale aus.
  • Registerbank

    • Beinhaltet die sog. Register
    • Die dinger speichern daten die der Prozessor in diesem Moment benötigt
    • Denn auf Register kann ohne Wartezyklus direkt vom Rechenwerk aus Zugegriffen werden

Register des Prozessors

  • Hier werden die sachen aufbewahrt, die schnell vom Prozessor gebraucht werden
Art der InformationSpeicherortNameAcronym
aktuell abzuarbeitender BefehlBefehlsregisterInstruction RegisterIR
Adresse des als nächstes abzuarbeitenden BefehlBefehlszählerProgram CounterPC
Adresse im RAM ab der Daten gespeichert werden könnenStackpointerStackpointerSP
von der ALU zu verarbeitende DatenArbeitsregisterGeneral Purpose RegisterGPR

Prinzipielle Arbeitsweise eines Prozessors

  • Fetch-Decode-Execute-Zyklus

    • Fetch

      • Hol dir den nächsten Maschinensprachebefehl aus dem GPR und speicher ihm im IR a. Die benötigte Adresse steht im PC
    • Decode

      • Analysiere (Decode) die daten und lade dir alle wat du gerade brauchst
    • Execute

      • Führ dat wat de dir da zusammen gesucht hast aus und speicher dat erjebnis ab (im Hauptspeicher)
    • REPEAT!

Assembler

  • Der kram ist die letzte ebene vor 1en und 0en
  • Befehle sind meist elemetare operation (also so simpel wie es geht)
  • Du hast die Register für datenmanipulation, damit du damit halt arbeiten kannst nich
  • Operanden werden durch verschiedene Adressierungsarten bestimmt
  • Wir verweisen zurück auf die Ebenenansicht
  • wir schauen uns die jetzt nochmal genauer an

Ebenensicht : The SQL

  • Höhere Programmiersprachen
    • C++, Java, Fortran, Rust, Son kram
  • Assembler
    • symbolische Notation der bisher vorhandenen Befehle
  • Betriebssystemebene
    • zusäzliche util Dienste wie Speicherorganisation, Dateiverwaltung
  • Maschinensprache
    • unterste frei zugängliche Sprache Befehle sind am ende Folgen über 0 und 1
  • Mikroprogrammebene
    • Instruktionen zum setzen von Steuersignalen
    • Hier werden die Instruktionen in Maschinensprache auseinander genommen und in die Steuersignale übersetzt
  • digitale Ebene
    • die eigentliche Hardware

Assembler Höhere Programmiersprachen

AssemblerHöhere Programmiersprachen
Zusammenhang ist oft schwer erkennbarMan kann den Code (meisstens) gut lesen und funktionen dem kontext entnehmen
Einfache BefehleKomplexe Sprachkonstrukte
Direkter Speicherzugriff und volle KontrolleKonstruktion komplexer Datentypen und limitierte Kontrolle
Maschinenabhängige ProgrammeProgramme die weitgehend unabhängig von Maschinen sind

Befehlssatz

Der Befehlssatz eines Prozessors wird beim Entwurf festgelegt

  • Kompromiss:
    • Wünsche aus Anwendersicht
    • Technische Machbarkeit
  • Von bedeutung sind dabei
    • Bitbreite zur kodierung eines Befehls
      • Also wie viel platz ein Befehl verbrauchen soll
      • und im Umkehrschluss auch wie viele Befehle verwendet werden können
    • Zusätzliche Adressierungsarten von Befehlen

Klassen von Befehlen

Da gibts janz viele, wir betrachten hierbei z.b.. sowas wie

  • Arithmetische Befehle (Rechnen-Dinger)
    • Add, Sub, Mult, Div, Srl, ...
  • Datentransportbefehle (Ja dinger zum Daten transportieren halt)
    • Load, Store, Move, Push, Pop, I/O, ...
  • Logische Befehle (Halt so dings dinger zum vergleichen)
    • And, Or, Not, ...
  • Bitverarbeitende Befehle (So zeuchs was iwas iwo rein schreibt)
    • Setzen, Rücksetzen von bits, Statusflags, ...
  • Sprungbefehle (So GEH ZU BEFEHL 210,7 BRE!!!!!)
  • Systembefehle (Ja du da fällt mir gerade kein Beispiel ein)

Exkurs: RISC-V

Wofür steht RISC-V?

  • Reduced
  • Instruction
  • Set
  • Computer
  • 5

Wat is das überhaupt

  • Eine Modulare 32/64/128-Bit RISK Architektur
    • Basisinstruktionen RVd ()
    • Dazu gibt es Optionale Instruction-Set-Extentions (Befehlssatzerweiterungen) u.a:
      • RVd: Multiplikation & Division
      • RVd: Floating-Point Arithmetic mit einfacher , doppelter und vielfacher Genauigkeit
    • LOAD/STORE-Architektur:
      • Es kann lediglich durch LOAD- bzw. STORE-Befehle auf den RAM zugegriffen werden
      • Alle anderen Befehle müssen mit den Registern auskommen

Die verschiedenen Register

  • 32-Bit Datentyp, hat eine kapazität von "einem Wort"
  • Konventionen legen fest, wie diese Register heißen und wie sie verwendet werden sollen:
    • 12 Register für Variablen des Quellprogramms:
    • 7 Register für temporäre Variablen:
  • Allerdings müssen diese Konventionen nicht zwingend beachtet werden
  • Derartige Konventionen sind aber notwendig, wenn mehrere, potentiell getrennte, Programmteile zusammen laufen können
RegisterNameVerwendung
Konstante 0
Rücksprungadresse
Stackpointer
Globaler Pointer
Threadpointer
--Temporäre Register
/Registerzwischenspeicher oder Framepointer
Registerzwischenspeicher
--Funktionsargumente und Rückgabewerte
--Funktionsargumente
--Registerzwischenspeicher
--Temporäre Register
  • Beschränkte Anzahl von Registern
    • Diese sind leider unzureichend um die Variablen von "echten" Programmen aufzunehmen
  • Deswegen müssen größere, oder größere Mengen von Variablen (z.B. Arrays) im Speicher abgelegt werden.

Arithmetische Befehle

  • Befehle für Festkommaarithmetik (RV32 )
    • mit oder ohne Vorzeichen
  • Befehle für Gleitkommaarithmetik (RV32 )
    • Im prozessor integriert
    • Emulation durch Zerlegung in elementare Operationen
  • Vergleichsbefehle
  • Schiebe und Rotationsbefehle

Rechenbefehle

InstruktionOperationResultat
ADD , , Add
ADDI , , Add immediate
  • Analog dazu gibt es SUB
  • Andere Assemblersprachen lassen auch Speicherinhalte als Operanden zu (z.b. Einige CISC Sprachen)

Vergleichsbefehle

InstruktionOperationResultat
SLT Set less than
SLTU SLT unsigned

Schiebebefehle

InstruktionOperationResultat
SLL Shift left logical
SRL Shift right logical
SRA Shift right arithmetic

Notation: kann Register oder Immediate sein

Ladebefehle

InstruktionOperationResultat
LUI Load upper immediate
LW Load word
LB Load byte

Speicherbefehle (Memory)

InstruktionOperationResultat
SB Store byte
SW Store word

Logische Befehle

InstruktionOperationResultat
AND And
  • BITWISE OR
  • Analog dazu OR, XOR (Exclusive Or)

Sprungbefehle

  • Werden verwendet um den ablauf von Programmen zu steuern
  • Klassifikation
    • bedingte / unbedingte Sprungbefehle
      • Sprung erfolgt relativ zum Programmzähler oder absolut
    • Unterprogrammaufrufe (wie Subroutines oder so)
    • Rückker zum aufrufenden Programmabschnitt (wie beim ende einer Subroutine)
      • Nennt man auch "unterprogrammbeendigung"
    • Unterbrechung (Interrupt)

Unbedingte Sprünge: (pc: Program Counter)

InstruktionOperationResultat
JAL Jump and Link, Sprung zu
JALR JAL RegisterJAL zu Adresse

Bedingte Sprünge

InstruktionOperationResultat
BEQ Branch EqualSprung, falls
BNE Branch not EqualSprung, falls
BLT Branch Less ThanSprung, falls
BGE Branch Greater EqualSprung, falls
BLTU Unsingned BLTSprung, falls
BGEU Unsingned BGESprung, falls

Systembefehle

In RISC-V

InstruktionOperation
ECALLSystemaufruf

Control-/Statusregister (CSR):

InstruktionOperation
CSRR{W|S|R} Lese bzw, überschreibe Control- und Statusregister
  • Dat gut für
    • Fehlerbehandlung(Exceptions)
    • das Steuern vom Prozessorverhalten

Beispiele für Systembefehle

Rechenbefehle

BedeutungRISC-V Instruktion
  • Längere Ausdrücke müssen vom Anwender bzw. dem Compiler in eine Reihe von einfacheren operationen aufgeteilt werden
  • Wenn nötig kann man auch temporäre Variablen einführen
  • Befehl
  • Annahme: Variable befindet sich im Register , im Register , im Register und im Register . Das Ergebnis soll im Register gespeichert werden.

(# Ist hier der Kommentar-Operator)

Logische Befehle

Sprungbefehle

  • C/C++ Programm:
if (i == j) {
    f = g + h;
} else {
    f = g - h;
}
  • RISC-V Assembler-Programm:
    Annahmen: Variablen in

  • Hier sind und Labels (Sprungmarken) zu denen gesprungen werden kann

Anderes Beispiel:

Annahmen: Variablen in Ebenso: Basisadresse von in

Hier ist ein massiv weiteres Beispiel für Assembly

Datentransportbefehle


Annahme: ist ein Array vom Datentyp Wort. Die Variable steht im Register , die Basisadresse von steht im Register

Datentransportbefehle

  • Transport von Daten zwischen Quelle und Ziel
  • Quelle und Ziel sind entweder im Hauptspeicher oder in den Registern
  • Übertragung ist auch zwischen den I/O-Schnitstellen und Registern möglich
  • Zudem ist Transport nicht wirklich das Richtige Wort, Weil eigentlich nicht wirklich viel von der Quelle entfernt wird

Adressierungsarten

(Keine RISC-V Befehle)

  • Implizite Adressierung
    • Dat Ziel wird durch den Befehl bestimmt
  • Unmittelbare Adressierung
    • Operand wird als Wert angegeben
  • absolute (direkte) Adressierung
    • Operand ist Inhalt der angegeben Adresse
  • indirekte Adressierung
    • Operand ist Inhalt des Zeigers an der angegeben Adresse
  • indizierte Adressierung

Unterprogramme

(Subroutines oder so)

  • Prinzipieller Ablauf, wie kann man sich dat vorstellen
    • Der Kontrollfluss wird an eine Subrutine abgegeben
    • Diese Prozedur macht wat sie machen soll
    • Und dann wird der Kontrollfluss zurück an die aufrundende Funktion geworfen
  • RISC-V-Unterstützung für Prozeduraufrufe
    • es gibt ein spezielles Register für die Sicherung der Rücksprungadresse:
    • Sprunginstruktionen
      • (Jump and Link)
        • Speichert die Rücksprungadresse in und springt dann zur Adresse der Subroutine
      • (Jump Register)
        • springt zur Adresse, die im angegebenen Register steht, d.h. springt zurück zum aufrufenden Programm
      • Hier eine tolle grafik die diesen Sachverhalt zeigt
    • Prozeduren brauchen im Allgemeinen Argumente und leifern Resultate
      • Dafür gibt es in RISC-V folgende Konvention:
        • 8 Register für Argumente
        • 2 Register für Resultate

Beispielprogramm:

Gegeben: Wert in Register , Rückgabe in

Beispielprogramm, n! ausrechnet

Instruktionskodierung

  • Wir haben bisher die Instruktionen "nur" in Assemblersprache notiert, der Prozessor versteht den kram aber leider so garnich
  • Detwegen müssen wir iwas aus dem kram machen, was der Prozessor verstehen kann.
  • Was kann der verstehen? genau! binär, deswegen müssen wir dat jz binär kodieren
  • Das nennt man (... Trommelwirbel) Instruktionskodierung (Wasn Schocker)

add

  • Bei RV32 sind alle Instruktionen 32 Bit lang!
    • Da die ganzen Instruktionen allerdings verschieden viele Operanden haben, gibt es verschiedene Instruktionsformate:
      • R-Typ
      • I-Typ
      • S/B-Typ
      • U/J Typ

Instruktionsformat R-Typ

Instruktionsformat R-Typ (Register-Format) wird für Arithmetische Instruktionen verwendet

Hier ist ne Grafik die garnicht zu 100% aus den Folien geklaut ist

Instruktionsformat I-Typ

Das Immediate-Format wird verwendet für

  • Immediate-Versionen der arithmetischen und logischen Instruktionen
  • Load-Instruktionen und Systembefehle

Hier ist noch ne krasse Grafik vom Niemeier

  • ist eine signed 12-bit Zahl im 2er Kimplement und kann dadurch Werte zwischen und annehmen
  • Beispiel:

hier noch ein massiv besseres bld für ityp

Instruktionsformat S/B-Typ

Das Store-Format wird, wie man sich wohl schion denken kann, für Store-Befehle verwendet

Krasses bild was den aufbau für das ding da zeigt

  • offset ist eine signed 12Bit-Zahl auf die der Wert aus Register addiert wird um die effektive Speicheradresse zu bekommen

mehr krasse beispiele

Beim B-Typ - also Branch-Format für bedingte Sprünge - gibt es eine andere interpretation der offset bits

Instruktionsformat U/J-Typ

Das Upper-Format wird für Spezielle Load-Befehle verwendet

Krasses beispiel für uj dings

  • ist eine 32-Bit Zahl deren 20 höchstwertige Bits
    [31:12] ins Register geladen werden

Beim J-Typ, also unbedingten Sprüngen wird die effektive Sprungadresse aus [20:1] (interpretiert als signed 20-bit Zahl) konstruiert

Assembler Maschinenschprache

AssemblerMaschinensprache
Symbolische Bezeichnung von Befehlen, Adressen (label) und teils der operandenBinäre Darstellung von Befehlen (Op-Code) Adressen und Operanden in einem Datenwort
Ein-/Ausgabe-Routinen eines etwaigen betriebssystems könenn verwendet werdenBibliotheken für komplexe Befehl(sketten)
Programme müssen vor der Ausführung assembliert (also zu Maschinensprache übersetzt) werdenProgrammen werden direkt ausgeführt, da wir praktisch eine "binary" von hand schreiben

Verarbeitung einer Instruktion (RISC-V)

  • Im Folgenden bereits um Pipelining erweitererte CPU
    • Pipelining kommt später
  • Die verarbeitung läuft Stufenweise
    • Wir holen uns den befehl
    • Decoden den kram erstmal / Holen uns den Operanden
    • Befehl ausführen
    • Speicherzugriff (wenn wa wat schreiben oder lesen wollen)
    • Ergebnis in Register schreiben
  • Hier ist zu beachten, dass es je nach prozessor anders aussehen kann

Aufbau eines RISC-V Prozessors

Hier eine schematic wie der RISC-V Prozessor aussieht Hier ein Weiteres Bildschin mit anderen krassen instruktionssachen

Befehlssätze und Optimierungen

Die Extreme:
CISC-Rechner und RISC-Rechner

CISC - Complex Instruction Set Computer

  • Großer Satz von Maschinenbefehlen
    • Diese können teilweise sehr Spezifische und Komplexe operationen selbstständig ausführen
  • Sehr unterschiedliche Ausführungszeiten, also nicht wirklich regelmäßig
  • Das system wird durch ein sog. Mikroprogramm im Prozessor gesteuert, nicht durch direkte Hardware.
  • Zudem war der erste "moderne" Rechner (IBM 369) ein CISC-Rechner

Was spricht für CISC?

  • Komplexe Befehle schliessen eine Lücke zwischen den programmiersprachen und der hardware
    • es gibt "direktere" übersetzungen
  • Komplexe Befehle verringern den Ramverbrauch, da alles praktisch "vorprogrammiert" ist und nicht erst in viele kleine operation zerbrochen werden muss
  • Dadurch kann es auch zu einem geschwindigkeitsboost kommen, da weniger auf den "langsamen" Speicher zugegriffen werden muss
  • Komplexe befehle können vom Compiler einfacher aus geschriebenem programmcode hergeleitet werden
  • Je mehr der Computer in hardware / intern Regeln kann, desto zuverlässiger "ist" er, denn hardware ist angeblich zuversichtlich
    • Ist allerdings nicht ganz richtig, da fehler die hier auftreten, fast nicht zu beheben sind ohne neue hardware zu beschaffen

Was spricht dagegen?

  • Viele Programmspeicher-Zugriffe können aufgrund von Cache strategien sehr schnell und effizient ausgeführt werden
    • Dementsprechend brauchen wir keine "riesiegen" mikroprogramme
  • Hardware ist, wie oben schon gesagt, nicht zuverlässiger als Software, zum großen teil auch wegen der fehlenden debugging-möglichkeit
  • Die komplexen befehle die der compiler "einfach" nutzen könnte werden von modernen Compilern kaum noch genutzt, da sie oft sehr spezifisch sind und gewisse hardware voraussetzen

Eine Statistik für CISC-Rechner (ca.1990)

Wenn wir uns CISC Rechner anschauen, denken wir an die Intels und AMDs auf dieser Welt, irgendwie klar weil sie die einzigsten firmen auf der Welt sind die die x86 Architektur verwenden dürfen, die, wie oben erläutert, die weit verbreiteteste CISC Architektur die wir haben ist.

Hier eine krasse Statistik die zeigt wie falsch die leute at itel damals lagen

Wenn wir uns obige Statistik anschauen, sehen wir, dass mehr als 90% aller Operationen die ein x86 (oder auch x86, x86_64 (auch bekannt als AMD64 weil AMD als erste Firma einen funktionierenden 64-Bit prozessor bauen konnte)) ausführt "einfache" Befehle sind, die nicht weiter heruntergebrochen werden können und deswegen auch direkt in Hardware gehandled werden könnten. Da dies bei CISC allerdings nicht passiert, wird effizienz auf dem tisch liegen gelassen, um die restlichen ~10% zu supporten.

RISC - Reduced Instruction Set Computer

  • Einfache Befehle
    • Deswegen ein insgesamt kleinerer Befehssatz
  • Jeder Befehl ist in einem Verarbeitungsschrit ausführbar
    • Effizienz durch berechenbarkeit
  • großer interner Registersatz
  • Leistungsfähige Speicherhirachie
  • Dadurch, dass das System nicht mehr durch Mikrocode Kontrolliert wird, kann ein Fest verdratetes Steuerwerk verwendet werdn
  • Dadurch wird das System schneller und effizienter, einfach weil Hardware in so ziemlich jedem fall schneller ist als software.

Bekannte Beispiele für RISC-Prozessoren sind

  • Mips R2000/3000 (1982-89)
  • IBM Power
  • IBM PowerPC
  • Apple M
  • Apple A
  • Apple T
  • Quallcomm Snapdragon

RISC VS CISC

Hier ein massiv cooles bild was die Performance und Zyklenanzahl zwischen RISC und CISC vergleicht

Man sieht hier vor allem, dass RISC was Zyklen / Operation angeht um einiges Effizienter agiert als CISC in vergleichbaren fällen.
Ein Großes Element ist natürlich auch der Unterschied zwischen Hardware und Software als ausführungsplattform, da Hardware logischerweise um einiges schneller und effizienter ist.

Hier mal ein paar konkrete beispiele:

  • Power PC (IBM, RISC)

    • Operanden aus dem Hauptspeicher kommen nur von load-, store-, branch- oder cache-Befehlen vor
    • Drei Modi der Adressberechnung:
      • Registerinhalte + Konstante
      • Summe zweier Register
      • Registerinhalt
  • Pentium 4 (Intel, CISC)

    • Mögliche Operanden für beliebige Befehle
      • Konstante (natürlich nicht für Ergebnisse)
      • Registerinhalt
      • Speicherplatz
      • I/O Port
    • Adressberechnung:
      • Speicheradresse = Segment + Offset
      • Segment steht in einem speziellen Register
      • Offset wird entsprechend der folgenden Tabelle berechnet
      • Hier eine massiv coole tabelle die darstellt, wie ein Pentium4 die Memoryadressen berechnet

Designprinzipien für Rechner

  • Was sind die Schlüsseloperationen für das was wir bauen wollen
  • Wie soll der Datenpfad aussehen? (also dat rechenwerk + die Verbindungen zum RAM etc.)
  • Was brauchen wir für Maschinenbefehle in dieser Architektur.
    • Wie können wir dafür sorgen, dass alles was wir brauchen möglichst in Hardware und ohne mikroprogramme in einem Zyklus ausführbar ist
  • Wie können wir den Befehlssatz erweiterbar machen, aber so, dass bei erweiterung die Maschine nicht langsamer wird

Pipelining

Wat dat überhaupt?

Wir visualisieren uns dat mal mit nem massiv coolen Beispiel:
Wir kommen nachhause und finden einfach nen riesigen haufen Wäsche die AUF EINMAL dreckig geworden ist.

Nun Reflektieren wir mal darüber, wie wir die wäsche wieder sauber bekommen. Unserer normaler Workflow ist wie folgt:

  1. Wir nehmen die Dreckige Wäsche und stecken sie gewaltsam in die Waschmaschine die dann etwa 30 Minuten Läuft
  2. Wir werfen die gewaschene Wäsche in den Trockner der dann ebenfalls wieder 30 Minuten läuft
  3. Dann müssen wir die Kleidung Bügeln und falten, was wieder etwa 30 Minuten dauert
  4. Und zuletzt müssen wir unsere nun wieder saubere Wäsche nehmen und sie in den schrank räumen.

Wir werfen einen Blick auf den unmöglich großen Berg an plötzlich dreckiger wäsche und realisieren, dass dat nich alles in unsere Waschmaschine passt. Wir müssen sogar warscheinlich insgesamt 4 Mal waschen. Das dauert, wenn wir alles hintereinander machen, ja knapp 8 Stunden. Das ist nicht so gut, und genau hier kommt pipelining ins spiel!
Denn wenn wir mehrere Verschiedene Arbeitsschrotte auf einmal bzw. gleichzeitig erledigen können reduzieren wir die zeit von etwa 8 auf 3 Stunden Reduzieren!
Wie wir das machen zeigt dieses Bild:

Hier ein bild was das oben beschriebene Phänomen beschreibt und dadurch die beschreibung beschreibender macht

Das ist ja alles Schön und gut, aber wie machen wir das Im computer?!

  • Damit wir Pipelining im Datenpfad anwenden können müssen wir die abarbeitung der diversen Maschinenbefehle in mehrere teilschritte (Phasen) aufteilen die idealerweise alle die gleiche dauer haben.
  • Bei der Aufteilung ist vor allem der bestehende Befehlssatz und die zur verfügung stehende Hardware zu beachten, da die beiden elemente genau aufeinander abgestimmt sein müssen, wenn wir ein effizientes system entwickeln wollen.
  • Hier ein Beispiel für die Abarbeitung in 5-Schritten:
    • Befehl-Holphase, auch bekannt als Instruction-Fetch
    • Dekodierungsphase, hier lesen wir die Operanden aus Registern
    • Ausführung / Adressberechnung, hier führen wir den befehl aus und berechnen wo wirs hin speichern müssen
    • Speicherzugriff, hier wird alles gelesen was wir vom Speicher wollten
    • Abspeicherphase (result write back phase) Hier schreiben wir alles zurück in den speicher, was wir berechnet haben
  • Bei CISC Pipelinig ists schwierig die genaue dauer zu bestimmen, da mikroprogramme in der Dekodier und Ausführungsphase unterschiedlich lang brauchen können und die komplexität sehr unterschiedlich sein kann

Hier ein Beispiel wie man den Datenpfad aufteilen kann:

Krasse Graphik von dem Datenpfad eines RISC-V Prozessors die in 5 segmente unterteilt ist

Speedup

  • Annahmen:
    • Abarbeitungszeit eines Befehls ohne Pipelining:
    • wir haben pipelinestufen mit gleicher lauftzeit der Stufen
    • Laufzeit einer Stufe ist also
  • Beschleunigung Bei ausführenden Instruktionen
    • Laufzeit mit pipeline =
    • Laufzeit mit Pipeline =
      • Beschleunigung um Faktor

Laufzeit mit Pipeline:
Laufzeit ohne Pipeline:

Beschleunigung um:

Ergebnis:

für nähert sich der Speedup also der Anzahl der Pipelinestufen

Es wurde vorausgesetzt, dass sich die Ausführung der BEfehle ohne weiteres aneinanderreihen ("verzahnen") lässt. Dies ist in der Praxis mit immer der Fall Hazards

Hazards

Massiv krasse Gefahren würd ich mal sagen (boah krass dat hat sich ja sogar gereimt)

Hier ist ein weiteres massiv krasses game

Hier tritt ein Problem auf! Denn wenn pipelining verwendet wird kann es sein, dass der ADD Befehl in diesem Beispiel nicht auf den Wert in R1 zugreifen kann wenn man die Pipeline nicht stoppt

Dat kann man lösen indem man NOPs einfügt, also No-Operation

Ein NOP könnte erspart werden, wenn der load befehl direkt am ende der Execute-Phase das ergebnis im angegebenen Register zur verfügung stellt. Allerdings ist dafür extra Hardware von nöten

Bedingte Verzweigung: Control Hazards

Sprungbedingungen werden potentiell zu spät ausgeführt, da durch das pipeling schon die nächste Instruktion abgearbeitet wird

Mögliche Lösung: Branch Prediction

  • Mit branch Prediction Raten wir praktisch, was als nächstes kommt
    • Natürlich raten wir nicht vollständig sondern agieren auf bisherigen erkenntnissen
  • Wir springen also basierend auf unserer Spekulation durch die gegend
  • Und falls wir uns mal vertun leeren wir die pipeline wieder auf den vorherigen stand wenn wir dann "zurücksetzen"

Zusammenfassend

  • Wir können unsere Schnelligkeit in den Pipelines steigern, indem wir Branch Prediction oder Forwarding und Optimierung der Instruktionen verwenden, allerdings kann das auch zu Hazards führen die unterm strich unsere Schnelligkeit verringern

Out of Order Execution

In Ohrder ExecutionOut of Order Execution
Es wird sich strickt an den Programmcode gehalten und alles wird sequenziell ausgeführtProzessor bestimmt die ausführungsreihenfolge und optimiert "on the fly" mit möglichen Fehlern
Vorab-analyse von Datenabhängigkeiten und DatenflussFortlaufende Datenabhängigkeitanalyse zur Laufzeit
Warten auf "langsamere" BefehleKein warten, alles was unabhängig bearbeitet werden kann wird dann einfach vorgezogen
LeistungseinbußenSchnelligkeit erfordert zusätzliche Hardware, kann zu unvorhersebaren Risiken führen

Datenabhängigkeiten

  • Read-after-Write (RAW)

    • bzw. True Dependence
    • Instruktion liest Wert aus Register, das in beschrieben wurde
  • Problem:

    • Zugriff auf veralteten Registerwert
    • Hier ein krasses beispiel was probleme bei Pipelining hervorhebt -Die lö sung hier: Wir müssen mit der Ausführung Warten, bis wir den richtigen wert haben.
  • Write-after-Read (WAR)

    • bzw. Anti-Dependence
    • Instruktion schreibt Wert in Register, das in gelesen wurde
    • Hier ein weiteres Beispielprogramm was massiv cool ist
  • Problem

    • ggf. haben wir aufgrund der Veränderten Ausführungsreihenfolge den falschen Wert.
    • Lösung hier: ALten wert Zwischenspeichern und das Register umbenennen (Also einfach ein anderes Verwenden)
  • Write-after-Write (WAW)

    • bzw. Output Dependence
    • Instruktion schreibt Wert in Register, das in beschrieben wurde
    • Hier ein drittes, massiv cooles, asm beispiel in RISCVASM
  • Problem:

    • Hier ist ggf auch der falsche wert aufgrund der veränderten Ausführungsreihenfolge
    • Die Lösung sieht hier ähnlich aus, wir nennen die Register um bzw. verwenden andere Ressourcen

Out-Of-Order-Execution

  • Erlaube, dass RAW unabhängige Instruktionen langsame "überholen" können
  • Mehrere Funktionseinheiten verwenden um die Execute-Phase zu Pararellisieren
  • Scheduler ein, der Instruktionen ihrer geschwindigkeit und aktuellen Prozessorauslastung scheduled und ausführt.
    • Hierfür verwendet man dann einen "Warteraum" für die nach hinten verlegten Instruktionen

Data-Driven-Execution-Graph

Hier ein krasser DDE Graph

Modifikation Registerbank

Hier ist noch eine weitere krasse registerbank

  • Pro Register zusätzliche Felder Busy und Producer.
  • Busy: Eine instruktion I in FU die gewisse instruktionen in dieses Feld schiebt
  • Producer: (nur relevant falls Busy-Flag gesetzt): Eindeutiger Name dieser Instruktion
  • Als namen werden Paare (j, k) mit folgender Bedeutung verwendet:
    • Diese instruktion wurde zur Dispatchzeit in SlotJ des Warteraumes der Funktionseinheit Allokiert
    • Schreibenden Zugriff auf Register erhält bei gesetztem busy flag nur der dort eingetragene Producer. SObald dieser schreibt wird das busy flag resetted

Struktur dieser "Warteräume"

  • Busy: Dieser Slot ist besetzt
  • Opcode der auszuführenden Instruktion
  • Dest Das zielregister für das Ergebnis der Instruktion
  • Source1 werden Kopiert aus den zur Dispatchzeit vorliegenden einträgen für die Source.Register
  • Wenn der Wert des Register aktuell berechnet wird, ist die Waiting flag gesezt, und der Produzent des Wertes Eingetragen
  • Data-Driven-Execution: Nur wenn beide Waiting Flags nicht gesetzt sind, kann die Instruktion ausgeführt werden

Verteilung der Ergebnisse

  • FU legt Dest, Producer, Value auf Common data bus
  • Alle FUs hören mit, und schauen ob in einem Warteslot auf diese Producer-Daten gewartet wird
  • Wenn ja: Wird das waiting flack zurückgesetzt und der Wert übernommen
  • Registerbank lässt den schreibzugriff auf Destination nur zu, wenn keine busy flag gesetzt ist und der genannte Producer mit dem Producer aus dem Common data bus übereinstimmt

Speicheradressierung

  • Speicher wird mit Byteadressen adressiert
    • Speicher ist praktisch ein Riesiges eindimensionales Array von Bytes
    • Adresse einer Speicherzelle entspricht dem Array Index
    • Logischerweise (looking at you, Lua) startet das Array bei 0, also ist dat auch die niedrigste Speicheradresse
  • Wie wird ein Wort (4 Byte / 32-Bit) im Speicher abgelegt?
    • Das höchstwertige Byte des Wortes speichert sich an der niedrigsten Byte adresse
    • Ein wort wird mit der Adresse seines höchstwertigsten Bytes adressiert (also da wo es losgeht)
    • Wortadressen müssen ein vielfaches von 4 sein ("Alignment Restriction")

SRAM

  • Static Random Access Memory

  • Ja halt statischer speicher für einen bit
  • Gleicher aufwand für lesen und schreiben
  • Die information wird im status der inneren Transistoren gespeichert
  • Vorteile:
    • ist sehr schnell
    • Braucht keine regelmäßige Auffrischung
  • Nachteil:
    • Physisch relativ groß im gegensatz zu DRAM

DRAM

  • Dynamic Random Access Memory

  • Information wird in der Ladung eines Kondensators gespeichert
  • Vorteile:
    • Einfacher Aufbau
    • Geringe Größe
  • Nachteile
    • höhere Zugriffszeit
    • kondensator verliert mit der zeit seine ladung
      • braucht daher einen periodischen refresh

Aufbau von Zellfeldern

  • 2-Dimensionale Matrix
  • mehrere Speicherzellen Speicherzeile
  • Mehrere Speicherzeilen Speicherfeld/Zellenfeld
  • Mehrere Speicherfelder
    • 1 Speicherbank
  • Mehrere Speicherbanken
    • 1 Speicherchip

Funktionsweise des RAM

  1. Ansprechen von Ziel chip/bank
  2. Speichercontroller der CPU übermittelt die Adresse
    • Entschlüsselung durch Zelendecoder
  3. Aktivierung der Speicherzeile (wordline)
  4. Spaltendecoder ermittelt die richtige Position
  5. Bitline wird mit Datenleitung des speicherchips verbunden
    • Lesen: Zustand des Kondensators wird ausgelesen
    • Schreiben: Richtiger Zustand wird gesetzt
  6. Deaktivierung der Speicherzelle

Gründe für Komlexe Speicheroganisation

  • Ein Zugriff auf eine Hauptspeicherzelle ist langsamer als ein Zugriff auf ein Register
    • Hautpspeicherzellen sind DRAM-Zeilen (dynamische speicherzellen), wärend Register in der Regel SRAM-Zellen (statische Speicherzellen) sind
    • Bei einem "simplen" registerzugriff kommt man sogar ohne Bus-operation aus!
  • Idee: man stellt dem prozessor einfach einige megabyte Register zur Verfügung
    • Aber:
      SRAM-Zeilen sind wesentlich größer als DRAM-Zellen
  • Leider ist das derzeit noch nicht realistisch, das kann aber vielleicht in der Zukunft kommen.

Lokalitätsprinzip

  • Lokalitätsprinzip:
    • Programme greifen sehr schnell hinterinander auf einen relativ kleinen Teil des Adressraums zu
  • Temporale Lokalität
    • Wenn ein Zugriff auf eine Adresse erfolgt, wird auf diese Adresse mit "großer" Wahrscheinlichkeit bald wieder zugegriffen
      • z.b. beim Abarbeiten von schleifen
  • Räumliche Lokalität
    • Wenn ein Zugriff auf eine Adresse erfolgt, werden mit "großer" Watscheinlichkeit bald Zugriffe auf in der nähe liegende Adressen erfolgen
      • z.b. Verarbeiten von Arrays, Loopen durch Listen
  • Aufgrund der Lokalität kann man Speichersysteme hierarchisch aufbauen
    • Obere Stufe der Hierarchie: schneller und teurer Speicher (wenig)
    • Untere Stufe der Hierarchie: Langsamer und billiger Speicher (aber viel davon)

Speicherorganisation Heute

Hier eine krasse Grafik die Zeigt wie Speicherorganisation heute funktioniert

Hier noch eine krasse speichertabelle die Speichertabelle anzeigt

Big Endian vs Little Endian

Boah krass eine visualisierung die erklärt was little und was Big endian ist

Caches

  • Cache kommt aus dem Französischen cacher (verstecken)
  • Er kann durch ein Anwendungsprogramm nicht explizit adressiert werden
  • Der kram ist "software-Transparent", d.h. der benutzer muss eig nich wissen, dass es den kram gibt

Lage des Caches

hier liegt der Cache in einer massiv krassen grafik die wieder angezeigt wird

In der Regel besitzt ein Rechner getrennte Caches für Instruktionen (Instruktionscache) und für Daten (Datencache)

Ziel des Cache Einsatzes

  • Wir versuchen die daten so "nah wie möglich" zu halten
    • Prozessor kann dann mehr auf Caches zugreifen und verschwendet weniger zeit beim warten auf den langsamen RAM oder auf den unglaublich langsamen langzeitspeicher
  • Hierfür müssen wir das oben angesprochene Lokalitätsprinzip verwenden

Wie sieht das in der Praxis aus?

Wenn der CPU die daten die er sucht in dem Cache findet, dann ist er glücklich und macht einfach weiter ohne zu warten
Sei das aber nicht so schön, muss der CPU erstmal auf den Arbeitsspeicher zu und schreibt das was er gelesen hat gleichzeitig in den cache, und in die arbeitsregister der CPU

Mittlere Zugriffszeit beim Lesen

  • Zugriffszeit des Caches
  • Zugriffszeit beim Hauptspeicher
  • Trefferrate
  • Durchschnittliche Zugriffszeit:

Aufbau eines Caches

  • Ein Cache besteht aus zwei Speicher-EInheiten, die wortweise einander fest zugeordnet sind,
  • Hier ist eine wundervolle Grafik die uns zeigt wie toll ein Cache von innen aufgebaut ist

Cache als assoziativer Speicher

  • Im idealfall, wäre Cache immer Inhaltsorientiert, also assoziativ
  • Die von dem Prozessor angelegte Adresse wird parallel mit allen im Adresspeicher des Caches vorhandenen Adressen verglichen
  • Außerdem kann ein neues Datenteil praktisch an jeder freien Stelle des caches abegelgt werden.
  • Deswegen gibt es eine Aufwendige Logik für den Parallelen Vergleich
  • Assoziative Speicher nur für kleine Cache-größen

Was passiert mit Alten daten?

  • Wenn wir cachedaten nicht mehr brauchen, dann müssen wir sie wegwerfen um platz für neues zu machen.
  • Wenn wir noch nen register frei haben, nutzen wir immer erst das, einfach weil das uns den job einfacher macht und wir nicht 500 Sachen abfragen müssen
  • Wenn aber nix mehr frei ist, dann schauen wir nach einigen Kriterien
    • Least Recently used (LRU) wirft das weg was am längsten nicht benutzt wurde
    • Least Frequently Used (LFU) wirft dat wech, auf das am wenigsten zugegriffen wird
    • First in, First out (FIFO) Wirft das über bord, wat schon am länchsten da war

Direct Mapped Cache

  • Die von der CPU angelegte Adresse wird in 2 Teile Gespalten
    • Die niederwertigen Bits adressieren einen EIntrag im Adresspeicher
    • Dieser Eintrag wird dann mit den höherwertigen Bits der Adresse verglichen
  • Speicherzellen des Hauptspeichers, deren niederwertige Stellen gleich sind, werden auf die gleiche Position im Cache abgebildet

Illustration

Hier eine krasse Skizze die Direktaddressierten Cache visualisiert

  • Cache Tag

    • Der Index (Cacheblockadresse) kann nicht eindeutig der Speicherblockadresse zugeordnet werden
    • Also ist der Inhalt des Caches an dieser position somit nicht eindeutig bestimmbar
    • Deshalb verwendet man die restlichen bits der Speicherblockadresse für einen sog. "Tag"
      • Zu jedem block im Cache speichern wir auch den Tag
    • Wir finden jetzt also daten, indem wir die caches nach dem Tag und dem Eintrag suchen
  • Valid bit

    • Ja nen bit was sagt, ob der eintrag valid is
      • Am anfang (und nach jedem flushen) enthält der cache keine gültigen daten
        • Also ist das Valid bit 0
      • Wenn wir dann aber einen validen eintrag hinzufügen, wird das bit auf 1 gesetzt

Hier eine massiv coole grafik die uns zeigt, wie viel direct mapped Cache ausmachen kann

Hier sehen wir, wie viele Anfragen im cache gehittet werden können, gemessen an der cachegröße

Prinzipielle Funktionsweise: Schreibzugriff

  • Schreibe Datum in den Arbeitsspeicher unter Adresse :
  • CPU Überprüft, ob eine Kopie der Hauptspeicherzelle a im Cache abgelegt ist
  • Write-through verfahren

    • cache miss: CPU schreibt das Datum in die Hauptspeicherzelle mit der Adresse . Der Inhalt des Cache wird nicht verändert
    • cache hit: die Kopie der Haauptspeicherzelle im Cache wird aktualisiert, die Hauptspeicherzelle wird auch direkt aktualisiert
      • so kann sich der Prozessor auch direkt anderen sachen widmen, aber der speicher-controller regelt das update im ram, ohne dass der Prozessor warten muss
  • Write-back Verfahren

    • cache miss: CPU schreibt das datum in die Hauptspeicherzelle mit Adresse , Der Inhalt des caches wird nicht verändert.
    • cache hit: Die kopie der Hauptspeicherzelle im Cache wird aktualisiert und durch "dirty bit" als verändert markiert. Die hauptspeicherzelle selbst wird erst später aktualisiert, nämlich erst wenn die Kopie ausm cache geworfen wird, die CPU damit also "fertig" ist
  • write-allocation Verfahren

    • cache miss: CPU schreibt Datum in den Cache (markiert mit "dirty bit"), aber nicht in den Hauptspeicher, da wirds dann wie oben erst aktualisiert, wenns ausm cache geworfen wird
    • cache hit: Wie beim write-back verfahren

Writeback VS writeallocation

Vorteile von Write-back/Write-allocation

  • Schreibzugriffe auf Cache bei cache hit ohne Wartezyklus möglich (bei write-allocation sogar bei cache miss)
  • Belastung des Systembusses kleiner, wenn das Rückschreiben in den Hauptspeicher erst nach mehreren Schreibvorgängen erfolgen muss

Nachteile von Write-back/Write-allocation

  • Schwierikeiten bei der Datenkonsistenz, wenn andere Komponenten die daten brauchen die nicht auf den CPU-Cache zugreifen können

Festplatte (Hard Disk Drive)

  • ja dat ding hat halt mehrere Platten
  • Die haben jeweils ihren eigenen lese/schreibkopf
  • und dann funktioniert dat maßgeblich wie ne CD
  • Sind aufgeteilt in Sektoren von 128Byte bis 1 Kbyte
  • Und haben dann auch diverse Spuren & Schreibdichten

Adressierung

  • Heute verwenden wir das sog. Logical block addrssing, oder LBA
  • Hierbei sind die Sektoren fortlaufend numerriert
  • Und ein Festplattencontroller übersetzt in physikalische Koordinaten des Sektors

Partitionierung

  • Festplatten kann man aufteilen in diverse Partitionen
    • Wie eine partition aufgebaut aussieht, steht im ersten Sektor im "master boot record" (MBR) oder den äußeren 32 Sektoren (GUID Partition Table, GPT) in einer sog. Partitionstabelle
  • MBR: 4 Master-Partitionen, je 16 Byte

    • Erster und letzter Sektur in CHS-Koordinaten (je 3Byte)
    • Erster Sektor in LBA und Gesamtzahl Sektoren (je 4Byte)
    • allg. Informationen (Typ/Format, bootfähig; je 1 Byte)
    • Maximale Partitionsgröße: Abhängig vom System
    • Maximale Festplattengröße: Abhängig von Systemarchitektur
  • MBR: Enthält vorwiegen Bootstrap-Code zum Laden des Betriebssystems (wird von BIOS/UEFI beim Start geladen und ausgeführt)

Ausführung eines Festplattenzugriffs

  • Beweg die Köpfe zu dem Richtigen Zylinder
  • Warte bis der gesuchte Sketor zum Kopf rotiert
  • Übertrage den Inhalt des Sektors

Hier ein beispiel für die rechnung eines festplattenzugriffs

Alternative: Solid State Disk (SSD)

  • Hier werden zum speichern Halbleiterbausteine wie beim RAM verwendet
  • Es gibt zwei große verfahren:
    • Flash-Specher:
      • Nicht flüchtig (verliert also seinen zustand nicht, wenn er keinen strom mehr bekommt)
      • sehr energieeffizient
      • Kurze Zugriffszit ~
    • SDRAM
      • Flüchtig, deswegen nicht für langzeitspeicher geeignet
      • Allerdings als cache für die SSDs
      • Ist allerdings auch seeehr schnell
      • aber Stromineffizienter
  • Vorteile:
    • kein verschleis weil keine mechanischen teile
    • Kann besser mit äußerlichen Einwirkungen umgehen
    • Ideal für Anwendungen mit niedrigem energieverbrauch
  • Nachteil:
    • Deutlich Teurer als Festplatten
    • Nicht beliebig oft wiederbeschreibbar (flash: 100.000 bis 5 Millionen Schreibyklen)
    • Daher benutzen die meissten modernen SSds Reserve-Zellen und Wear-leveling-Algorithmen

Das problem mit dem Hauptspeicher

  • Der adressraum von heutigen Computern, ist aufgrund von 64-Bit Prozessoren sehr groß
  • Bei busbreite sind beispielsweise Speicherzellen adressierbar
  • So viel speicher hat aber niemand, weils einfach unendlich teuer wird

Daher: Festplatte als virtuellen Arbeitsspeicher verwenden

  • Der nutzer kriegt davon eig nix mit
  • Wie sieht das dann in der Praxis "unter der haube" aus?

    • Multi-User: nicht jeder benutzer kriegt den kompletten hauptspeicher zugeschrieben
    • Programme werden nicht für einen spezifischen rechner geschrieben, sondern sehr generalisiert
  • Ausweg?

    • Benutze die Festplatte als erweiterten Hauptspeicher
    • Hier sollen dann sachen die noch gebraucht werden, aber nicht unbedingt dringend gebraucht werden gelagert werden, sobald nicht mehr genug platz im Hauptspeicher ist

Ja aber was machen wir jetzt mit dem Adressraum?

-> Virtueller adressraum

  • Jeder Prozess bekommt einen virtuellen Adressraum
  • Diese virtuellen adressräume werden vom Betriebssystem verwaltet
    • Das OS hat also eine "übersetzungstabelle", denn wenn z.b. Word denkt, dass es auf memory adresse 0x10331 zugreift, weiss das OS, dass die daten in 0xff781 liegen.
    • Zudem verwaltet das Betriebssystem welche programmteile im Ram gehalten werden
    • und wann welche daten in den festplatten-ram (SWAP) ausgelagert werden
  • In diesem zusammenhang werden konzepte wie
    • Paging
    • Segmentierung
  • angewandt

Segmentierung

  • Unterteilung des Virtuellen Speichers in Segmente unterschiedlicher Größen
  • Wenn ein programm versucht ausserhalb seiner Segmentgrenzen zu schreiben gibts den bekannten segmentation fault
  • und wenn nen angefordertes segment erst garnicht existiert, gibts den auch
  • Das betriebssyteme ist dafür verantwortlich, welche segmente im ram liegen und welche weggeworfen werden können und welche weggeworfen werden

Paging

Grundidee

  • Der Virtuelle Speicher wird auf dem Sekundärspeicher abgelegt
    • dabei wird er in seiten fester größe unterteilt
  • der hauptspeicher besteht aus page-frames, die jeweils eine Seite aufnehmen können
  • Eine Seitentabelle (page table) gibt an, welche seitenrahmen durch welche Seiten belget sind

Hier eine Illustration wie paging funktioniert

Paging: Zugriff auf Datenseite

  1. Überprüfe ob Datenseite im Hauptspeicher liegt;
  2. If Seitenfehler (page fault)
  3. then Überprüfe ob ein Seitenrahmen im Hauptspeicher leer ist;
  4. if Kein seitenrahmen leer
  5. then Verdränge eine Seite ausm hauptspeicher und aktualisiere dann die seitentabelle
  6. Schreibe Die datenseite in den Freien Rahmen und aktualisier die tabelle
  7. auf im Hauptspeicher zugreifen

Übersetzung von virtuellem Speicher auf physikalischen Speicher

  • macht eine MMU (memory Management Unit)
    • Ist heutezutage direkt im Prozessor (früher North-Bridge)
    • Cache für zuletzt benutzte Pages
      (Translation Loojkaside Buffer, TLB)
    • Falls nicht in TLB aus (mehrstufiger) Seitentabelle Berechnen
      • das erfordert bis zu 5 Hauptspeicherzugriffe und ggf. Pagefaults (+ handling) falls die seitentabelle nicht vollständig im speicher ist
  • Caches:
    • PIPT (Physicalle Indexed, Physically Tagged)
      • Einfach aber langsam wegen MMU-Aufrufen
    • VIVT (virtually Indexed, Virtually Tagged)
      • sehr schnell, aber Homonyme/Synonyme
    • VIPT (Virtually Indexed, Physically Tagged)
      • für schmale indices: Index der Virtuellen adresse stimmt mit phys. Adresse überein
      • in Frage kommendes Cache-Set kann parallel zum MMU Aufruf geladen werden

Speed-up vs. Security

Meltdown

  • CPU- Branch-Prediction Exploits
  • Idee:

    • Greife auf Kernel-Speicher zu (ohne berechtigung)
    • Das wirft logischerweise ne Exception
    • Während die Exception behandelt wird, wird allerdings auf den daten die bereits geholt wurden aufgrund der Branch-prediciton spekulativ weitergerechnet
    • Hat messbare effekte auf den Cache, die nicht zurückgesetzt werden
  • Auslesen der Informationen

    • Je nach Speicherinhalt wird eine andere Seite in den Cache geladen
    • anderer Prozess überprüft dann anhand von Zugriffszeiten welche Seite geladen wurde
    • Dadurch kann man rückschlüsse auf den Speicherinhalt erziehlen
    • Auslesegeschwindigkeit ~500 kB/s
  • Wat kann man dagegen machen?

    • Auf der OS-Ebene schon den speicher besser isolieren und keinen zugang zum Kernel zulassen
    • Mikrocode Updaten

Spectre V1

  • schläust sich in laufende Prozesse ein
  • kann dann auf den jeweiligen User-Space zugreifen

Spectre V2

  • Branch prediciton manipulativ trainieren (Context A)
  • Spekulative Code-execution ausnutzen, wie oben schon benannt (Context B)
    • denn oft wird nur ein teil der virtuellen speicheradresse für den Sprungcode verwendet
    • Und alle prozesse eines Kerns nutzen die selbe branch perediction engine
  • Hier sehen sie eine noch viel krassere Abbildung über den Branch-Prediciton Probleme
  • Gegenmaßnahmen:
    • SpectreV1:
      • Bounds check Bypass
        • absichtlich ungenaue zeitmessungen
      • Spectre V2
        • Branch Target Injection
          • Maßnamen auf OS-Ebene
          • Microcode-Updates
          • weitere sicherheitsmechanismen
          • allerdings auch hier wieder merkbare Leistungseinbußen

Parallelverarbeitung

Formen der Parallelität

  • Bis etwa 1985 haben wir das auf bitebene gemacht, also hatten wir kombinatorische addierer und Multiplizierer die immer alles 1zu1 verglichen haben, das wurde dann irgendwann unpraktisch, weil wir ja immer größere wörter in memory haben, was zu mehr und mehr pain geführt hat

  • Heutezutage machen wir das Auf instruktionsebene, also werden immer mehrere instruktionen gleichzeitig ausgeführt, anstelle von einigen operationen die "gleichzeitig" im ram gespeichert und immer sequenziell aisgeführt werden

    • Das kann allerdings ab > 4 Cores problematisch werden - was zu hindernissen bei effizienz und optimierungen führt
  • Als alternative dazu gibt es auch die paralelität auf Prozessorebene

    • nur damit sind beschläunigungen um den Faktor 50 und mehr möglich (allerdings is Amdahl's Law zu beachten)

Amdahl's Law

  • = Relative Größe des Programmanteils, welcher leider nicht massiv hip und multithreaded werden kann

  • = Anzahl der massiv coolen Kerne

  • Ideal wäre natürlich, wenn wir dat alles gleichmäßig aufteilen könnten (logischerweise) geht nur leider iwie nicht ganz so gut auf

  • Beschleunigung:

  • Sicke Grafik

Formen der Parallelverarbeitung auf prozessor-/ Rechnerebene(1)

Arrayprozessoren

  • Viele Prozessoren die gleich sind und eventuell lokalen speicher haben
  • Jeder dieser prozessoren hat seine eigene Steuereinheit
  • Und alle haben immer dieselbbe Instruktionsfolge
  • Bsps:
    • Illiac IV
    • CM-2

Wie machen wir dat sinnvoller? -> Wir machen die einzelnen Prozessoren in der Datenvararbeitung unabhängiger machen

Multiprozessoren:

  • bestehend aus mehreren (seperaten) Prozessoren und haben insgesamt einen (realtiv großen) hauptspeicher
  • die kommunizieren über den gemeinsamen speicher
  • Allerdings kann das zu performanceprobleben füren wenn viele prozessoren gleichzeitig auf den speicher zugreifen wollen

Multi-Core Prozessoren

  • Mehrere prozessoren auf einem chip die evtl gemeinsamen Cache und ggf. direkte Kommunikationsmöglichkeiten untereinander haben.

Koprozessoren

  • Sollen hauptsächlich den hauptprozessor entlasten
  • sind daher meisstens auf eine bestimte menge an spezialisierten Aufgaben Spezialisiert
  • Wie z.b. GPUs für alles das wofür man ne Grafikkarte braucht
    • Die dinger haben scheinbar ne große Ähnlichkeit zu Vektorprozessoren
  • Und dann gibts natürlich noch die absoluten chads: die mathemathischen Koprozessoren die unanfälliger für die nervigen Floating-Point issues sind.

Multicomputer

Man kanns natürlich maximal übertreiben und mehrere computer zusammenstrappen.

  • Dabei haben sie kein shared memory
  • Die prozessoren kommunizieren über kommunikationstunnel mit gewissen protokollen (nachrichten)
  • Dadurch wird das potentiell sehr komplex, dafür aber "beliebig" expandierbar

Beispiele für parallele Rechnerarchitekturen:

  • Symmetrische multiprozessoren (SMP)

massiv bessere Grafik

  • Dat is leider oft busbasiert und nutzt einen gemeinsamen Speicher
  • Das sind halt homogene Prozessoren
  • Dabei wird durch lokale Caches die Speicherlatenz verringert
  • leider können dabei diskrepanzen zwischen dem Cache und dem gemeinsamen Speicher entstehen, die zu komplikationen führen
  • Damit das passiert, müssen alle caches permanent "überwacht" werden, damit alle diskrepanzen frühzeitig behoben werden können

Cache Koeärenz

  • z.B. MESI-Protokoll
    • Modified:
      • Einzige, veränderte kopie
    • Exklusive:
      • Einzige unveränderte Kopie
    • Shared:
      • mehrere unveränderte kopien
    • Invalid:
      • ungültige kopien

Hier ein krasseres bild über das MESI Protokoll

  • Systeme mit Verbindungsnetzwerg und dezentralisiertem gemeinsamen Speicher:

Einfach die beste grafik der VL

  • Mit dieser Technik können sehr riesige Speichermodule realisiert werden.

  • System mit Dezentralisiertem Speicher mit Verbindungsnetzwerk und zusätzlichem lokalen cache

Boah die ist ja fast noch besser als die letzte grafik

  • Dann gibt es noch die Parallelen Rechnerarchitekturen die ein Verbindungsnetz und viele "kleinere" lokale speicher verwenden.
  • Hier ist der Prozessoroverhead hoch, weil jedes system eigenständig ist und immer alles an die jeweils anderen weitergeben muss.

Das ist ja trotzdem mega cool

  • Dabei ist der direkte Zugriff auf den lokalen speicher einer anderen maschine nicht möglich. Man muss alles anfragen
  • Dadurch, dass mehr anfragen / antworten gebraucht werden um dasselbe zu erreichen wie bei den "simpleren" systemen wird die "normale" usage komplizierter.
  • dafür ist dieses System allerdings pysikalisch skalierbarer, da jede einheit alleine agiert und durch das Verbindungsnetz die Aufgaben aufgeteilt werden können

Verbindungsstrukturen

  • Wie schnell die maschinen untereinander kommunizieren können ist ausschlaggebend für die allgemeine Performance, da durch übermäßiges Warten prozessorzeit verloren gehen könnte

  • Zudem ist zu beachten, dass nicht unbedingt jedes Problem direkt für Parallelisierung geeignet ist, da manche sachen so stark aufeinander aufbauen, dass mehr zeit verschwendet würde, wenn die prozessoren aufeinander warten, als wenn es einer in einem zug "alleine" machen würde

  • Um die Datenverarbeitung zu maximieren muss man zwischen diversen Strukturen wählen, welche alle andere Vorteile im hinsicht zu Kosten und Leistung haben

Modellierung von Verbindungen

  • Die Topologie eines Parallelrechners wird durch einen abstrakten Graphen dargestellt mit

    • Menge der Knoten, diese repräsentieren Prozessoren oder switches
    • menge der Kanten. Diese Repräsentieren die Verbindungen zwischen den einzelnen Knoten (Switches und CPUs)
  • {Länge des kürzesten Pfades von v nach w}

Bsp:

MAN IST DAS NEN MEGA KRASSES BILD NEY?

Stern

Andernfalls gibt es noch den stern als Verbindungsmodell, hierbei läuft alle Kommunikation durch einen Knotenpunkt

Mench Krasse sterngrafik

Ebenso kann mann einen Bus als Stern Modellieren, allerdings ist dann hierbei zu beachten, dass der Mittlere Punkt keine Logik verarbeiten kann. Leider gibt es dabei aber wieder denselben "Flaschenhals" (Bottleneck) wie beim Stern, denn es kann nie schneller Kommuniziert werden als der Mittlere Punkt / Das Switchboard Zulässt

Ring

Dann gibt es noch das Ring-Modell, was man sich wie einen Redekreis vorstellen kann. Hierbei kursiert ein sog. "Ring-Token" was wie der mystische "Gesprächsstein" fungiert, denn ein mitglied des Ringes darf nur dann etwas senden, wenn es diesen Token hat.

  • Durchmesser =
  • Grad =
  • | Verbindungen | =

CDDI / FDDI-Ring

[Copper / Fiber Distributed Data Interconnect]

Characteristika:

  • Besteht aus den komischen Sitzkreis-Ringen die oben beschrieben wurden
  • Allerdings hat das ding zwei davon, die gegenläufig sind, also in die jeweils andere Richtung voneinander Laufen.
    • Dadurch wird die Fehlertoleranz erhöht

BOAH KRASS EINFACH kreise

MESH ("torusähnliches Gitter")

MESH

  • wird z.b. bei MPPs verwendet
  • Durchmesser =
  • Grad =
  • | Verbindungen | =

HYPERCUBE (-Dimensionaler Würfel)

MAN DAS IST NEN HYPENDER CUBE ODER

  • dieses Modell ist bei einer hohen anzahl von Prozessoren nicht verwendbar, da der grad zu schnell ansteigt.
  • Im Bild haben wir z.b. einen 3-Dimensionalen würfel mit 8 ecken, also Knoten. Sprich:
    • (Dimension)
    • (Nodes)
  • Allgemein:
  • Durchmesser =
  • | Verbindungen | =

Cube Connected Cycle (CCC)

MAN NEN WÜRFEL DER WÜRFELIGER IST ODER WIE

  • Prozessoren =
  • Durchmesser =
  • Grad = 3
  • | Verbindungen | =

Beispiele für parallele Rechnerarchitekturen

  • Die "heute" gängigen Multi-Core Architekturen
    • Dual Core:
      • Intel Core 2 Duo
      • AMD Athlon X2
    • Quad Core:
      • AMD Phenom II X4
      • Intel Core 2 Quad
      • Intel Core i7
    • Octa Cores (Und darüber hinaus):
      • AMD Ryzen 9 (bis zu 16 Kerne + 32 Threads)
      • Intel Core i9 (bis zu 18 Kernen + 36 Threads)

Beispiel AMD Phenom II X4 (2009)

  • Dat teil hat:
    • 4 Identische Kerne
    • Cache:
      • L1: 64 KB / Kern
      • L2: 512KB / Kern
      • L3: 6144KB Insgesamt
    • 45 nm
    • 2,8 - 3 GHz

Beispiel: Cell Chip

  • Cell Chip
    • (IBM, Sony, Toshiba)
    • 234 Millionen Transistoren
    • 256 Gigaflops (Single prec.)
    • CPU: 1 x 64-Bit-Power-PC
    • 8 x SPE (Synergistic Processing Element)

Grafikprozessor

KRASSES BILD

  • die Grafikpipeline beschreibt die Schritte in denen eine 3D.Szene auf dem Bildschirm gerendert wird.
  • Ein Grafikprozessor setzt diese Pipeline direkt in Hardware um

Aber wie funktioniert das eigentlich?

  • Bildpunkte werden durch Vektoren dargestellt
  • Eine GPU ist dafür ausgelegt, sehr viele Bildpunkt-Operationen gleichzeitig auszuführen
  • Ebenso ist die GPU auf alles ausgelegt, was in der Grafikverabreitung vorkommt wie z.b.Skalarprodukt, Logarithmen etc. Hardwareseitig optimiert

Grafik-2 YEAH KRASS ODER

Die Schritte in der Grafikpipeline:

  • Projektion von 3D Auf 2D

    • Beispiel: Zentralprojektion für einen Punkt und das Projektionszentrum ergibt sich die Projektion durch:

    • MEGA SICKE GRAFIK

    • Die Operation wird sehr häufig verwendet, daher wird sie durch einen Multiplikationsakkumulator (MAC) direkt in Hardware realisiert

  • Matrix

  • Wir betrachten, mal wieder, eine extremst veraltete Grafikkarte als Beispiel:

AMD Radeon RX 580

  • GPU "Polars20"
  • spezielle Funktionseinheiten:
    • 2304 Shading Units (Stream-Prozessoren)
    • 36 Compute Units
    • 144 Textureinheiten
  • 1,257 GHz
  • 6200 Gflops
  • 2 x 1024KB L2-Cache

Klassifikationsmerkmale bei Parallelen Rechnerarchitekturen

Speichermodell:

  • Nicht verteilter Speicher, gemeinsamer Adressraum
  • verteilter Speicher, gemeinsamer Adressraum
  • verteilter Speicher, getrennte Adressräume

Homogenität der Prozessoren

  • homogene Parallelrechner: alle prozessoren sind gleich
  • heterogene Parallelrechner: Prozessoren dürfen sich hardwaremäßig unterscheiden

Hirachie zwischen den Prozessoren

  • symmetrische Parallelrechner: Die Prozessoren sind bzgl ihrer Rolle im gesamtsystem untereinander Austauschbar.
  • nichtsymmetrische Parallelrechner: es gibt masters und Slaves

Eigenständigkeit der Prozesoren:

  • lose gekoppelter Parallelrechner: Netzwerk von eigenständigen Rechnern
  • eng gekoppete Parakkekrechner: physikalisch ein Rechner

Klassifikation nach Flynn [1966]

  • SISD (Single Instruction stream, Single Data stream)
    • Eine Instruktion betrachtet immer ein Datenteil isoliert und alleine
    • So lernen wir Programmierne zu Beginn
  • SIMD (Single Instruction stream, Multiple Data streams)
    • Eine Instruktion behandelt direkt mehrere Datenteile
    • Dieses Modell findet sich in modernen GPUs wieder
    • Beispielsweise loopen wir über eine Liste von elementen und rechnen alle + 1
  • MISD (Multpiple Instruction stream, Single Data Stream)
    • Wenn mehrere Instruktionen verwendet werden um ein Datenteil zu editieren.
    • z.b. wenn wir 3 verschiedene Rechenoperationen hintereinander auf ein element ausführen
  • MIMD (Multiple Instruction streams, Multiple Data streams)
    • Basically "true" multitasking. Mehrere unabhängige Systeme interagieren mit mehreren unabhängigen Datensätzen

Codierung (Von Zeichen)

Motivation?

  • Ein Rechner kann traditionell leider keine
    • Zeichen verarbeoten
    • mit zahlen rechnen
    • Bilder / Grafik darstellen
  • Wir können zwar theoretisch algorithmen bauen, die diese sachen implementieren, allerdings müssen wir diese algorithmen in ein vom Computer verstandenes Binärformat umwandeln (Kompillieren)

ASCII

Wir reden erstmal über Primitive Dinge: also T-Scr.. ich meine Ascii (American Standard Code for Information Interchange)

  • Mit Ascii kann man (sehr begrenzte) Zeichen darstellen und deswegen hat man angefangen Alternativen zu bauen

  • Man kann mit Ascii zudem nur lateinische Buchstaben darstellen, und auch nur die, die im englischen sehr aktiv genutz werden, da man aufgrund von bandbreitenlimitierung ein (weirdes) 7-Bit format gewählt hat.

  • Dann hatten wir eine radikal bessere idee als Ascii: Unicode

Unicode

  • Auch bekannt als UTF-8

  • 8 weil ein zeichen bis zu 8 bit lang sein kann.

  • Zudem hat Unicode auch support für Ascii, indem man nur den ersten byte der sequenzfolge nutzt. Da ascii praktischerweise in einen byte passt, ist damit das gesamte Ascii spektrum auch abgebildet

  • Wenn ein Zeichen nicht Ascii codiert ist, dann ist es zwischen 2 und 4 Byte lang

Definition: Code

Das werdet ihr in Info3 wieder sehen :P

  • Sei ein endliches Alphabet der größe
  • Die Menge oder heißt Code falls injektiiv ist.
  • Die menge
  • Ein Code heißt Code fester Länge
  • Beobachtung: Für einen Code fester Länge gilt .

Probleme bei Binär-encoding:

  • Daten können in der Transmission beschädigt werden, weswegen dann Interpätationsschwierigkeiten aufkommen

Was kann alles Passieren?

  • Bitstellen können Geflipped werden (Der mysteriöse Bitflip)

  • Die distanz zwischen zwei bitfolgen könnte sich verändern, dass dazwischen mehr 0en stehen als geplant.

  • Ein Übertragungsfehler heisst einfach, wenn gilt.

  • Hier ein beispiel wie die funktion funktioniert:

  • Wat bei der krassen Fehlerhaft übertragung helfen könnte wäre eine FEHLERERKENNUNG (BOAH KRASS)

Fehlererkennender Code

Sei ein code fester Länge von

  • Der kürzeste Abstand
  • zwischen zwei Codewörtern wird Distanz des Codes genannt. Der code heisst -fehlererkenned, wenn mder Empfänger in jedem fall entscheiden kann, ob ein gesendetes Codewort durch flippen von Bits verfälscht wurde.

Lemma

Ein Code von fester Länge ist genau dann -fehlererkennend, wenn gilt.

  • Wir erkennen Fehlerhaften code indem wir parity-checks (Paritätstests) durchführen, und prüfen, ob sich die beiden bitfolgen an einer oder mehreren Stellen unterscheiden

  • Man kann z.b. einen Parity-Bit (Paritätsbit) an eine bitsequenz hängen um mit dem abschliesenden bit überprüfen zu können, ob die datenübertragung erfolgreich war.

MASSIV COOLE GRAFIK

Beweis Lemma [Fehlerkorrektur]

Idee

  • Sei . Da -Fehlererkennend ist, muss gelten.
  • Wir haben zwei Codewörter , die sich an genau Stellen unterscheiden. Die Bitfolge die man erhält, wenn dieser stellen in geflippt werden, underscheidet sich in Bit von
  • Ist dann und es kann nicht mehr eindeutig bestimmt werden, zu welchem Codewort korrigiert werden muss
  • Ist , unterscheidet sich von an mehr als Stellen. Gleiches gilt dann auch für alle anderen Codewörter und bitfolgen die sich von an höchstens stellen unterscheiden. Also ist eine eindeutige Korrektur zu c(a_j) möglich

1-Fehlerkorrigierender Code

Um 1 Fehler Korrigieren zu können benötigt man mindestens

Hamming code

Idee:

  • Wir könnten normale Bitsequenzen um Prüfbits erweitern
  • Die Prüfbits müssten dann so belegt werden, dass jedes Codewort verschiedene Parity-checks bestehen kann
  • Genau die bitstellen (also 1, 2, 4, 8,...) sind Prüfbits
  • Das prüfbit an der Stelle muss so gewählt werden, dass alle Bitdarstellungen die an der -ten Stelle eine 1 haben, den Parity-check bestehen

Hamming Code an einem Beispiel

  • Uncodiertes Zeichen:

  • Wie sieht nun der Hamming-Code dieses Zeichen aus?

  • Der Code wird auf 21 Bitstellen verlängert

  • Die zweierpotenz-Bitstellen werden als Überprüfungsbits benutzt 0 1110 _ 101 0000 _ 111 _ 1 _ _
    wobei Bitstelle die Bitstellen Überprüft deren Binärdarstellungen an der -Ten Stelle eine 1 haben. Die belegung der Bitstelle 2^j ergibt sich jeweils aus der Summe der (belegungen der) überprüften Bistellen modulo 2

Hamming Code Berechnen

  • Wie viele bits brauchen wir für die Parity?
    • Um einen Hamming code zu berechnen schauen wir uns die datenlänge von dem ding, was wir senden wollen an.
    • die menge an Paritätsstellen ist immer der wo (aufgerundet)
    • Das macht bei 11-bit also
  • Stellen bestimmen
    • Jetzt schauen wir uns die bit-nachricht an, und stellen an die indizes die mit dem Wert einer zweierpotenz übereinstimmen eine Leere stelle, die wir mit der Parity-Zahl füllen werden.
    • Bei unserer 11-Bit langen Datei sind das die Indizes 1, 2, 4 und 8.
  • Parity Berechnen
    • Jetzt kommen wir an den lustigen Teil des ganzen
    • Wir schauen uns die binärrepresenationen der Indizes der 1en und 0en an.
    • Sprich, wenn wir eine Zahl mit 15 Stellen haben (wie bei unserer ursprünglich 11-bit Langen Datei) ist das 1111, 1110, 1101 etc. you get the point.
    • Wir schauen uns dann alle Zahlen an, deren Index eine 1 ganz am ende hat.
    • Hier bemerken wir, dass eine unserer Parity Zahlen auch eine 1 am ende hat, nämlich die 1 (oHhHHHHh).
    • Das ist absichtlich, denn wir werden diese Zahl nutzen um die Menge an 1en an den stellen die wir gerade betrachten gerade zu machen.
    • wenn wir also an index 7 und 3 eine 1 stehen haben, und sonst nirgendwo schreiben wir bei index 1 eine 0 hin, da wir ja schon 2 1en haben und 2 ist gerade.
    • ebenso, würden wir wenn wir bei index 9, 7 und 3 1en hätten eine 1 an den index 1 schreiben, damit wir am ende 4 1en in der Gruppe hätten. (Damit unsere Zahl wieder gerade wäre)
    • Das wiederholen wir jetzt mit allen zahlen die an der 2. stelle des Index eine 1 haben usw.
    • Am Ende sollten dann alle lücken gefüllt sein.

Bussysteme

Memory - I/O Busse

  • Wat das eig?
  • ein Elektronisches leitungsbündel in einem digitalen Rechner
  • Kommunikationsmedium auf dem daten fließen können
    • Zwischen CPU und Hauptspeicher
    • zwischen CPU und I/O Geräten
    • zwischen Hauptspeicher und I/O-Geräten
  • normierte Stecker
  • standarisierte Interpretation der einzelnen Leitungen

Heutige Bussysteme

  • USB
  • SATA
  • Thunderbolt
  • AGP
  • PCI-E

Morgige?

  • Thunderbolt?
  • USB 4?

Selbstaktende Codierung

  • Problem:

    • Nur eine Leitung bei srielle Übertragung
    • fehlende Synchronisierung / kein seperates Takt signal
    • Wann beginnen einzelne bits? -> Es muss ein takt aus dem datensignal ausgelesen werden können
  • Keine Steuersignalleitungen
    • Wo sind die blockgrenzen? was sind bus befehle bzw. daten?
      • Steuersignale sind bestimmte bitfolgen
  • Manchester Code:

    • übertrage 2 Bits pro Datenbit
    • Übergang in Taktmitte codiert Informatin
      • fallende und steigende Flanke
    • andere Übergänge: Takt-Rückgewinnung
    • Hier eine tolle grafik die manachestercode zeigt
  • -Codes

    • Z.b. bei PCI-E, SATA, USB (ab 3.0)
    • codiere Datenbits in Übertragungsbit (früher heute: )
    • ~4 Möglichkeiten für jede -Bitfolge erlaubt primitive Fehlerkorrektur
    • einige -Bitfolgen repräsentieren Steuersignale
      • für : Zwölf besondere Bitfolgen
      • für : Codiert über die ersten zwei bit ("Präambel")
        • "01": Nutzerdaten
        • "10": Steuer-/Nutzerdaten
        • "00"/"11": Nicht erlaubt, Fehler!

Prinzipieller ablauf einer Kommunkation

Datentransfer vom Hauptspeicher zu einer Festplatte

  1. Der Prozessor fragt daten an
  2. Liest die daten vom Ram in den cache
  3. Fragt an ob er daten schreiben kann

Datentransfer von einer Festplatte zum Hauptspeicher

  1. Prozessor fragt daten an
  2. Prozessor sagt der festplatte was er will
  3. Festplatte schreibt das ind en ram

Direct memory Access

  • Da ja leider die datenübertragung über den Prozessor den prozessor unnötig belastet kann ein eigenständiger DMA-Controller eingeführt werden
  • Dieser kann dann selbstständig daten aus dem sekundären (langzeit) Speicher in den RAM schieben wenn der CPU sie verlangt
  • Dadurch wird der Prozessor weniger Belastet
  • und es gibt unterm Strich einen höheren Datendurchsatz

Optionen eines Busses

SchnellerBilliger
Seperate Adress- und DatenleitungenMultiplexen von Adress- und Datenleitungen
BreiterSchmaler
Mehrere Busmaster erlaubt (Erfordert Schiedsrichter)Nur ein Busmaster
synchrone Übertragungasynchrone Übertragung

Zu guter letzt: Vielen dank fürs Lesen! Ich hoffe ich konnte ein wenig behilflich sein. VG, Tobi :)