Rechnerstrukturen Michael Engel und Peter Marwedel TU Dortmund, Fakultät für Informatik SS 2013 Hinweis: Folien a. d. Basis von Materialien von Gernot Fink und Thomas Jansen Boole. Fkt. 25. April 2013 1 Boolesche Funktionen und Schaltnetze Rechner-Arithmetik Addition (Wiederholung) Multiplikation Wallace-Tree Subtraktion Addition negativer Zahlen Gleitkommazahlen-Arithmetik Multiplikation von Gleitkommazahlen Addition von Gleitkommazahlen Boole. Fkt. Addition von Binärzahlen Beobachtungen zu den Überträgen ◮ ◮ ◮ ◮ 1 + 1“ erzeugt einen Übertrag ” 0 + 0“ eliminiert einen vorhandenen Übertrag ” 0 + 1“ und 1 + 0“ reichen einen vorhandenen Übertrag weiter ” ” Übertrag ist höchstens 1 Kann man Addition als boolesche Funktion ausdrücken? x y 0 0 fHA : {0, 1}2 → {0, 1}2 mit 0 1 1 0 1 1 realisiert Addition mit Summenbit s Beobachtung Boole. Fkt. c =x ∧y c s 0 0 0 1 0 1 1 0 und Übertrag c (Carry) s =x ⊕y Halbaddierer c =x ∧y x y s =x ⊕y =1 s & c Größe 2 Tiefe 1 x 0 2 2 Drückt fHA : {0, 1} → {0, 1} mit 0 1 1 wirklich Addition aus? y 0 1 0 1 c 0 0 0 1 s 0 1 1 0 Beobachtung: Nur für isolierte Ziffern, vorheriger Übertrag fehlt! Boole. Fkt. Realisierung von Addition als boolesche Funktion calt x y 0 0 0 0 0 1 0 1 0 3 2 fVA : {0, 1} → {0, 1} mit 0 1 1 1 0 0 1 0 1 1 1 0 1 1 1 realisiert Addition mit Summenbit s und Beobachtung Beobachtung aber Boole. Fkt. c s 0 0 0 1 0 1 1 0 0 1 1 0 1 0 1 1 Übertrag c (Carry) s = 1 ⇔ Anzahl der Einsen ungerade s = calt ⊕ x ⊕ y c = 1 ⇔ Anzahl Einsen ≥ 2 direkte Realisierung c = x y ∨ x calt ∨ y calt für Realisierung im Schaltnetz Schaltnetz Volladdierer s = x ⊕ y ⊕ calt c = calt (x ⊕ y ) ∨ x y x y calt =1 s =1 & ≥1 & Größe 5, Tiefe 3 Boole. Fkt. c Realisierung Addition x0 y0 x1 y1 x2 y2 .. . s0 s1 HA VA1 s2 VA2 ··· .. . xn−1 yn−1 Größe 2 + (n − 1) · 5 = 5n − 3 Tiefe 1 + (n − 1) · 3 = 3n − 2 Boole. Fkt. .. . .. . sn−1 ··· VAn−1 sn Ergebnis: Ripple-Carry Addierer ◮ Realisierung Addition von natürlichen Zahlen“ ” sehr gut strukturiert ◮ Größe 5n − 3 ← sehr klein ◮ Tiefe 3n − 2 ← viel zu tief Warum ist unser Schaltnetz so tief? Überträge brauchen sehr lange offensichtlich Verbesserungsidee Überträge früher berechnen Erinnerung Struktureinsicht (xi , yi ) = (1, 1) (xi , yi ) = (0, 0) (xi , yi ) ∈ {(0, 1), (1, 0)} Boole. Fkt. generiert Übertrag eliminiert Übertrag reicht Übertrag weiter Multiplikation direkt mit Binärzahlen. . . 1 0 1 also 1 1 0 0 1 0 0 1 1 0 1 1 1 0 1 0 1 0 0 · 1 1 1 0 1 1 0 1 0 1 1 0 0 0 1 0 1 0 0 1 1 1 1 1 0 1 1 0 0 1 0 0 0 1 1 0 0 Multiplizieren heißt ◮ Nullen passend schreiben ◮ Zahlen passend verschoben kopieren ◮ viele Zahlen addieren Boole. Fkt. 0 0 0 Multiplikation als Schaltnetz Multiplikation ist ◮ Nullen passend schreiben ◮ Zahlen passend verschoben kopieren ◮ viele Zahlen addieren klar Boole. Fkt. Nullen schreiben einfach und kostenlos, Zahlen verschieben und kopieren einfach und kostenlos, viele Zahlen addieren nicht ganz so einfach Addition vieler Zahlen klar Wir haben Addierer für die Addition zweier Zahlen. Wie addieren wir damit n Zahlen? erster Ansatz einfach nacheinander m1 m2 m3 m4 m5 · · · mn Tiefe (n − 1) · Tiefe(+) Schrecklich! + klar sehr naiv + merken + in Schaltnetzen niemals alles nacheinander + Was geht gleichzeitig? Boole. Fkt. .. . + Addition von n Zahlen besserer Ansatz paarweise addieren m1 m2 m3 m4 m5 m6 m7 m8 + + + + + + + Anzahl Addierer = n2 + n4 + · · · 1 ≈ n Gesamtgröße ≈ n · Größe(+) Tiefe also auf i -ter Ebene 2log2 (n)−i Addierer ≈ log2 (n) Ebenen Gesamttiefe ≈ log2 (n) · 2 log2 (n) = 2 log2 (n)2 Geht es vielleicht noch schneller? Boole. Fkt. Addition von n Zahlen noch schneller (triviale) Beobachtung ◮ ◮ zentral für uns gleiche Summe weniger Zahlen (verrückte?) Idee Addition ersetzt zwei Zahlen durch eine Zahl gleicher Summe Korrektheit Fortschritt“ ” Vielleicht ist es einfacher, drei Zahlen zu ersetzen durch zwei Zahlen gleicher Summe? klar immer noch gleiche Summe ” aber 3 2“ statt 2 1“ ” ” weniger Fortschritt Ist das schlimm? Boole. Fkt. Korrektheit Wallace-Tree m1 m2 m3 m4 CSA m5 m6 m7 CSA CSA CSA CSA CSA Carry Save Adder (≈ log3/2 (n) Ebenen) klar nur sinnvoll, wenn CSA viel flacher als Addierer CSA CSA CSA + Boole. Fkt. m8 m9 m10 m11 CSA m12 Carry Save Adder gesucht Zahlen a, b mit a + b = x + y + z Beobachtung für x, y , z ∈ {0, 1} schon bekannt x + y + z = 2 · u + v (Volladdierer) Beobachtung Es genügt, das parallel für alle Stellen zu tun. + + u3 + Boole. Fkt. x3 y3 z3 (2u3 + v3 ) u2 v3 x2 y2 z2 (2u2 + v2 ) u1 v2 x1 y1 z1 (2u1 + v1 ) u0 v1 x0 y0 z0 (2u0 + v0 ) v0 Korrektheit der CSA-Realisierung aus Volladdierer x +y +z xi + yi + zi = 2ui + vi = = n−1 X xi · 2i i =0 n−1 X ! + n−1 X i =0 (xi + yi + zi ) · 2i i =0 = = n−1 X (2ui + vi ) · 2i i =0 n−1 X i =0 Boole. Fkt. i +1 ui · 2 yi · 2i ! + ! + i ! i =0 n−1 X i =0 vi · 2 n−1 X zi · 2i ! Multiplikation mit Wallace-Tree klar für drei n-Bit-Zahlen reichen n Volladdierer also Größe Tiefe 5n 3 Gesamtgröße ∼ n2 Gesamttiefe ≈ 3 · log3/2 (n) + 2 log2 (n) ≈ 7,13 log2 (n) | {z } | {z } Wallace-Tree Fazit Boole. Fkt. Addierer Multiplikation wesentlich teurer“ als Addition, ” aber nicht wesentlich langsamer! Subtraktion Beobachtung Niemand muss subtrahieren! Begründung also Idee Statt x − y“ einfach x + (−y )“ rechnen! ” ” Ersetze Subtraktion durch 1. Vorzeichenwechsel 2. Addition einer eventuell negativen Zahl noch zu untersuchen 1. Wie schwierig ist der Vorzeichenwechsel? 2. Wie funktioniert die Addition von negativen Zahlen? Boole. Fkt. Vorzeichenwechsel Repräsentation Vorzeichen-Betrag Einerkomplement Zweierkomplement Exzess Beobachtung also Boole. Fkt. Vorgehen Vorzeichen-Bit invertieren alle Bits invertieren alle Bits invertieren, 1 addieren Subtraktion von 2y Kommentar sehr einfach einfach machbar schwierig für Exzessdarstellung funktioniert Addierer selbst bei positiven Zahlen nicht x + y“ (b + x) + (b + y ) = (b + x + y )+b ” Exzessdarstellung fürs Rechnen weitgehend ungeeignet, nur günstig für Vergleiche Addition negativer Zahlen klar unsere Schaltnetze für die Addition (Schulmethode, Carry-Look-Ahead) sind für Betragszahlen entworfen Müssen wir für negative Zahlen komplett neu entwerfen? klar Das hängt von der Repräsentation ab. Exzessdarstellung Betrachten wir gar nicht, weil wir damit nicht einmal addieren können. Vorzeichen-Betrag positive und negative fast gleich dargestellt, darum neuer Schaltnetzentwurf erforderlich Boole. Fkt. Addition negativer Zahlen im Einerkomplement auf dieser und nächster Folie y ist Komplement von y ◮ Notation ◮ Wir wechseln frei zwischen Zahlen und ihren Repräsentationen. ◮ feste Darstellungslänge ℓ Beobachtung y + y = 2ℓ − 1 ⇔ y = 2ℓ − 1 − y Rechne x − y = x + (−y ) = x + y = x + 2ℓ − 1 − y = 2ℓ + (x − y ) − 1 Wichtig also Boole. Fkt. Darstellungslänge ⇒ 2ℓ passt nicht“ (Überlauf) ” Überlauf ignorieren ⇒ noch 1 addieren korrekt Addition negativer Zahlen im Zweierkomplement Beobachtung y + y = 2ℓ − 1 ⇔ y = 2ℓ − 1 − y Rechne x − y = x + (−y ) = x + y + 1 = x + 2ℓ − 1 − y + 1 = 2ℓ + (x − y ) wichtig also Darstellungslänge ⇒ 2ℓ passt nicht“ (Überlauf) ” Überlauf ignorieren ⇒ korrekt also Addierer rechnet richtig auch für negative Zahlen Zweierkomplement verbreitetste Darstellung ganzer Zahlen Boole. Fkt. Überträge bei Addition im Zweierkomplement Wann ist das Ergebnis korrekt und wann nicht darstellbar? 1. Addition zweier positiver Zahlen klar Ergebnis positiv Beobachtung kein Überlauf möglich also Ergebnis korrekt, wenn positiv 2. Addition einer positiven und einer negativen Zahl klar Ergebnis kleiner als größte darstellbare Zahl klar Ergebnis größer als kleinste darstellbare Zahl also Ergebnis immer korrekt 3. Addition zweier negativer Zahlen gesehen Überlauf entsteht ( ignorieren) klar Ergebnis negativ also Ergebnis korrekt, wenn negativ Boole. Fkt. Gleitkommazahlen-Arithmetik Darstellung gemäß IEEE 754-1985 x = (−1)sx · mx · 2ex y = (−1)sy · my · 2ey Vorzeichenbit Mantisse (Binärdarstellung, inklusive impliziter 1) Exponent (Exzessdarstellung, b = 2ℓ−1 − 1) s m e Ergebnis z = (−1)sz · mz · 2ez Vereinfachung Wir ignorieren das Runden. Aber : Wichtiger Teil des IEEE 754 Standards! Weitere Details z.B. in: David Goldberg (1991): What every computer scientist should know about floating-point arithmetic. ACM Computing Serveys 23(1):5–48. Boole. Fkt. Multiplikation von Gleitkommazahlen x = (−1)sx · mx · 2ex y = (−1)sy · my · 2ey z =x ·y = (−1)sz · mz · 2ez Beobachtung z = (−1)sx ⊕sy · (mx · my ) · 2ex +ey also 1. sz := sx ⊕ sy (trivial) 2. mz := mx · my (Multiplikation von Betragszahlen wie gesehen, implizite Einsen nicht vergessen!) 3. ez := ex + ey (Addition, wegen Exzessdarstellung ex + ey − b berechnen) Boole. Fkt. Beispiel Multiplikation Gleitkommazahlen x 1 1000 0101 101 0000 0000 0000 0000 0000 y 1 1000 0111 110 1000 0000 0000 0000 0000 Vorzeichen sz = 1 ⊕ 1 = 0 Exponent Bias ist 2ℓ−1 − 1 = (1000 0000)2 − 1 (1000 0111)2 − ((1000 0000)2 − 1) = (111)2 + 1 = (1000)2 (1000 0101)2 + (1000)2 = (1000 1101)2 (1000 1101)2 ist vorläufiger Exponent Mantisse 1, 1 0 1 · 1, 1 1 0 1 1 1 0 1 Normalisieren: 1 1 0 1 Komma 1 Stelle nach links 1 1 0 1 Exponent zum Ausgleich +1 0 0 0 0 implizite Eins streichen + 1 1 0 1 1 0, 1 1 1 1 0 0 1 z Boole. Fkt. 0 1000 1110 011 1100 1000 0000 0000 0000 Addition von Gleitkommazahlen x = (−1)sx · mx · 2ex y = (−1)sy · my · 2ey z =x +y = (−1)sz · mz · 2ez Beobachtung einfach, wenn ex = ey dann m1 · 2e + m2 · 2e = (m1 + m2 ) · 2e Plan 1. Ergebnis wird so ähnlich“ wie Zahl mit größerem Exponenten, ” darum Mantisse der Zahl mit kleinerem Exponenten anpassen 2. Mantissen auf jeden Fall addieren, bei unterschiedlichen Vorzeichen dazu eine Mantisse negieren (Zweierkomplement) 3. anschließend normalisieren Boole. Fkt. Algorithmus zur Addition 1. Falls ex < ey , dann x und y komplett vertauschen. 2. Falls Vorzeichen ungleich, dann Vorzeichen von sy invertieren und Übergang von y zu −y im Zweierkomplement ( y + 1“). sz := sx ” 3. Mantisse my um ex − ey Stellen nach rechts verschieben (Exponenten virtuell“ jetzt angeglichen) ” Achtung Kann zum “Verlust” signifikanter Stellen führen! 4. mz := mx + my Falls ex = ey , Vorzeichenwechsel möglich. Dann sz invertieren. 5. ez := ex . Ergebnis normalisieren Achtung klar Boole. Fkt. Bei Mantissen an implizite Einsen denken! Keine separate Subtraktion erforderlich. Vorzeichenwechsel trivial. Addition negativer Zahlen enthalten durch Zweierkomplement. Beispiel Addition Gleitkommazahlen 1 1001 0101 111 0010 0000 0000 0000 1 1001 0100 110 0001 1000 0000 0000 ex > ey , Vorzeichen gleich, also zunächst nur sz := 1 0000 0000 x y Mantisse my um ex − ey = 1 Stelle 0,111000011 1, 1 + 0, 1 Mantissen addieren 1 0, 1 Normalisieren nach rechts verschieben 1 1 1 1 1 0 ◮ Komma um 1 Stelle nach links verschieben ◮ Exponent um 1 vergrößern z Boole. Fkt. 1 1001 0110 011 0 0 0 0 0 0 1 0 1 0 0 1 1 1 1 1,0110001011 1001 0110 0001 0110 0000 0000 0000 Noch ein Beispiel zur Addition 1 0 x y 1000 1000 0101 0100 010 101 0000 1010 0000 0000 0000 0000 ex > ey weil sx 6= sy sy invertieren Vorzeichenwechsel bei my in Zweierkomplementdarstellung Boole. Fkt. 1 0 1 1000 1000 1000 0000 0000 √ klar x aus wird y 0000 0000 0101 0100 0100 1 01 10 , , , 010 101 010 0000 1010 0110 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 Noch ein Beispiel zur Addition (2) x 1 1000 0101 1 , 010 0000 0000 y 1 1000 0100 10 , 010 0110 0000 jetzt ey an ex anpassen, my verschieben 1 1 1 x y z 1000 1000 1000 1 1000 Normalisieren z Boole. Fkt. 1 1000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 überfließende“ 1 einfach ignorieren ” 0101 0 , 011 0011 0000 0000 0000 0000 0101 0101 0101 Erinnerung z 0000 0000 1 11 100 , , , 010 001 011 0000 0011 0011 0000 0000 0000 Komma um zwei Stellen nach rechts verschieben Exponent zum Ausgleich um zwei verkleinern 0011 100 1100 0000 0000 0000 0000 Fehlerquellen bei der Gleitkommaarithmetik ◮ Rundung, wenn Berechnungsergebnis zur korrekten Darstellung mehr signifikante Bits (d.h. i.d. Mantisse) erfordert als verfügbar (kann bei Multiplikation und Addition auftreten) ◮ “Verlust” niederwertiger Bits durch Angleich der Exponenten während der Addition Worst Case: x ≫ y und y 6= 0 aber x + y = x Und nicht zu vergessen: Darstellung nur einer extrem kleinen Auswahl der rationalen Zahlen möglich, variiert mit der Größenordnung der repräsentierten Zahlen! Boole. Fkt. Probleme bei der Addition: Ein Szenario Gegeben: Folge von n Gleitkommazahlen [xi ] mit 0 ≤ i ≤ n (z.B. gespeichert in einem Feld/Array x[i]) Aufgabe: Berechne Summe S ... möglichst exakt (d.h. mit den Möglichkeiten der Gleitkommaarithmetik) Naive Lösung: Direkte Summation, d.h. berechne: 0 n−1 P P xi xi oder lieber S ↓ = S↑ = i =0 i =n−1 Theorie/Intuition: Beide Summationen liefern dasselbe Ergebnis! Praxis: S ↑ und S ↓ sind i.a. nicht gleich! −→ Beispielprogramm (in C) Mögliche Abhilfe: Erhöhung der Genauigkeit (i.d.R. schwierig) ... oder “schlauere” Berechnung ;-) Boole. Fkt. Fehlerreduktion: Kahan-Summation Algorithmus zur numerisch stabileren Berechnung von S = n−1 P xi : i =0 S = 0; E = 0; for i = 0 Y Z E S } /* Summe */ /* geschaetzter Fehler */ to n-1 { = x[i] - E; /* bish. Fehler beruecksichtigen * = S + Y; /* neues Summationsergebnis */ = (Z - S) - Y; /* neue Fehlerschaetzung */ = Z; −→ Boole. Fkt. Beispielprogramm (in C) Fehlerreduktion: Kahan-Summation (2) Veranschaulichung des fehlerkompensierenden Berechnungsablaufs: Z S Yh + Yl − Yh Z − E= Boole. Fkt. S Yh Yl −Yl