Numerische Fehlerkorrektur und - STS

Transcription

Numerische Fehlerkorrektur und - STS
Bachelorarbeit
Sebastian Elm
Numerische Fehlerkorrektur und
Programmflusskontrolle zur Behandlung
von Soft Errors
29. Juli 2014
betreut durch:
Prof. Dr. Sibylle Schupp
Hamburg University of Technology (TUHH)
Technische Universität Hamburg-Harburg
Institute for Software Systems
21073 Hamburg
Inhaltsverzeichnis
Inhaltsverzeichnis
Eidesstattliche Erklärung
v
1. Einleitung
1
2. Soft Errors
3
3. Lösen eines linearen Gleichungssystems
3.1. Anwendungsbezug . . . . . . . . . . . . . .
3.2. Verfahren der konjugierten Gradienten . . .
3.2.1. Minimierung der quadratischen Form
3.2.2. Berechnung der Lösung . . . . . . .
3.3. Algorithmus . . . . . . . . . . . . . . . . . .
3.4. Implementierung . . . . . . . . . . . . . . .
3.4.1. Datentyp Vektor . . . . . . . . . . .
3.4.2. Matrix- und Vektoroperationen . . .
3.5. Betrachtung der Effizienz . . . . . . . . . .
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
5
. 5
. 5
. 5
. 6
. 7
. 8
. 8
. 9
. 10
4. Error Correction Code
11
4.1. Realisierung der ECC . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 11
4.2. Betrachtung der Effizienz . . . . . . . . . . . . . . . . . . . . . . . . . . . 11
5. Programmflusskontrolle
5.1. Defensive Programming . . . . . .
5.2. Anwendung zur Korrektur von Soft
5.3. Implementierung . . . . . . . . . .
5.4. Betrachtung der Effizienz . . . . .
. . . .
Errors
. . . .
. . . .
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
13
13
13
14
15
6. Numerische Fehlerkorrektur
17
6.1. Algorithmus . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 17
6.2. Betrachtung der Effizienz . . . . . . . . . . . . . . . . . . . . . . . . . . . 18
7. Software-Tests
19
7.1. Äquivalenzklassen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 19
7.2. Mehrfachbedingungsüberdeckung . . . . . . . . . . . . . . . . . . . . . . . 20
8. Implementierung eines Tests unter FITIn
8.1. Annotation des Quellcodes . . . . . . . . . . . . .
8.2. Steuerung mittels eines Lua-Skriptes . . . . . . .
8.3. Injektion eines Soft Errors in Kontrollstrukturen
8.4. Testautomatisierung . . . . . . . . . . . . . . . .
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
23
23
24
25
26
iii
Inhaltsverzeichnis
9. Test der Behandlungsmethoden
9.1. Testumgebung . . . . . . . . . . . .
9.2. Test der Programmflusskontrolle . .
9.2.1. Spezifikation der Tests . . . .
9.2.2. Realisierung . . . . . . . . . .
9.2.3. Testergebnisse . . . . . . . . .
9.2.4. Evaluation . . . . . . . . . . .
9.3. Test der numerischen Fehlerkorrektur
9.3.1. Spezifikation der Tests . . . .
9.3.2. Realisierung . . . . . . . . . .
9.3.3. Testergebnisse . . . . . . . . .
9.3.4. Evaluation . . . . . . . . . . .
9.3.5. Vergleich mit Oboril et al. . .
9.4. Fazit . . . . . . . . . . . . . . . . . .
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
29
29
30
30
32
32
33
34
34
34
35
36
36
37
10.Zusammenfassung und Ausblick
39
Abbildungsverzeichnis
41
Literaturverzeichnis
44
Begriffe und Abkürzungen
45
A. Anhang
A.1. Die Lösung von Ax = b minimiert die quadratische Form
A.2. Implementierung der Matrix- und Vektoroperationen . .
A.3. Beispiel eines Kompilierungbefehls . . . . . . . . . . . .
A.4. Inhalte des digitalen Mediums . . . . . . . . . . . . . . .
iv
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
47
47
48
50
50
Eidesstattliche Erklärung
Ich, Sebastian Elm, versichere an Eides statt, dass ich die vorliegende Bachelorarbeit
mit dem Titel Numerische Fehlerkorrektur und Programmflusskontrolle zur Behandlung
von Soft Errors selbstständig verfasst und keine anderen als die angegebenen Quellen
und Hilfsmittel verwendet habe. Diese Arbeit wurde in dieser oder ähnlicher Form bisher
keiner anderen Prüfungskommission vorgelegt.
Buxtehude, den 29. Juli 2014
(Unterschrift)
Sebastian Elm <[email protected]>
Matrikelnummer: 21157971
Studiengang: Informatik-Ingenieurwesen B. Sc.
v
1. Einleitung
Soft Errors (=induzierte Bitflips) besitzen u. a. durch extreme Umgebungsbedingungen, bspw. von rechnergestützten Anwendungen im Weltraum, eine große Bedeutung [9].
Durch Soft Errors kann sich der Programmablauf und das Berechnungsergebnis ungewollt
und unkontrolliert verändern; mitunter sind auch Programmabstürze die Folge. Zusätzlich sind Soft Errors nicht reproduzierbar, was die Fehlerdiagnose erschwert [6].
Daher sollen in dieser Arbeit - motiviert durch den Artikel von Oboril et al. ([9]) - Ansätze
auf Seiten der Software zur Behandlung von Soft Errors anhand eines Beispielproblems
vorgestellt werden. Das Beispiel ist ein aus [9] übernommenes Modell, was die Lösung eines linearen Gleichungssystems beinhaltet [9]. Lineare Gleichungssysteme werden häufig
zur Berechnung von Differentialgleichungen in Wettervorhersagen oder Umströmungsberechnungen von Körpern benötigt [14]. Das Verfahren der konjugierten Gradienten (engl.:
conjugated gradients method, kurz: CG-Verfahren) ist eine Möglichkeit zur Lösung der
linearen Gleichungssysteme [12].
Eine technische Maßnahme zur Prävention von Soft Errors besteht in der Verwendung
von Speicher, der durch einen Error Correction Code (ECC) geschützt wird [9, 10]. Diese
bieten jedoch keinen allumfassenden Schutz [9, 6].
Der erste in der Arbeit vorgestellte softwarebasierte Ansatz, die Programmflusskontrolle, adressiert das Problem von Soft Errors in Kontrollstrukturen. Dazu werden, ähnlich
dem Defensive Programming [2], Assertions eingefügt. Durch die neuartige Anwendung
können die Kontrollstrukturen überprüft und ggf. der letzte Ausführungszustand wiederhergestellt werden. Der Ansatz soll anhand des CG-Verfahrens implementiert und untersucht werden. Zudem soll die Programmflusskontrolle bezüglich der These, sie schütze
die Kontrollstrukturen des CG-Verfahrens vor einem Soft Error, getestet werden.
Der zweite, in dem Papier von Oboril et al. vorgestellte, Ansatz behandelt in erster
Linie die durch Soft Errors gefährdete Datenintegrität. Dabei handelt es sich um eine
Erweiterung des CG-Verfahrens; es wurde eine einschließende Schleife zur numerischen
Fehlerkorrektur eingeführt [9]. Die numerische Fehlerkorrektur soll in dieser Arbeit implementiert und analysiert werden; zusätzlich wird sie auf die Wirksamkeit bei einem
Soft Error getestet.
Die Tests werden mittels FITIn realisiert; FITIn ist ein von Clemens Terasa und Marcel
Heing-Becker entwickeltes, auf Valgrind basierendes Werkzeug [4]. FITIn erlaubt es, Soft
Errors in Variablen und Speicherstellen zu injizieren und damit die Auswirkung eines
solchen auf die Anwendung zu simulieren, zu analysieren und zu testen.
Zum Testen wird das White-Box-Testing [1] eingesetzt. Zusätzlich werden Äquivalenzklassen zur Reduktion der Anzahl der Testfälle verwendet. Es wird gezeigt, dass die Tests
der Verfahren die jeweilige These bestätigen und Aussagen über Effektivität und Effizienz erlauben. Daraufhin erfolgt eine Beurteilung der Programmflusskontrolle und der
numerischen Fehlerkorrektur.
Abschließend werden die Ergebnisse kurz zusammengefasst; zudem werden Einschränkungen und weiterführende Ansätze aufgezeigt.
1
2. Soft Errors
Das Phänomen der Soft Errors ist, auch wenn derzeit hochaktuell (vgl. [9, S. 144]),
schon länger bekannt; erste Beobachtungen über diese Art Fehler wurden bereits im Jahr
1975 getroffen [6, S. 128]. Mit Soft Error wird ein temporärer Fehlzustand eines Bits,
also eine temporäre Negierung des Zustands bezeichnet; die Ursache sind sogenannte
single event upsets (zu deutsch: einmalige Veränderungen). Diese entstehen unter Anderem durch den Einfluss von Strahlung auf CMOS-Transistoren, wie sie in aktuellen
Prozessoren eingesetzt werden. Beispiele für die Strahlung sind komische Strahlung oder
elektromagnetische Strahlung, die aus Schaltkreisen emittiert wurde. Treffen energetische
Teilchen auf einen Transistor, kann dieser kurzgeschlossen werden und schalten, was zu
einer Zustandsänderung führt. Bricht der Strom der Teilchen ab, wechselt der Transistor
in seinen ursprünglichen Zustand zurück. Aufgrund der fehlenden Möglichkeit, diesen
Fehler vorherzusagen, und der nur temporären Beeinflussung erhielt diese Art Fehler die
Bezeichnung Soft Error [6, S. 128].
Auf Ebene der Software kann ein Soft Error mitunter fatale Folgen haben. Da ein Soft
Error in jedem Speicherelement, vom Hauptspeicher bis zum Prozessorcache, auftreten
kann, reichen die Folgen von der Änderung der letzten Nachkommastelle in einer Berechnung bis zum kompletten Programm- oder Systemabsturz. Für ersteres reicht es aus, dass
ein Soft Error kurz vor oder während des Leseprozesses aus einer Datenvariable für eine
Berechnung erfolgt; ist die Datenvariable jedoch der Speicher für eine Speicheradresse
oder eine Funktionsadresse, resultieren aus dem Soft Error Zugriffe auf falsche Speicherbereiche oder das Ausführen der falschen Funktion [9, 6].
Zur Verdeutlichung ist in Abbildung 1 das Ablaufdiagramm einer if-Abfrage dargestellt. Bei normaler Ausführung würde die Bedingung x > 0 ausgewertet werden und
x > 0
wahr
A
falsch
B
Abbildung 1.: Ablaufdiagramm einer if-Abfrage
dementsprechend dann entlang des korrekten Pfades die Durchführung fortgeführt. Ist
beispielsweise die Bedingung x > 0 erfüllt, so wäre das dann Pfad A. Allerdings besteht
bei diesem einfachen Vorgang schon an mehr als zwei Stellen die Gefahr, dass ein Soft
3
2. Soft Errors
Error den Fortgang beeinflussen könnte: zum Einen könnte ein Soft Error beim Auslesen
des Wertes von x diesen so beeinflussen, sodass die Überprüfung einen anderen Ausgang
nimmt, als angenommen. Eine andere Möglichkeit bestünde darin, dass der Soft Error
direkt in dem Ergebnis der Überprüfung auftritt und dadurch den Pfad verändert. Bei
Rückblick auf das vorige Beispiel, in dem x > 0 erfüllt ist, wäre dies dann Pfad B. Weiterhin ist es theoretisch möglich, dass ein Soft Error das Ziel des Sprungbefehls verändert,
und somit keiner der beiden gezeigten Pfade genommen wird, oder dass das Programm
komplett abstürzt.
Aufgrund der oben dargestellten Folgen ist es sinnvoll, Soft Errors zu verhindern oder zu
behandeln. Dafür sollen ab Kapitel 4 entsprechende Verfahren vorgestellt werden.
4
3. Lösen eines linearen
Gleichungssystems
In dieser Arbeit werden ab Kapitel 5 zwei Ansätze auf Seiten der Software zur Behandlung
von Soft Errors vorgestellt werden. Zur Veranschaulichung der Auswirkungen wird ein
Anwendungsfall verwendet, der u.a. der Industrie entstammt [9, 14]: das Lösen eines
linearen Gleichungssystems, welches auf Differentialgleichungen beruht.
3.1. Anwendungsbezug
Differentialgleichungen spielen eine wichtige Rolle in der heutigen Industrie. So ist schon
die Anwendung in der numerischen Strömungsberechnung sehr vielfältig: als Werkzeug
zur virtuellen Simulation werden sie u.a. in der Forschung, Entwicklung, Luftfahrt oder
Automobilindustrie eingesetzt; aber auch in der Medizin oder der Wettervorhersage finden sie ihre Anwendung [9, 14].
Dort besitzen die modellierten Probleme häufig eine hohe Komplexität sowie große Dimension und eine daraus resultierende lange Berechnungszeit zur Simulation. Daher ist
es sinnvoll, diese vor Soft Errors zu schützen, um Kosten und Zeit zu sparen [9, S. 144].
3.2. Verfahren der konjugierten Gradienten
Das Verfahren der konjugierten Gradienten (engl.: conjugated gradients method, kurz:
CG-Verfahren) ist eine Lösungsmethode für lineare Gleichungssysteme (LGS)(Gleichung
1). Es eignet sich besonders für symmetrische, positiv definite Systemmatrizen. [12, 9].
Das CG-Verfahren basiert auf der iterativen Berechnung eines Vektors, der von einem
gegebenen Startpunkt aus mit jedem Schritt der exakten Lösung angenähert wird [12].
Im Folgenden soll dieses Verfahren genauer erläutert werden.
A∗x=b
(1)
1
f (x) = xT Ax − bT x + c
2
(2)
In Gleichung 1 ist eine Formel für lineare Gleichungssysteme, in Gleichung 2 die Formel
für eine quadratische Form des LGS angegeben; dabei ist A eine Matrix der Dimension
N xN , x sowie b sind Vektoren der Dimension N und c ist eine skalare Konstante.
3.2.1. Minimierung der quadratischen Form
Ausgehend von der in Gleichung 2 dargestellten Formel für eine quadratische Form kann
gezeigt werden, dass die Lösung des LGS in 1 äquivalent zur Minimierung von 2 ist (siehe
5
3. Lösen eines linearen Gleichungssystems
Anhang A.1). Diese Minimierung kann durch das Ableiten von f (x) und anschließender
Berechnung und Einordnung der Nullstellen erfolgen. Es gilt:
f (x) = min → f 0 (x) = 0
(3)
Bei einem Gleichungssystem wie der quadratischen Form besteht die Ableitung der Funktion aus dem Gradienten (Gleichung 4). Dieser gibt, im geometrischen Kontext, in jedem
Punkt die Richtung des steilsten An- bzw. Abstiegs an.



f 0 (x) = 

∂
∂x1 f (x)
∂
∂x2 f (x)
...
∂
∂xn f (x)





(4)
Angewendet auf Gleichung 2 ergibt sich f 0 (x) = 12 AT x + 21 Ax − b, welches sich aus
Gründen der Symmetrie zu Gleichung 5 reduzieren lässt.
f 0 (x) = Ax − b
(5)
Dies wird zur Minimierung mit 0 gleichgesetzt (Gleichung 6) und anschließend die Lösung
mit dem CG-Verfahren berechnet [12].
0 = Ax − b → f 0 (x) = min
(6)
3.2.2. Berechnung der Lösung
Zur Berechnung von x in Gleichung 6 verwendet das CG-Verfahren, ausgehend von einem
gegebenen Startvektor, A-orthogonale Vektoren, die in jeder Iteration berechnet werden.
Dabei bezeichnen die A-orthogonale Vektoren die Richtung mit dem betragsmäßig größten Gradienten. Zwei Vektoren di und dj sind orthogonal respektiv der Matrix A, wenn
Gleichung 7 erfüllt ist [12, S. 22].
(7)
dTi Adj = 0
Diese werden nach dem Verfahren des steilsten Abstiegs zur Lösung aufsummiert, sodass
in jeder Iteration eine Dimension der Lösung minimiert wird [12].
xi+1 = xi + αi di
(8)
Die Neuberechnung des Lösungsvektors x ist in Gleichung 8 dargestellt. di bezeichnet dabei die Richtung des steilsten Abstiegs (ausgehend von xi ) und ist der in diesem Schritt
berechnete A-orthogonale Vektor; αi ist der Skalierungsfaktor zur Minimierung des Abstands in dieser Richtung.
Zur Bestimmung von αi wird die Tatsache ausgenutzt, dass di orthogonal zur Matrix und
zum vorherigen Vektor xi ist. di wird dafür entlang der Richtungsableitung minimiert
6
3.3. Algorithmus
[12]:
0=
d
f (xi+1 )
dα
0 = f 0 (xi+1 )T
d
xi+1
dα
0 = −(ri+1 )T di
0 = dTi ri+1
αi = −
dTi xi
dTi di
(9)
Zur Berechnung der Vektoren di kann nun das Verfahren nach Gram-Schmidt verwendet
werden. Jedoch ist dies nicht die effizienteste Variante zur Bestimmung der orthogonalen Vektoren, da bei Gram-Schmidt sämtliche vorherigen Vektoren d1 , d2 , . . . , di−1 zur
Berechnung des Vektors di benötigt und somit abgespeichert werden müssen [12, S. 25].
Stattdessen werden für das CG-Verfahren die Richtungen di aus den Residuen der Matrix
ri berechnet. Das Residuum ri (Gleichung 10) ist orthogonal zu den vorherigen Residuen
r1 , r2 , . . . , ri−1 , und es kann direkt aus der Matrix und dem vorhergehenden Residuum
berechnet werden [12, S. 30].
ri = b − Axi
(10)
Nach Skalierung von di für di+1 über β kann dies wie folgt zusammengefasst werden [12,
S. 32]:
d0 = r0 = b − Ax0
(11)
riT ri
dTi Adi
(12)
xi+1 = xi + αi di
(13)
ri+1 = ri − αi Adi
(14)
αi = −
βi+1 =
T r
ri+1
i+1
riT ri
di+1 = ri+1 + βi+1 di
(15)
(16)
3.3. Algorithmus
Das in Kapitel 3.2 vorgestellte CG-Verfahren ist sehr effizient bezüglich Laufzeit und
Speicherverwendung (siehe Kapitel 3.5). Daher ist es ein häufig implementiertes Verfahren. Der Pseudocode dazu ist in Abbildung 2 zu sehen. Im Folgenden werden sämtliche
Variablen, die einem Code-Stück entnommen sind, in Schreibmaschinenschrift dargestellt. Variablen, die aus Gleichungen entnommen wurden, sind in kursiv dargestellt.
Dort ist die Hauptschleife sowie die Berechnung der Startwerte dargestellt. Aufgrund
der fehlenden mathematischen Symbole in einem Quelltext wurden die Variablen ausgeschrieben (bspw. alpha für α). h·, ·i steht für das Skalarprodukt zweier Vektoren x und
7
3. Lösen eines linearen Gleichungssystems
1 x = x_0 S t a r t v e k t o r
2 R = r = b − Ax , rho = <r , r >, b e t a = 0 , p = 0
3 f o r k = 1 t o MAX_iter and | | r | | > e p s ∗ e p s ∗ | | R | | do
4
p = r + b e t a ∗p
5
q = A∗p
6
a l p h a = rho/<rho , q>
7
x = x + a l p h a ∗p
8
r = r − a l p h a ∗q
9
rho_old = rho , rho = <r , r>
10
b e t a = rho / rho_old
11 end
Abbildung 2.: Pseudo-Code des Verfahren der konjugierten Gradienten [9, S. 146]
P
y, definiert durch N
i=1 xi yi , und ||·|| bezeichnet die Eulersche 2-Norm || · ||2 .
Damit ist weitestgehend eine direkte Zuordnung zwischen der Variablen und dem Algorithmus in Kapitel 3.2.2 möglich. ρ gibt das Skalarprodukt von r mit sich selbst an;
q enthält das Produkt von Matrix A und Vektor p. p entspricht dem Vektor d in den
Gleichungen 11 bis 16.
Zu den Variablen aus Kapitel 3.2.2 kommt noch R hinzu; dies wird für die Abbruchbedingung in Zeile 3 benötigt. R enthält das Residuum des Startvektors und spiegelt den
anfänglichen Gradienten wider. Der Algorithmus bricht unter anderem ab, sobald eine
gewisse Genauigkeit ||R||2 (vgl. Zeile 3) erreicht wird [9]. bezeichnet dabei den gewünschten maximalen Fehler. Der maximale Fehler wird aus den Gradienten des Startvektors und des Ergebnisvektors berechnet. Dies lässt sich wie folgt veranschaulichen:
das Verfahren bricht dann ab, wenn die Änderung (also die Steigung) an der Lösung eine
Grenze unterschreiten. Der andere Teil der Abbruchbedingung besteht aus einer oberen
Grenze MAX_iter für die Anzahl an Iterationen; diese beträgt in dieser Arbeit zehn. Der
Grund dafür ist die Ungenauigkeit der Maschinenberechnungen, da sich mit diesen nur
gerundete Ergebnisse erzielen lassen [5, 12].
3.4. Implementierung
Sämtliche Programme und Algorithmen sind, sofern nicht anders angegeben, in der Hochsprache C verfasst, und mit dem C89-Standard kompiliert (siehe Kapitel 9.1). Dies bedingt
eine wichtige, umfassende Besonderheit bei der Implementierung: da im C-Standard die
Datentypen Matrix und Vektor nicht definiert wurden, musste eine eigene Implementierung der Datentypen und der notwendigen Operationen benutzt werden.
3.4.1. Datentyp Vektor
Als Ersatz für den fehlenden Standard wurde eine Array(/Feld)-Implementierung des
Datentyps double (Abbildung 3) gewählt. Für die Matrix kam ein mehrdimensionales
8
3.4. Implementierung
Array zum Einsatz. Die Gründe dafür sind die einfache Definition und Deklaration, sowie
die simple Verwendung mit einem hohen Grad an Kontrolle, gerade bei der operationellen
Verarbeitung. Zudem ist auch ein sehr geringer Speicheroverhead durch die Verwendung
von ’Call by Reference’ möglich. Nach der Definition der Matrix (Zeile 1) und des Vektors
(Zeile 2) mit den Dimensionen N xN und N ist noch der Speicher dafür zu reservieren und
mit einem definierten Startwert zu initialisieren (Zeile 9-13). Dies geschieht mit Hilfe von
malloc (Zeile 5-7). Da die Matrix ein mehrdimensionales Array ist, wird zuerst eine Zeile
reserviert, und anschließend ausgehend von dem jeweiligen ersten Element die zugehörige
Spalte. Nach den Berechnungen wird der allozierte Speicher in umgekehrter Reihenfolge
wieder freigegeben (Zeile 16-18).
3.4.2. Matrix- und Vektoroperationen
Im CG-Verfahren wurden vier Operationen angewendet, die auf Matrizen oder Vektoren
arbeiten: die Matrix-Vektor-Multiplikation Av, die Vektor-Skalar-Multiplikation vc, das
Skalar-Produkt h·, ·i und die Eulersche Norm || · ||. Diese wurden in eigenen Funktionen
implementiert, die alle dem gleichen Schema folgen: zuerst werden die beiden Operanden
als Parameter übergeben. Zusätzlich wird, wenn das Ergebnis ein Vektor ist, ein solcher
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
/∗ D e f i n i t i o n e i n e r Matrix a l s
z w e i d i m e n s i o n a l e s Array ∗/
double ∗∗A;
/∗ D e f i n i t i o n e i n e s V e k t o r s a l s Array ∗/
double ∗v ;
/∗ S p e i c h e r a l l o k a t i o n ∗/
A = m a l l o c ( s i z e o f ( double ∗ ) ∗ N ) ;
f o r ( i = 0 ; i < N; i ++)
A[ i ] = m a l l o c ( s i z e o f ( double ) ∗ N ) ;
b = m a l l o c ( s i z e o f ( double ) ∗ N ) ;
/∗ W e r t i n i t i a l i s i e r u n g mit 0 ∗/
f o r ( i = 0 ; i < N; i ++) {
v [ i ] = 0;
f o r ( j = 0 ; j < N; j ++) A[ i ] [ j ] = 0 ;
}
/∗ S p e i c h e r f r e i g a b e ∗/
f o r ( i = 0 ; i < N; i ++) f r e e (A[ i ] ) ;
f r e e (A ) ;
free (v );
Abbildung 3.: Implementierung der Datentypen Matrix und Vektor als Array(s)
9
3. Lösen eines linearen Gleichungssystems
übergeben, um das Ergebnis darin zu speichern. Sollte das Ergebnis kein Vektor sein, wird
eine Variable angelegt und diese am Ende zurückgegeben. Nachdem eine Ergebnisvariable
festgelegt wurde, wird diese mit Null initialisiert. Dann wird das Ergebnis berechnet und
in der Ergebnisvariable abgespeichert bzw. zurückgegeben (vgl. Anhang A.2).
3.5. Betrachtung der Effizienz
Das CG-Verfahren ist einer der effizientesten Algorithmen zur Lösung von linearen Gleichungssystemen [8, S. 101]. Dazu tragen vor allem der geringe Speicherverbrauch sowie
die geringe Laufzeit bei.
Wie schon in Kapitel 3.2.2 angedeutet, ist es beim CG-Verfahren nicht notwendig, sämtliche vorhergehenden Vektoren zur Berechnung des nächsten linear unabhängigen Vektors
abzuspeichern. Damit verbleiben nur die Matrix, der Vektor der rechten Seite, sowie
der Lösungsvektor, die während der gesamten Berechnung vorzuhalten sind. Aus Gründen der geringeren Laufzeit kann auch das Matrixprodukt (vgl. Abbildung 2, Zeile 5)
zusätzlich abgespeichert werden, was den zu speichernden Daten einen weiteren Vektor
hinzufügt [12][8, S. 107].
Bezüglich der Laufzeit ist das CG-Verfahren - wie schon oben angedeutet - sehr effizient: in jeder Iteration wird durch die Orthogonalität der Summanden eine Komponente
des Lösungsvektors minimiert, sodass nach spätestens N Schritten der mathematische
Algorithmus garantiert terminiert und die mathematisch exakte Lösung liefert. Bei einer
symmetrischen Lösung terminiert das Verfahren schon nach dN e Schritten, wenn eine
passende obere Schranke für den Fehler eingebaut wurde [12, 8].
Daraus folgt, dass das CG-Verfahren bei großen Dimensionen ein rechenintensives Verfahren ist.
10
4. Error Correction Code
Eine Möglichkeit zur Behandlung von Soft Errors besteht in der Verwendung eines Error Correction Codes (zu deutsch: fehlerkorrigierender Code, kurz: ECC). Diese aus der
digitalen Codierungstheorie stammende Technik basiert auf dem Hinzufügen von Redundanzinformationen, um daraus in Kombination mit den - im Falle eines Soft Errors fehlerhaften Informationen das Original wiederherzustellen [10].
4.1. Realisierung der ECC
Der einfachste Ansatz ist das Hinzufügen eines Paritätsbits. Dabei werden immer zwei
benachbarte Bits mit einem zusätzlichen Bit versehen, welches den Zustand beider Bits
widerspiegelt: bspw. kann dem Paritätsbit eine 0 zugewiesen werden, wenn die beiden
benachbarten Bits gleich sind, ansonsten eine 1. Somit ist die Anzahl an Einsen in diesen
drei Bits immer gerade; daher kann im Falle eines Soft Errors in einem der benachbarten Bits dieser durch das Paritätsbit erkannt werden [10]. Leider ist es nicht möglich,
aus einem Paritätsbit den vorherigen Zustand widerherzustellen, da nicht ersichtlich ist,
welches der beiden Bits den Soft Error erfahren hat. Daher werden andere Verfahren
verwendet, in denen sieben oder acht Bits zur Korrektur von 32 oder 64 Bit großen Blöcken benutzt werden [11]. Dafür werden beim Schreiben in den Speicher die zugehörigen
Bits von einem zusätzlichen Controller mit dem ECC-Code versehen. Wird aus einem
ECC-geschützten Speicher gelesen, wird aus den gelesenen Daten erneut ein ECC-Code
errechnet, welcher mit dem ursprünglichen ECC-Code verglichen wird. Ist ein einzelner
Soft Error aufgetreten, wird dies in dem Vergleich erkannt und durch den Controller
korrigiert [11].
4.2. Betrachtung der Effizienz
Damit sind mit ECC geschützte Speicher in der Lage, mindestens einen Soft Error zu
korrigieren; es gibt auch Implementierungen, die mehr als einen Fehler entdecken und
korrigieren können [6, S. 134]. Allerdings bietet das keinen umfassenden Schutz; vor allem
Register und Ausführungseinheiten besitzen meist keine ECC-Implementierung und sind
somit anfällig für Soft Errors [9, 6, S. 134]. Daher ist es sinnvoll, den Schutz vor Soft
Errors auf eine weitere Ebene, der Software-Ebene, auszuweiten [9].
11
5. Programmflusskontrolle
Im Gegensatz zum teils sehr kostenintensiven ECC-Schutz, sollen nun zwei verschiedene Behandlungsmöglichkeiten auf Seiten der Software betrachtet werden: zum Einen die
Programmflusskontrolle, abgeleitet vom defensiven Programmieren (Defensive Programming), zum Anderen die Numerische Fehlerkorrektur (siehe Kapitel 6).
5.1. Defensive Programming
Defensive Programming (zu deutsch in etwa: schützender Programmierstil), nach Firesmith ([2]) auch ein Teil des Defensive Development (zu deutsch soviel wie: schützende
Entwicklung), bezeichnet eine Art und Weise des Programmierens, in der die Implementierung sich selbst vor unsachgemäßem Gebrauch oder Fehlern schützt. Um das zu
erreichen, werden vor der Ausführung der Befehle eine große Anzahl an Voraussetzungen
überprüft. Dazu werden meist Assertions (zu deutsch: Zusicherungen, Sicherstellungen)
verwendet [2].
In Abbildung 4 ist beispielhaft eine Assertion im Quellcode einer Funktion zur Be1 f l o a t d i v i d e ( f l o a t a , int b ) {
2
A s s e r t i o n ( "B n i c h t n u l l " ) ;
3
return a / b ;
4 }
Abbildung 4.: Beispiel einer Assertion in einer Funktion zur Division
rechnung der Division dargesellt. Für den Fall, dass der Divisor Null beträgt, muss die
Division anders behandelt werden, da hier der Quotient nicht definiert ist. Dieser Fall
wird in Zeile 2 überprüft.
5.2. Anwendung zur Korrektur von Soft Errors
Da es wünschenswert ist, die Soft Errors gerade im Bereich des Ausführungspfades eines Programms zu verhindern oder zu korrigieren, wird die defensive Programmierung
auf Kontrollstrukturen angewendet. Das wird im Folgenden als Programmflusskontrolle
bezeichnet. Dazu wird die Abfrage-Bedingung der for-Schleife mit Assertions überprüft.
Hierbei handelt es sich um sogenannte Postconditions, also Assertions, die nach erfolgreicher Berechnung erfüllt sein müssen [2, S. 260].
Um dies beim CG-Verfahren anwenden zu können, muss die Kontrollstruktur for modifiziert werden. In Abbildung 5 ist eine einfache for-Schleife dargestellt, die in jeder
Iteration eine Berechnung durchführt und anschließend die Laufvariable um den Wert 1
inkrementiert. Dies wird solange durchgeführt, bis die maximale Anzahl MAX an Iterationen erreicht ist.
13
5. Programmflusskontrolle
Um die Ausführung dieser Kontrollstruktur bei einem Soft Error zu korrigieren, müssen
1 i = 0;
2
3 while ( 1 ) {
4
f o r ( ; i < MAX; i ++) {
5
Assertion ( " Letzte Schrittweite korrekt ?" ) ;
6
// Ggf . R e s e t d e r Parameter und d e r S c h l e i f e
7
Assertion ( " S o l l t e S c h l e i f e beendet s e i n ?" ) ;
8
// Ggf . Beendigung d e r S c h l e i f e
9
[ Berechne ]
10
}
11
Assertion ( " Letzte Sc h r i t t w e i t e korrekt ?" ) ;
12
// Ggf . R e s e t d e r Parameter und d e r S c h l e i f e
13
A s s e r t i o n ( " Abbruchbedingung f o r −S c h l e i f e k o r r e k t ? " ) ;
14
// Ggf . R e s e t d e r Parameter und d e r S c h l e i f e
15 }
Abbildung 5.: Kontrollstruktur for nach der Anwendung der Programmflusskontrolle
zwei wichtige Punkte überprüft werden: erstens, die Abbruchbedingung, und zweitens,
die Schrittweite. Dazu werden die Assertions an geeigneten Punkten eingefügt und eine
einschließende Schleife gelegt, die im Bedarfsfall ein Zurücksetzen der Schleife oder die
Wiederholung einer oder mehrerer Iterationen veranlasst.
Dies ist in Abbildung 5 realisiert. Sollte ein Soft Error in der Berechnung oder der Auswertung der Abbruchbedingung auftreten, sodass diese zum Verlassen der for-Schleife
führt, wird die Abbruchbedingung erneut ausgewertet und dementsprechend agiert: wird
die Abbruchbedingung immer noch eingehalten, so wird die for-Schleife erneut durchlaufen (ggf. mit Zurücksetzen der Parameter aus Backup-Variablen); ist dies nicht der Fall,
kann mit dem weiteren Programm fortgefahren werden.
Ähnlich verhält es sich bei der Überprüfung der Schrittweite, auch wenn diese an zwei
Punkten überprüft werden muss (Zeile 6 und 9). Wird ein Soft Error an diesen Stellen durch eine veränderte Schrittweite ersichtlich, so werden die Parameter sowie die
Schleife zurückgesetzt; tritt kein Soft Error auf, ist keine Beeinflussung des Programms
vorhanden.
5.3. Implementierung
Um den Einfluss eines Soft Errors auf die Steuerungsvariablen wie die Laufvariable oder
die Schrittweite möglichst gering zu halten, werden diese mit dem Schlüsselwort volatile
versehen. Dies erzwingt das Laden des Variableninhalts aus dem Speicher bei jedem Zugriff sowie das sofortige Zurückschreiben der Variable nach Beendigung der Berechnung
[5, S. 13ff]. Dadurch wird ein Auftreten eines Soft Errors auf die Zeit der Berechnung
beschränkt.
14
5.4. Betrachtung der Effizienz
Zudem kann die Implementierung der Programmflusskontrolle in Bezug auf das CGVerfahren noch optimiert werden. Dabei steht in dieser Arbeit ein geringer Overhead
(vgl. Kapitel 5.4) im Fokus.
Ein Schritt zur Optimierung besteht in der Verringerung der Backup-Variablen. Da der
Algorithmus des CG-Verfahrens in jeder Iteration acht Variablen berechnet (vgl. Kapitel 3.3), und auch die Laufvariable berücksichtigt werden muss, müssten bei naiver
Herangehensweise die Zwischenzustände aller neun Variablen gespeichert werden, um
ein Zurücksetzen zu ermöglichen. Jedoch kann die Zahl der Backup-Variablen auf ein
Backup der Laufvariablen reduziert werden. Der Grund dafür ist die Funktionsweise des
CG-Algorithmus: da in jedem Schritt Berechnungen unabhängig von der Laufvariablen
getätigt werden und es hier auf die Anzahl der Berechnungen ankommt, kann diese Reduzierung durchgeführt werden.
Zusätzlich sind die Assertions so entworfen, dass diese unnötige Berechnungsiterationen
1 while ( 1 ) {
2
f o r ( ; Bedingung ; Inkrement ) {
3
Berechne V a r i a b l e n
4
}
5
i f ( Bedingung ) {
6
Reset d e r L a u f v a r i a b l e n
7
}
8
break ;
9 }
Abbildung 6.: Verhinderung unnötiger Iterationen durch die Kombination if-break
verhindern (siehe Abbildung 6).
Angenommen, es tritt ein Soft Error in einer Kontrollstruktur während der Ausführung
auf, so kann dieser entweder in der Bedingung der for-Schleife (Zeile 2) oder in der
Bedingung der if-Abfrage (Zeile 5) auftreten. Im ersten Fall wird die Assertion diesen
Soft Error erkennen und die berechnende Schleife zurücksetzen. Im zweiten Fall wird die
Bedingung der berechnenden Schleife erreicht, diese wird mit false evaluiert und die
Schleife verlassen. Danach evaluiert die Assertion korrekt mit true und das Programm
wird fortgesetzt.
5.4. Betrachtung der Effizienz
Wie schon im vorigen Kapitel (Kapitel 5.3) aufgezeigt, ist die Programmflusskontrolle in
Bezug auf das CG-Verfahren eine Möglichkeit zur Korrektur von Soft Errors in Kontrollstrukturen mit geringem Overhead. Die Hauptgründe dafür sind der geringe zusätzliche
Speicheraufwand, welcher sich auf ein Backup der Laufvariablen beschränkt, und die
Verhinderung von unnötigen Iterationen bei der Berechnung. Damit ist die Programmflusskontrolle für das CG-Verfahren gut geeignet.
15
5. Programmflusskontrolle
Bei der Übertragung der Programmflusskontrolle auf andere Algorithmen ist es wahrscheinlich, dass die gleiche Effizienz wie beim CG-Verfahren nicht mehr erreicht wird.
Auch wenn der Laufzeit-Overhead ähnlich gering sein wird, ist der Speicheraufwand möglicherweise ein vielfaches größer. Ein einfaches Gegenbeispiel findet sich in Abbildung 7.
Dort ist eine Funktion zur Berechnung der Summe der Zahlen von eins bis zu einem
1 int sum = 0 ;
2 f o r ( int i = 0 ; i < MAX; i ++) {
3
sum += i ;
4 }
Abbildung 7.: Algorithmus zur Summe der Zahlen von 1 bis MAX
Höchstwert MAX abgebildet. Sollte man nun die Programmflusskontrolle auf diesen Algorithmus anwenden, so müsste man nicht nur ein Backup der Laufvariablen erzeugen,
sondern auch ein Backup der Summe, um so den vorhergehenden Wert wiederherstellen
zu können. Damit eignet sich die Programmflusskontrolle für diesen Algorithmus nicht, da
der doppelte Speicherplatz benötigt wird. Daraus folgt, dass die Programmflusskontrolle
bei nur rechenintensiven Anwendungen geeignet ist. Bei speicherintensiven Anwendungen
ist das nicht der Fall, sofern sich diese nicht - ähnlich wie das CG-Verfahren - optimieren
lassen.
16
6. Numerische Fehlerkorrektur
Anstelle der Programmflusskontrolle kann auch die Numerische Fehlerkorrektur verwenden werden. Diese adressiert im Gegensatz zur Programmflusskontrolle nicht die korrekte
Ausführung der einzelnen Pfade, sondern die Korrektheit der Lösung als Ganzes. Das bedeutet, dass ein Soft Error sowohl in den Kontrollstrukturen als auch den Datenvariablen
auftreten könnte.
Bei der numerischen Fehlerkorrektur handelt es sich um eine mathematische Transformation des Ausgangsproblems zu einem Defekt-Problem: anstatt die Ausgangsgleichung
direkt zu lösen, wird der Lösungsvektor durch einen fehlerbehafteten Vektor ersetzt [9].
Ax = b
(17)
A(x + d) = b
(18)
Ad = b − Ax
(19)
Ad = r
(20)
Dabei bezeichnet d den angenommenen Fehler.
Die Gleichung (20) wird nun mit dem beschriebenen CG-Verfahren gelöst und das Ergebnis zur Korrektur des Lösungsvektors benutzt. Anschließend wird die Genauigkeitsbedingung überprüft und die nächste Iteration gestartet [9, S. 147f]. Dabei ist anzumerken,
dass das CG-Verfahren nicht nur zur Verdeutlichung dient, sondern direkt ein Teils des
Verfahrens ist.
6.1. Algorithmus
1
2
3
4
5
6
7
x = x_0
R = r = b −
while | | r | |
Setze A ∗
x = x + d
r = b − A
end while
A ∗ x
> e p s ∗ | | R | | do
d = r i n CG−V e r f a h r e n e i n
∗ x
Abbildung 8.: Pseudo-Code der numerischen Fehlerkorrektur (vgl. [9, S. 148])
Abbildung 8 stellt den Pseudo-Code der numerischen Fehlerkorrektur dar. Während in
Zeile 1 und 2 die aus dem CG-Verfahren bekannten Startbedingungen berechnet werden,
ist in den darauf folgenden Zeilen die einschließende Schleife dargestellt. Die Bedingung
für die gewünschte Genauigkeit wurde eins zu eins übernommen; direkt darauf erfolgt der
Aufruf des Lösungsalgorithmus mit dem fehlerbehafteten Vektor d. Nach erfolgreichem
Abschluss wird der Lösungsvektor um das Ergebnis korrigiert und das Residuum für den
17
6. Numerische Fehlerkorrektur
nächsten Schritt berechnet. So wird um das CG-Verfahren eine einschließende Schleife gelegt, die die gleiche Bedingung (Genauigkeitsbedingung) wie das originale CG-Verfahren
besitzt. Die einzige Ausnahme bildet die untere Schranke , die bei der numerischen
Fehlerkorrekture nicht quadratisch afutritt. Somit wird, wenn kein Soft Error auftritt,
auch keine weitere Iteration benötigt. Im Falle eines Soft Errors im CG-Verfahren ist die
gewünschte Genauigkeit nicht mehr erreicht, und das Verfahren mit dem aktualisierten
Residuum erneut gestartet [9].
Dabei wird keine Unterscheidung über das Auftreten eines Soft Errors gemacht, solange dieser innerhalb des CG-Verfahrens auftritt. Damit besteht die Möglichkeit, dass das
CG-Verfahren durch einen Soft Error sehr viel länger zur Terminierung benötigt, oder
die Terminierung überhaupt nicht mehr eintritt [9, S. 148].
6.2. Betrachtung der Effizienz
Durch die Verwendung einer einfachen, äußeren Schleife für die numerische Fehlerkorrektur wird der Speicheraufwand reduziert: so sind zusätzlich zu den Variablen des CGVerfahrens nur der fehlerbehaftete Vektor d, die Residuen r und R sowie der Lösungsvektor x abzuspeichern. Bei effizienter Programmierung ist es möglich, die zusätzlichen
Variablen von vier auf eine zu senken; dies wird durch Wiederverwendung der Residuen
und des fehlerbehafteten Vektors im CG-Verfahren ermöglicht.
Zusätzlich ist, wie schon im vorangegangenen Kapitel 6.1 angedeutet, diese Implementierung der numerischen Fehlerkorrektur berechnungseffizient: im Falle eines Soft Errors
wird, ausgehend vom letzten Ergebnis, die Berechnung erneut gestartet. Somit gehen
mögliche - bis zu diesem Zeitpunkt erzielte - Fortschritte nicht verloren. Im Normalfall,
also ohne ein Auftreten eines Soft Errors, besteht der zusätzliche Berechnungsaufwand
nur aus dem einmaligen Überprüfen der Genauigkeitsbedingung; hier ist also auch nur
ein sehr geringer Overhead vorhanden [9, S. 148].
18
7. Software-Tests
Mit dem Einsatz von Software in sehr vielfältigen und unterschiedlichen Gebieten steigt
die Notwendigkeit einer zuverlässigen, robusten und nach Möglichkeit fehlerfreien Implementierung. Dies führt zur Einführung eines Teilgebiets des Software Engineering, dem
Testen von Software. Durch die vielen Faktoren, die Software beeinflussen können, wird
der Entwurf einer vollständig fehlerfreien Software nahezu unmöglich. Daher sollte es
beim Testen nicht das Ziel sein, die korrekte Funktionsweise eines Programms oder eines
Algorithmus, sondern die Abwesenheit von Fehlern zu zeigen. Das ist gerade bei der Verwendung von Software in kritischen Prozessen, in denen Menschen involviert sind und
zu Schaden kommen können, äußerst wichtig [7].
Bei dem Design von Tests werden hauptsächlich zwei Arten des Testens unterschieden:
das Black-Box-Testing und das White-Box-Testing [1]. Bei Ersterem wird die zu testende Funktion, das Programm/Modul oder das System als schwarze Box behandelt,
deren genaue Funktionsweise unbekannt ist. Hier werden die Testfälle enstprechend der
Programmspezifikation entworfen, dementsprechend Eingaben durchgeführt und die Ergebnisse mit den Erwartungen verglichen.
Im Gegensatz dazu steht das White-Box-Testing, bei dem eine andere Herangehensweise
verwendet wird: die Tests werden anhand des konkreten Quellcodes entworfen, um bestimmte Eigenschaften zu überprüfen (siehe Kapitel 7.2). Bei beiden gilt: je höher die
jeweilige Überdeckung, desto größer ist die Qualität. Während beim Black-Box-Testing
die Überdeckung der Eingabe gemeint ist, handelt es sich beim White-Box-Testing um
eine möglichst hohe Ausführungsrate der Programmpfade mit einem gebenen Kriterium,
die erzielt werden soll [7].
Es wird angenommen, dass eine Kombination aus beiden Varianten optimal ist [7].
7.1. Äquivalenzklassen
Angenommen, es sei ein Algorithmus zu testen, der einen Soft Error in der Addition
zweier Zahlen bitgenau entdecken soll (Abbildung 9). Dies generiert schon zahlreiche
Testfälle, die untersucht werden müssten. Der maximale Zahlenbereich der Variablen a
1 short int a = 5 , int b = 7 , int c = 0 ;
2 c = a + b ; /∗ S o f t Error−I n j e k t i o n i n d i e s e A d d i t i o n ∗/
3 [ Entdecke S o f t E r r o r ]
Abbildung 9.: Addition zweier Zahlen, in die ein Soft Error injiziiert werden soll.
und b erstreckt sich von −215 − 1 bis 215 ; der benötigte Speicherbereich beträgt damit
32 Bit pro Zahl [5, S. 22]. Für einen vollständigen Test müsste in jedes Bit beider Zahlen
jeweils einmal ein Soft Error injiziert werden; die Gesamtzahl der Testfälle betrüge bei
dieser einfachen Addition 64.
19
7. Software-Tests
Damit umfassende und umfangreiche Software-Tests von komplexen Programmen realisierbar bleiben, werden für die Variation der Eingabe Äquivalenzklassen benutzt.
Äquivalenzklassen bieten die Möglichkeit, die Eingabemenge zu partitionieren, sodass
sich durch die Auswahl eines Vertreters für jede Partition die Menge der Testfälle reduziert. Alle Elemente einer Partition besitzen die gleichen Eigenschaften und erzeugen
daher auch die gleiche Ausgabe. Das bedeutet, dass ein Auftreten eines Fehlers bei einem Element einer Partition den gleichen Fehler bei allen anderen Elementen derselben
Partition impliziert [1, S 67f].
Bei dem in Abbildung 9 dargestellten Beispiel bietet es sich an, dieses Verfahren anzuwenden. Da das Erkennungsverfahren bitgenau arbeitet, macht es keinen Unterschied, in
welches Bit einer Variable der Soft Error injiziert wird. Somit ist es möglich, alle Bits
einer Variable in einer Partition zusammenzufassen. Daraus resultieren dann zwei Partitionen (jeweils eine für die Variablen a und b), aus denen jeweils ein Vertreter ausgewählt
wird. Aufgrund dessen verbleiben von den ursprünglich 64 verschiedenen Testfällen nur
noch 2, was eine erhebliche Verbesserung bedeutet.
7.2. Mehrfachbedingungsüberdeckung
Eine der Möglichkeiten, das White-Box-Testing durchzuführen, besteht in der Verwendung der Pfadüberdeckung. Dafür werden die Testfälle so entworfen, dass sämtliche Ausführungspfade des Programm(-teils) mindestens einmal durchlaufen werden. Allerdings
kann durch das Kriterium der Pfadüberdeckung durch die exponentiell hohe Anzahl an
Pfaden eine sehr große Menge an Testfällen generiert werden, weshalb eine Variante verwendet wird: die Bedingungsüberdeckung [7].
Bei der Bedingungsüberdeckung wird jede mögliche Kombination aus Eingaben in einer
Bedingung verwendet, um alle möglichen Ergebnisse der Abfrage hervorzurufen und damit sämtliche Pfade mindestens einmal zu durchlaufen. Ist mehr als eine Bedingung in
der Abfrage enthalten, wird dies Mehrfachbedingungsüberdeckung genannt [1]. Zur Ver1 if (x > 0 | | y > 0 ) {
2
[ Berechne ]
3 }
Abbildung 10.: Einfache if-Abfrage mit zwei Bedingungen
deutlichung ist in Abbildung 10 eine if-Abfrage mit zwei Teilbedingungen zu finden: x
> 0 und y > 0. Um hier eine vollständige Mehrfachbedingungsüberdeckung zu erreichen,
sind vier Testfälle notwendig:
1. x > 0 und y > 0
2. x > 0 und y <= 0
3. x <= 0 und y > 0
20
7.2. Mehrfachbedingungsüberdeckung
4. x <= 0 und y <= 0
Für die vier Fälle können entsprechend ihrer Definition die korrekten Werte bestimmt
werden, um die jeweiligen Anforderungen zu erfüllen.
21
8. Implementierung eines Tests unter
FITIn
Um mittels FITIn einen Soft Error in ein Programm zu injizieren, sind zwei Schritte notwendig: als Erstes die Annotierung der Variable, in der die Soft Error-Injektion erfolgen
soll; als zweites die Steuerung des Werkzeugs FITIn durch ein Lua-Skript, in dem der
genaue Zeitpunkt der Manipulation festgelegt werden kann.
8.1. Annotation des Quellcodes
Für den ersten Schritt ist demnach der Quellcode des zu testenden Programms notwendig; die Annotierung erfolgt über Makros, welche durch Einbinden des FITIn-Headers zur
Verfügung gestellt werden [4, S. 65]. In Abbildung 11 ist eine beispielhafte Annotation
1 #include <s t d i o . h>
2 #include " f i _ c l i e n t . h"
3
4 int main ( void ) {
5
int a = 0 ;
6
FITIN_MONITOR_VARIABLE ( a ) ;
7
a = a + 1;
8
FITIN_UNMONITOR_VARIABLE ( a ) ;
9
p r i n t f ( "The v a l u e o f a i s %d\n" , a ) ;
10
return 0 ;
11 }
Abbildung 11.: Quellcode mit beispielhafter Annotation
eines Quellcodes durchgeführt worden: während in Zeile 2 nur die in FITIn integrierte
Header-Datei eingebunden wird, wird in den Zeilen 5 und 7 die eigentliche Annotierung
durchgeführt. Die beiden Makros FITIN_MONITOR_VARIABLE und FITIN_UNMONITOR_VARIABLE sorgen für die korrekte Erkennung der Variablenzugriffe in dem
durch die Makros eingeschlossenen Intervall. Das Makro FITIN_MONITOR_VARIABLE (a) wird von FITIn dazu verwendet, die Adresse des zugehörigen Speicherbereichs
an Valgrind weiterzuleiten und Callbacks dafür zu registrieren; diese werden dann durch
FITIn verarbeitet (vgl. Kapitel 8.2). Im Gegensatz dazu wird FITIn durch das Makro
FITIN_MONTIOR_VARIABLE (a) dazu angehalten, ab diesem Zeitpunkt die Lesezugriffe der Variablen a nicht mehr zu verarbeiten [4, S. 10ff].
23
8. Implementierung eines Tests unter FITIn
8.2. Steuerung mittels eines Lua-Skriptes
Der zweite Schritt erfordert die Erstellung eines sogenannten Kontroll-Skriptes, welches in
der Skript-Sprache Lua zu verfassen ist. In Abbildung 12 ist ein passendes Kontroll-Skript
für das in Abbildung 11 enthaltene Programm dargestellt. FITIn ruft bei einem erkann1 t r e a t _ s u p e r b l o c k = f u n c t i o n ( a d d r e s s , fnname ,
2
f i l e n a m e , dirname , linenum )
3
return fnname == "main"
4 end
5
6 monitor_address = f u n c t i o n ( a d d r e s s , a n n o t a t e d )
7
return annoted
8 end
9
10 f l i p _ v a l u e = f u n c t i o n ( s t a t e , a d d r e s s , c o u n t e r , s i z e )
11
i f ( c o u n t e r == 1 ) then
12
return {32}
13
else
14
return {}
15
end
16 end
Abbildung 12.: Ein beispielhaftes Kontroll-Skript in Lua zur Steuerung von FITIn
ten Lesezugriff auf einen Speicherbereich verschiedene Lua-Callbacks auf, die wichtigsten
sind in Abbildung 12 zu finden: treat_superblock, monitor_address und flip_value.
Der Callback treat_superblock entscheidet über den weiteren Aufruf der anderen Callbacks im Falle eines lesenden Variablenzugriffs. Da FITIn sämtliche Variablenzugriffe
registriert, ist es hiermit möglich, nur Variablenzugriffe eines bestimmten Blocks, beispielsweise einer Funktion oder einer Datei, zu selektieren und weiter zu verarbeiten.
Dies dient vor allem der Performance; sollten alle Variablenzugriffe verfolgt werden, ist
ein enormer zusätzlicher Speicher- und Rechenaufwand notwendig. In diesem Beispiel
weist das Skript FITIn an, alle Variablenzugriffe innerhalb der main-Funktion zu behandeln. Da es selbst innerhalb eines Blocks zu mehrfachen, verschiedenen Variablenzugriffen
kommt, ist es mittels des Callbacks monitor_address möglich, zu entscheiden, wie die
einzelnen Zugriffe behandelt werden sollen. Hier wird bei vorhandener Annotation der
Variable im Quellcode, welche durch den Wahrheitswert im Parameter annotated angegeben ist, die Manipulation ermöglicht. Die aufgeführte Manipulation wird durch das
letzte Callback flip_value durchgeführt. Dieser wird nur aufgerufen, wenn die vorhergehenden Callbacks eine Verarbeitung der Variable erlauben, i.e. wenn die Variable in
einem erlaubten Block enthalten ist und eine Annotation im Quellcode erfahren hat.
Sind diese Bedingungen erfüllt, kann über die Zurückgabe einer positiven Ganzzahl eine
Bitmaske definiert werden, nach der der Bitflip des Soft Errors erfolgen soll. Zur kon-
24
8.3. Injektion eines Soft Errors in Kontrollstrukturen
trollierten Manipulation stehen verschiedene Parameter zur Verfügung, die wichtigsten
sind address und counter. Während address die Adresse des erkannten Speicherzugriffs
enthält, anhand derer zwischen verschiedenen Variablen unterschieden werden kann, ist
in counter die Iteration des Zugriffs enthalten. Da FITIn jeden Zugriff auf die Variable
registriert und hierbei immer einen Zähler inkrementiert, ist es dadurch möglich, den
Zeitpunkt der Soft Error-Injektion auf die Operation genau festzulegen.
In dem gezeigten Beispiel (vgl. Abbildung 11) wird in dem durch die Makros eingeschlossenen Bereich genau einmal lesend auf die Variable a zugegriffen (Zeile 6: a = a + 1).
Der Callback führt hier beim Lesen der Variable vor der Berechnung von a + 1 die Injektion auf das Bit mit dem Wert 32 durch (also das sechstniedrigste Bit: 25 ), was zu
einer Änderung der Variable für die Berechnung von dem Wert 0 zum Wert 32 führt und
dadurch die Berechnung das Ergebnis 33 liefert. Das Ergebnis wird nun wieder in der
Variable a abgespeichert; dies ruft keine erneute Behandlung durch FITIn hervor.
8.3. Injektion eines Soft Errors in Kontrollstrukturen
Um die angestrebte Injektion eines Soft Errors in die Abfrage-Bedingung einer Kontrollstruktur zu erreichen, muss diese ab einer gewissen Komplexität aus der Kontrollstruktur
extrahiert werden.
Im ersten Beispiel (Abbildung 13) ist die Kontrollstruktur if mit einer simplen Bedin1
i f ( x < 0) { [ . . . ] }
Abbildung 13.: Einfache if-Abfrage als Beispiel für eine Kontrollstruktur
gung dargestellt; es ist eine einzelne Variable x beteiligt, welche eine einzelne Bedingung
zu erfüllen hat (x < 0). Zur erfolgreichen Manipulation reicht es, wenn in x das höchstwertigste Bit (engl: Most Significant Bit, kurz: MSB) durch einen Soft Error negiert wird.
Da das MSB bei einer vorzeichenbehafteten, ganzen Zahl das Vorzeichen eindeutig repräsentiert, wird bei einem Soft Error im MSB das Vorzeichen der Variable negiert und
somit der Ausgang der Abfrage umgekehrt.
Im Gegensatz dazu ist beim zweiten Beispiel (Abbildung 14) diese einfache Steuerung
1
i f ( x < 10 && y > −10) { [ . . . ] }
Abbildung 14.: Komplexere if-Abfrage mit zwei Variablen
von FITIn nicht möglich, da hier zwei verschiedene Variablen Einfluss auf den Ausgang
der Abfrage haben. Daher muss hier die Bedingung aus der Abfrage extrahiert und selbige ein wenig umgeschrieben werden; dies ist in Abbildung 15 zu erkennen.
Die Bedingung aus der Abfrage wurde eins zu eins einer Variablen als Wert zugewiesen. Dies wird durch die Behandlung von Wahrheitswerten im C89- und C99-Standard
ermöglicht [5, S. 55]. Im Standard sind für true und false keine eigenen Datentypen
25
8. Implementierung eines Tests unter FITIn
1
2
int c o n d i t i o n = x < 10 && y > −10;
i f ( condition ) { [ . . . ] }
Abbildung 15.: Extraktion der Bedingung aus der Kontrollstruktur
vorgesehen; sie werden stattdessen durch eine 0 oder eine 1 in einem Integer abgespeichert. Dadurch wird dann die Manipulation durch FITIn stark vereinfacht: es ist durch
eine Negierung des LSB (20 ) möglich, aus den beiden Werten true und false den jeweils
anderen zu erzeugen. Des Weiteren wird diese Variable als Bedingung für die Abfrage
eingesetzt. Nach dem C-Standard hat sich hier nichts geändert, und die eingesetzte Variable erzeugt eine voll funktionsfähige Abfrage [5].
Die Extraktion der Abfrage-Bedingung kann in unterschiedlicher Granularität durchgeführt werden; es ist auch möglich, den Teilbedingungen jeweils eine Variable zuzweisen,
um diese dann getrennt voneinander testen zu können.
In der letzten Abbildung (Abbildung 16) wurde zusätzlich zur Definition der Teilbe1
2
3
4
int condition_X = x < 1 0 ;
int condition_Y = y > −10;
int condition_XY = condition_X && condition_Y ;
i f ( condition_XY ) { [ . . . ] }
Abbildung 16.: Extraktion der Teilbedingungen aus der Kontrollstruktur
dingungen auch die Kombination der beiden Teilbdingungen zur vollständigen - aus den
vorhergehenden Beispielen bekannten - Bedingung eingeführt, um erschöpfendes Testen
zu erlauben.
8.4. Testautomatisierung
Da das erschöpfende Testen sehr umfangreich sein kann (siehe Kapitel 7), ist es hilfreich,
das Testen in manchen Fällen zu automatisieren. Gerade wenn in alle Bits einer Variablen
einmal ein Soft Error injiziert werden muss, lohnt sich der Einsatz einer Automatisierung
über ein Bash-Skript. Das Bash-Skript (vgl. Abbildung 17). führt die Modifikationen des
Steuerungsskripts für Tests durch. Danach werden die Tests dann gestartet. Der genaue
Ablauf ist wie folgt: in Zeile 6 wird die Schleife gestartet, die alle Fälle behandelt. In
Zeile 10 wird das von FITIn genutzte Steuerungsskript auf ein vorgefertigtes Template
zurückgesetzt, in dem nur noch die Bitmaske für den Soft Error eingefügt werden muss
(Zeile 12-13). Dies geschieht durch Verwendung des in Ubuntu integrierten Werkzeugs
sed. Danach wird nur noch Valgrind mit FITIn als Tool aufgerufen (Zeile 15ff).
Zur Auswertung der Tests werden die dazu relevanten Daten in ein für alle Fälle gemeinsames Dateilog geschrieben.
26
8.4. Testautomatisierung
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
#! / b i n / bash
echo "Bash−T e s t i n g with FITIn " ;
# Clear log
rm . /NF. l o g
# Loop through a l l 64 c a s e s
fo r i i n { 1 . . 6 4 }
do
echo " T e s t i n g Case $ i " ;
# Clear lua s c r i p t
cp −f . / NF_caseTemplate . l u a . / NF_caseBash . l u a
# Replace t e m p l a t e ’X ’ with c u r r e n t case number
case_number=$ ( ( i − 1 ) )
s e d −i " s /X/ $case_number / g" . / NF_caseBash . l u a
# Run f i t i n
. . / . . / . . / v a l g r i n d − f i t i n / b i n / v a l g r i n d −−v e r b o s e −−t o o l= f i t i n \
−−l o g − f i l e =NF_caseBash . l o g −−c o n t r o l −s c r i p t=NF_caseBash . l u a \
. / NF_TestBits $ i
done
Abbildung 17.: Bash-Skript zur Automatisierung der Tests
27
9. Test der Behandlungsmethoden
Im Folgenden werden die beiden Ansätze Programmflusskontrolle und Numerische Fehlerkorrektur zum Schutz vor Soft Errors getestet. Dazu werden für beide Tests die gleichen
Bedingungen gelten:
1. Es wird auf eine konkrete These hin getestet.
2. Das CG-Verfahren verwendet den in Abbildung 18 dargestellten Datensatz.
3. Die Tests werden auf dem gleichen System durchgeführt (siehe Kapitel 9.1).
In Bezug auf den Testdatensatz Datensatz muss noch hinzugefügt werden, dass dieser
von einer unabhängigen Implementierung überprüft wurde [15]. Bei normaler Berechnung
(also ohne Soft Error) werden zur Berechnung des Ergebnisses drei Iterationen benötigt.


 
72 −36
0
0
0
1
−36 72 −36

1
0
0


 
 0
 
−36 72 −36
0 

 · x = 1 ,
 0

1
0
−36 72 −36
0
0
0
−36
0
1


0.0694
0.1111



x=
0.1250
0.1111
0.0694
Abbildung 18.: Der für die Berechnung verwendete Testdatensatz
9.1. Testumgebung
Um die Tests nachvollziehen zu können, ist eine genaue Dokumentation der zum Einsatz
kommenden Soft- und Hardware notwendig.
In dieser Arbeit wurde der Linux-Kernel 3.2 eingesetzt; dieser wurde mit dem Betriebssystem Ubuntu in der Version (12.04, 32 bit) verwendet. Ubuntu wurde in der Virtualisierungssoftware Vmware Player (Version 6.0.1) installiert. Im Ubuntu-Betriebssystem
wurden die Algorithmen und Tests mittels der GNU Compiler Collection (Version 4.8.1)
kompiliert und ausgeführt; es wurde der C89-Standard verwendet (vgl. Anhang A.3). Es
wurde mit FITIn (Stand Juni 2014) getestet und die Steuerung von FITIn während der
Tests durch Lua-Skripte durchgeführt.
Die Host-Maschine verfügt über einen Prozessor der aktuellen Haswell-Generation von
Intel (Intel Core i7-4500U) und wird unter Windows 8.1 Pro in der 64 bit-Version betrieben. Davon wurden der virtuellen Maschine zwei Kerne des Prozessors zugeteilt. Die
Prozessor-Befehle wurden durch die automatisch ausgewählte Virtualisierungs-Engine
verarbeitet.
29
9. Test der Behandlungsmethoden
9.2. Test der Programmflusskontrolle
Eine Kombination aus White-Box-Testing und Äquivalenzklassen soll nun zum Testen
verwendet werden. Um den Umfang in einem adäquaten Rahmen zu halten, soll folgende
These überprüft werden:
Die Programmflusskontrolle schützt die Kontrollstrukturen im CG-Verfahren vor einem
Soft Error.
Dafür werden folgende Annahmen getätigt:
• Die Anzahl der Soft Errors beschränkt sich auf 0 oder 1.
• Es werden nur die Kontrollstrukturen des CG-Verfahrens betrachtet.
Daraus folgt, dass Soft Error in sämtlichen Variablen außerhalb der Kontrollstrukturen
nicht in Betrachtung sind. Darauf basierend werden im Folgenden die Testfälle spezifiziert.
9.2.1. Spezifikation der Tests
k=0
k < MAX
&&
||r||2 > ||R||2
k += step
false
true
Berechne
Vektor
Rückgabe
der Lösung
Abbildung 19.: Ablaufdiagramm des CG-Verfahrens (gekürzt)
In Abbildung 19 ist das Ablaufdiagramm des CG-Verfahrens dargestellt. Es ist zu erkennen, dass das Verfahren nur eine Kontrollstruktur enthält; eine for-Schleife (vgl. auch
Kapitel 3.3). Diese enthält zwei Teilbedingungen: k < M AX und ||r||2 > ||R||2 . Damit
sind in der Schleife die beiden Variablen k und step enthalten.
Um diese Kontrollstruktur gemäß der Hypothese lückenlos zu testen, sind jeweils ein Soft
30
9.2. Test der Programmflusskontrolle
Error in die Abbruchbedingung, die Laufvariable k und die Inkrementierung der Laufvariable zu injizieren. Dies generiert die folgendenden elf Testfälle; die die folgende Form
besitzen: Ort des Soft Errors - Resultat, Beschreibung
1. step - zu großer Iterationsschritt, Schleifenbedingung gilt weiterhin
2. step - zu großer Iterationsschritt, Schleifenbedingung gilt nicht mehr
3. step - zu kleiner Iterationsschritt (step >= 0), Schleifenbedingung gilt weiterhin
4. step - zu kleiner Iterationsschritt (step < 0), Schleifenbedingung gilt weiterhin
(dies gilt nur, falls k >= 0 gilt)
5. step - zu kleiner Iterationsschritt (underflow, step < 0), Schleifenbedingung nicht
wie vorgesehen erfüllt (da k < 0)
6. k - k > 0, Schleifenbedingung gilt weiterhin
7. k - k > 0, Schleifenbedingung gilt nicht mehr
8. k - k < 0, Schleifenbedingung gilt weiterhin, der Anfangswert ist jedoch unterschritten
9. ||r||2 > ||R||2 - Schleifenbedingung gilt weiterhin
10. ||r||2 > ||R||2 - Schleifenbedingung gilt nicht mehr
11. k < M AX && ||r||2 > ||R||2 - nach letzter regulärer Iteration, Schleifenbedingung
gilt weiterhin
12. keiner - kein Soft Error tritt auf
Es wird auch der Fall betrachtet, dass ein Soft Error nach der letzten regulären Iteration auftritt. Hier ist nur noch ein Soft Error in der Abbruchbedingung relevant (Testfall
11). Dieser bewirkt, dass nach der letzten gültigen Iteration (Iteration 3), eine weitere
Iteration angestoßen wird, indem er die Schleifenbedingung wieder in Kraft setzt.
Jedoch müssen nicht alle Testfälle umgesetzt werden; dies wird im Folgenden dargestellt
und erläutert.
Bei Betrachtung der Testfälle 6 bis 8 wird schnell deutlich, dass diese eine starke Ähnlichkeit mit den Testfällen 1 bis 5 besitzen. Bei den Tesfällen 1 bis 5 wird die Laufvariable
mit einem (durch einen Soft Error) veränderten Inkrement verrechnet. Selbiges lässt sich
auf die Testfälle mit einem Soft Error in k übertragen; diese lassen sich durch ein verändertes Inkrement nachstellen. Daher können die Testfälle 6 bis 8 übersprungen werden.
Weiterhin kann auch der Testfall 4 übersprungen werden; der Grund dafür besteht in
der fehlenden Möglichkeit, diesen Fall mit einem Soft Error zu realisieren. Ein Soft Error
kann nur ein Bit negieren; um damit aus einem kleinen k eine negative Zahl zu erzeugen,
müsste das höchstwertigste Bit negiert werden. Daraus folgt jedoch eine sehr große, negative Zahl (−215 − 1 + k), welche aber die Definition des Testfalls 4 nicht mehr erfüllt.
31
9. Test der Behandlungsmethoden
Durch die Beschränkung auf das Auftreten eines einzelnen Soft Errors ist es nicht notwendig, die Kombination von verschiedenen Testfällen zu betrachten.
9.2.2. Realisierung
Durch Vergleichsbetrachtungen konnte die Anzahl der zu testenden Fälle reduziert werden. Dennoch wäre für eine erschöpfende Testsuite gemäß der These immer noch eine
sehr viel größere Zahl an Tests notwendig, da jedes einzelne Bit der Variablen step und
k einmal in jeder Iteration durch einen Soft Error modifiziert werden muss. Es ist jedoch
möglich, dies durch die Einführung von Äquivalenzklassen (Kapitel 7.1) signifikant zu
verringern.
Dazu kann die Beschreibung der verschiedenen Testfälle herangezogen werden. In den
Testfällen 1 und 2 ist es ausreichend, ein hochwertiges Bit zu negieren; es ist irrelevant
welches, solange die gestellte Bedingung erfüllt wird. In Fall 3 wird das niedrigstwertige
Bit negiert, und damit das Inkrement für diesen Schleifendurchlauf auf 0 gesenkt. In
Fall 5 führt das Flip des höchstwertigen Bits zum gewünschten Ergebnis: ein negatives
Inkrement, die Größe ist hier irrelevant. Durch die Extraktion der Teilbedingung (vgl.
Kapitel 8.3) in Fall 9 ist auch hier die Stelle des Soft Errors irrelevant, solange dies nicht
das niedrigstwertige Bit ist, da dies sonst Testfall 10 entspricht. Schließlich gelten in Fall
11 die gleichen Bedingungen wie bei Fall 9; es wird ein Soft Error in ein Bit, das nicht das
niedrigstwertigste ist, injiziert. Hier muss jedoch, im Gegensatz zu den vorherigen Fällen,
darauf geachtet werden, dass der Soft Error während des vierten Aufrufs geschieht, um
eine zusätzliche Iteration auszulösen. Abschließend folgt eine Auflistung der Testfälle, die
tatsächlich implementiert werden müssen.
1. step - zu großer Iterationsschritt, Schleifenbedingung gilt weiterhin
2. step - zu großer Iterationsschritt, Schleifenbedingung gilt nicht mehr
3. step - zu kleiner Iterationsschritt (step >= 0), Schleifenbedingung gilt weiterhin
5. step - zu kleiner Iterationsschritt (underflow, step < 0), Schleifenbedingung nicht
wie vorgesehen erfüllt (da k < 0) (Fall 5)
9. ||r||2 > ||R||2 - Schleifenbedingung gilt weiterhin (Fall 9)
10. ||r||2 > ||R||2 - Schleifenbedingung gilt nicht mehr (Fall 10)
11. k < M AX && ||r||2 > ||R||2 - nach letzter regulärer Iteration, Schleifenbedingung
gilt weiterhin (Fall 11)
9.2.3. Testergebnisse
Mit den definierten Tests wurden dann die in Abbildung 20 dargestellten Ergebnisse erzielt. In der Spalte außen links ist die Nummerierung des Falls dargestellt, diese kann
eins zu eins mit der Beschreibung in Kapitel 9.2.1 in Relation gesetzt werden. Die Spalte
darauf enthält den Reset; ist ein Reset aufgetreten (bzw. ist die Programmflusskontrolle
32
9.2. Test der Programmflusskontrolle
ausgelöst worden), so wird in Klammern die Anzahl der Resets angegeben. Anschließend
wird der Grund des Resets angegeben. Darauf folgen noch die Korrektheit des Ergebnisses sowie die Gesamtzahl an benötigten Iterationen, die zur Berechnung des Ergebnis
benötigt wurden.
Es ist anzumerken, dass in sämtlichen Fällen, in denen ein Reset auftritt, die Anzahl
Fall
1
Reset
(Anzahl)
Ja (1)
2
Ja (1)
3
Ja (1)
5
Ja (1)
9
10
Nein
Ja (1)
11
Ja (1)
12
Nein
Grund des
Resets
Falsche
Schrittweite
Auslösen der
Schleifenbedingung
Falsche
Schrittweite
Falsche
Schrittweite
Auslösen der
Schleifenbedingung
Auslösen der
Schleifenbedingung
Korrektes
Ergebnis
ja
Gesamtzahl
Iterationen
3
ja
3
ja
3
ja
3
ja
ja
3
3
ja
3
ja
3
Abbildung 20.: Testergebnisse für die Programmflusskontrolle
maximal 1 beträgt. Auch der in der Tabelle angegebene Grund des Resets entspricht den
in den Testspezifikationen festgelegten Bedingungen für die einzelnen Fälle: bei Fall 2
und 10 ist die Schleifenbedingung ausgehebelt, in den anderen Fällen ist der Grund die
falsche Schrittweite. Zusätzlich führen alle Testfälle trotz eines Soft Errors zum korrekten
Ergebnis, wobei keine weiteren Iterationen benötigt werden. Die Tatsache, dass bei der
Programmflusskontrolle keine weiteren Iterationen notwendig sind, ist jedoch nur für das
CG-Verfahren gesichert.
9.2.4. Evaluation
Anhand der Testergebnisse ist eine positive Auswertung möglich. Da in allen Fällen das
Ergebnis korrekt war, ist die These (siehe Kapitel 9.2) ebenfalls korrekt. Weiterhin zeigt
sich ein sehr gute Effizienz, da keine zusätzlichen Iterationen in einem der Fälle notwendig
war. Zudem sind die Veränderungen des Quellcodes durch das geringe Ausmaß an zusätzlichem Code schnell und einfach durchzuführen. Damit ist die Programmflusskontrolle
33
9. Test der Behandlungsmethoden
ein gutes Verfahren, um das CG-Verfahren vor einem Soft Error zu schützen.
9.3. Test der numerischen Fehlerkorrektur
Nach dem Testen der Programmflusskontrolle folgt nun der Test der numerischen Fehlerkorrektur. Auch hier soll von einer konkreten These ausgehend getestet werden:
Die numerische Fehlerkorrektur schützt das Ergebnis des CG-Verfahrens vor einem SoftError in den Komponenten des Lösungsvektors.
Dabei werden Einschränkungen durch folgende Annahmen vorgenommen:
• Die Anzahl an Soft Errors beschränkt sich auf 0 oder 1.
• Der Soft Error injiziert einen Fehler nach dem letzten Schleifendurchlauf in den
Lösungsvektor.
• Der Umfang beschränkt sich auf den verwendeten Testdatensatz (vgl. Abbildung
18).
Durch die Injektion des Soft Errors in den Lösungsvektor nach der letzten Schleifeniteration werden verschiedene Fälle abgedeckt. Der Soft Error steht damit stellvertretend für
einen Soft Error in einer Variable des CG-Verfahrens. Der genaue Ort im CG-Verfahren
ist dabei irrelevant, solange aus dem Soft Error eine Veränderung der Lösung resultiert.
9.3.1. Spezifikation der Tests
Eine naive Herangehensweise an das Testen der These bedeutet die Injektion eines Soft
Errors in jedes Bit jeder Komponente des Lösungsvektors; dies würde bei dem verwendeten Datensatz (Abbildung 18, die Lösung hat die Dimension fünf) ca. 320 Testfälle
erzeugen. Diese Zahl kann aber wieder durch die Verwendung von Äquivalenzklassen
verringert werden. Da die einzelnen Komponenten des Lösungsvektors die gleiche Größenordnung besitzen, ist es irrelevant, in welche Komponente der Soft Error injiziert wird.
Daher wird von einem Soft Error in der ersten Komponente ausgegangen, was die Testfälle auf 64 - ein Testfall pro Bit – reduziert. Dabei bezeichnet Testfall i eine Injektion
eines Soft Errors in das Bit mit der Maske 2i .
9.3.2. Realisierung
Die Realisierung der ersten Partition ist die einfachste: dazu reicht es aus, das Vorzeichenbit der Zahl zu negieren; der Soft Error wird also in das MSB injiziert [13, S. 4].
Bei den beiden anderen Partitionen wird ein Bash-Skript zur automatisierten Abarbeitung der verschiedenen Bitstellen benutzt. Das Skript erlaubt das Einsetzen des jeweiligen
Bits in das Lua-Steuerungsskript und führt danach den Test aus (siehe Kapitel 8.4). Da
34
9.3. Test der numerischen Fehlerkorrektur
zum Ändern der Größenordnung ein Soft Error im Exponenten der Zahl notwendig ist,
sind hier die elf Bits nach dem Vorzeichen zu adressieren (also MSB – 1 bis MSB –
12) [13, S. 4]. Im Gegensatz dazu ist für eine Manipulation des Wertes die Mantisse zu
adressieren; demnach also die verbleibenden Bits (MSB – 12 bis zum LSB) [13, S. 4].
9.3.3. Testergebnisse
Die mit der numerischen Fehlerkorrektur erzielten Ergebnisse sind in den Abbildungen
21 bis 23 dargestellt. Dabei wurden zur Terminierung der numerischen Fehlerkorrektur
Genauigkeiten von = 10− 3, = 10− 5, = 10− 10 und = 10− 15 verwendet.
Der Test der numerischen Fehlerkorrektur mit einer Genauigkeit von 10−3 erzeugte die
−6
x 10
2.5
1
0.9
0.8
Neuberechnung der Lösung
Relativer Fehler
2
1.5
1
0.5
0.7
0.6
0.5
0.4
0.3
0.2
0.1
0
0
10
20
30
40
Nummer des Testfalls
50
60
70
0
0
10
20
30
40
Nummer des Testfalls
50
60
70
Abbildung 21.: Der relative Fehler (links) und die Anzahl an Neustarts (rechts) bei einer
Genauigkeit von = 10−3 und = 10−5
gleichen Daten wie mit einer Genaugikeit von 10−5 . Daher sind beide Tests in einer Grafik
zusammengefasst. Es ist klar zu erkennen, dass die numerische Fehlerkorrektur zweimal
ausgelöst wird und einen Neustart verursacht. Dies geschieht bei den Testfällen 32 und
64. Zudem verdoppelt sich der relative Fehler mit steigender Wertigkeit des negierten
Bits stetig. Bei einem Neustart ist der Fehler wieder nahezu 0. Der maximale relative
Feher beträgt ca. 2 ∗ 10−6 .
Im Vergleich zu den vorherigen Genauigkeiten ist bei einem von 10−10 die Zahl der
Neustarts stark erhöht. Circa ein Drittel der Testfälle löst die numerische Fehlerkorrektur aus. Der maximale relative Fehler ist auf 2.5 ∗ 10−10 gesunken. Insgesamt zeigt der
relative Fehler das gleiche Bild wie bei = 10−3 . Jedoch sind die Spitzen nach links
verschoben, da mehr Neustarts den Fehler der Testfälle verringert haben. Genau wie bei
= 10−3 ist der Fehler bei einem Neustart nahezu 0.
Abschließend ist die Testreihe für = 10−15 angegeben (Abbildung 37). Es ist zu erkennen, dass ca. 94% der Testfälle mindestens einen Neustart verursachen. Während bei
der einen Hälfte nur ein Neustart auftritt, wird bei der anderen Hälfte das CG-Verfahren
35
9. Test der Behandlungsmethoden
−10
x 10
1
0.9
2.5
Neuberechnung der Lösung
0.8
Relativer Fehler
2
1.5
1
0.7
0.6
0.5
0.4
0.3
0.2
0.5
0.1
0
0
10
20
30
40
Nummer des Testfalls
50
60
70
0
0
10
20
30
40
Nummer des Testfalls
50
60
70
Abbildung 22.: Der relative Fehler (links) und die Anzahl an Neustarts (rechts) bei einer
Genauigkeit von = 10−10
zweimal neu aufgerufen. In zwei Fällen beträgt die Iterationszahl der numerischen Fehlerkorrektur drei. Der maximale Fehler ist auf 3.5 ∗ 10−14 gesunken. Auch hier ist der
Fehler bei einem Neustart nahezu 0.
9.3.4. Evaluation
In den Abbildungen 21 bis 23 wird bestätigt, dass sich die numerische Fehlerkorrektur als
Verfahren zum Schutz vor einem Soft Error im Lösungsvektor des CG-Verfahrens eignet.
Zudem ist der verbleibende Fehler nach einem Neustart sehr gering (nahe 0). Daraus lässt
sich folgern, dass die numerische Fehlerkorrektur ein effektives Verfahren zum Schutz vor
einem Soft Error ist.
Des Weiteren sind drei Neustarts die höchste Anzahl, die zur korrekten Bestimmung der
Lösung benötigt werden. Dies zeigt einen geringen Laufzeitoverhead, was ebenfalls für
das Verfahren spricht.
9.3.5. Vergleich mit Oboril et al.
In Artikel [9] von Oboril et al. ist ebenfalls ein Test mit verschiedenen Testfällen beschrieben. Von Oboril et al. wurde jedoch ein anderer Ansatz als in dieser Arbeit gewählt: anstelle eines systematischen, bitgenauen Tests wurde eine randomisierte Soft
Error-Injektion durchgeführt. Dazu wurde aus einem Vektor zufällig eine Komponente
ausgewählt, und darin ein Bit zufällig negiert. Dabei wurden Wahrscheinlichkeiten, mit
denen ein Soft Error auftritt, in Betracht gezogen. So traten die Soft Errors in den einzelnen Testfällen mit einer Wahrscheinlichkeit von 10−6 , 10−7 , 10−8 usw. bis 10−12 auf.
Zudem wurde eine Matrix der Dimension 2 ∗ 106 und ein von 10−10 verwendet. Um
einen Soft Error zu korrigieren, waren meist mehrere Iterationen der numerischen Fehlerkorrektur notwendig [9].
36
9.4. Fazit
−14
x 10
3.5
3
3
Neuberechnung der Lösung
2.5
Relativer Fehler
2.5
2
1.5
1
2
1.5
1
0.5
0.5
0
0
10
20
30
40
Nummer des Testfalls
50
60
70
0
0
10
20
30
40
Nummer des Testfalls
50
60
70
Abbildung 23.: Der relative Fehler (links) und die Anzahl an Neustarts (rechts) bei einer
Genauigkeit von = 10−15
Aufgrund der abweichenden Herangehensweise durch Oboril et al. ist ein Vergleich zu
den Ergebnissen dieser Arbeit nur sehr begrenzt möglich. Allein die benötigte Anzahl
an Iterationen der numerischen Fehlerkorrektur bei einem Soft Error ist vergleichbar.
Hier besitzt das Ergebnis dieser Arbeit einen geringen Vorteil, da maximal eine Iteration
benötigt wird. Bei einer sehr großen Genauigkeit (10−15 ) steigt die Zahl der notwendigen
Iterationen der numerischen Fehlerkorrektur auf drei. Oboril et al. verweisen hier lediglich darauf, dass in jedem Fall mehrere Iterationen des Verfahrens notwendig sind [9]. Es
besteht jedoch die Möglichkeit, dass bei Oboril et al. in einer Iteration der numerischen
Fehlerkorrektur wieder ein Soft Error aufgetreten ist. Damit würde es sich im Endeffekt
um zwei oder mehr Soft Errors handeln.
9.4. Fazit
Im letzten Kapitel 9 sind die beiden Verfahren Programmflusskontrolle und numerische
Fehlerkorrektur jeweils bezüglich einer konkreten These getestet worden. Die Testergebnisse und die Analysen in den jeweiligen Kapiteln der Verfahren unterstützen folgendes
Fazit: die Programmflusskontrolle bietet erfolgreich Schutz vor einem Soft Error in einer
Kontrollstruktur. Gleiches gilt analog für die numerische Fehlerkorrektur bei einem Soft
Error im Lösungsvektor des CG-Verfahrens. Die Verwendung von durch ECC geschützten Speicher ist nur eingeschränkt hilfreich, da kein umfassender Schutz besteht.
Da die numerische Fehlerkorrektur nicht unterscheidet, an welcher Stelle im CG-Verfahren
der Soft Error genau eintritt, scheint es der Programmflusskontrolle gegenüber überlegen zu sein. Allerdings besitzt die Fehlerkorrektur einen entscheidenen Nachteil: ein Soft
Error kann die Konvergenz des CG-Verfahrens so beeinflussen, dass dieses nicht oder
erst sehr viel später terminiert. Damit ist es möglich, dass ein enormer Laufzeitoverhead
ensteht.
37
9. Test der Behandlungsmethoden
Da die Programmflusskontrolle nur vor einem Soft Error in einer Kontrollstruktur schützt,
besitzen weder die Programmflusskontrolle noch die numerische Fehlerkorrektur insgesamt einen ausschlaggebenden Vorteil. Daher wäre eine Kombination beider Verfahren
für umfassenderen Schutz optimal.
38
10. Zusammenfassung und Ausblick
In dieser Arbeit wurde ein Beitrag zu dem aktuellen Thema der Soft Errors geleistet.
Durch Strahlung induziert, beeinflussen Soft Errors durch die temporäre Negierung eines Bits den Programmablauf mit teils massiven Folgen. Daher ist eine Behandlung und
Korrektur wünschenswert; der weitverbreiteste Ansatz ist die Verwendung von ECCgeschütztem Speicher. Jedoch bietet dies keinen vollständigen Schutz, weshalb hier zwei
andere, softwarebasierte Ansätze vorgestellt wurden: die Programmflusskontrolle als Abwandlung des Defensive Programming, und die numerische Fehlerkorrektur.
Beide Algorithmen wurden im Zusammenhang mit dem Verfahren der konjugierten Gradienten (CG-Verfahren) implementiert; dabei diente das CG-Verfahren zur Verdeutlichung der Auswirkungen. Im Anschluss daran wurde die Funktionsweise der Programmflusskontrolle untersucht. Sie wurde bezüglich des Schutzes vor einem Soft Error in den
Kontrollstrukturen des CG-Verfahren mit einer hundertprozentigen Überdeckung getestet. Das Testergebnis belegt den Schutz durch die Programmflusskontrolle, und zeigt
einen geringen Laufzeitoverhead. Des Weiteren wurde die numerische Fehlerkorrektur
anhand der These getestet, sie biete Schutz vor einem Soft Error im Lösungsvektor des
CG-Verfahrens. Auch hier bestätigt das Testergebnis die Eignung der numerischen Fehlerkorrektur in diesem Anwendungsfall sowie einen geringen Laufzeitoverhead. Es wurde
argumentativ gezeigt, dass eine Kombination der beiden Verfahren optimal ist.
Diese Arbeit beschränkt sich darauf, die Programmflusskontrolle sowie die numerische
Fehlerkorrektur in den für sie vorgesehenen Gebieten zu betrachten. In weiterführenden Betrachtungen könnte es von Interesse sein, dies auf eine erhöhte Anzahl von Soft
Errors oder einen anderen Ort der Modifikation, bspw. das Korrekturverfahren selbst,
auszuweiten. Des Weiteren ist auch eine Kombination der beiden Ansätze möglich, um
möglicherweise einen umfassenderen Schutz zu gewährleisten. Zuletzt ist die Frage, inwiefern die Programmflusskontrolle und die numerische Fehlerkorrektur auf andere Algorithmen übertragen werden können, noch offen. Auch die damit verbundenen Effizienzund Zusatzaufwandsbetrachtungen sind sicherlich interessant.
39
Abbildungsverzeichnis
Abbildungsverzeichnis
1.
Ablaufdiagramm einer if-Abfrage . . . . . . . . . . . . . . . . . . . . . . .
3
2.
3.
Pseudo-Code des Verfahren der konjugierten Gradienten [9, S. 146] . . . .
Implementierung der Datentypen Matrix und Vektor als Array(s) . . . . .
8
9
4.
5.
6.
7.
Beispiel einer Assertion in einer Funktion zur Division . . . . . . . . .
Kontrollstruktur for nach der Anwendung der Programmflusskontrolle
Verhinderung unnötiger Iterationen durch die Kombination if-break .
Algorithmus zur Summe der Zahlen von 1 bis MAX . . . . . . . . . .
8.
Pseudo-Code der numerischen Fehlerkorrektur (vgl. [9, S. 148]) . . . . . . 17
9.
10.
Addition zweier Zahlen, in die ein Soft Error injiziiert werden soll. . . . . 19
Einfache if-Abfrage mit zwei Bedingungen . . . . . . . . . . . . . . . . . 20
11.
12.
13.
14.
15.
16.
17.
Quellcode mit beispielhafter Annotation . . . . . . . . . . . . . . .
Ein beispielhaftes Kontroll-Skript in Lua zur Steuerung von FITIn
Einfache if-Abfrage als Beispiel für eine Kontrollstruktur . . . . . .
Komplexere if-Abfrage mit zwei Variablen . . . . . . . . . . . . . .
Extraktion der Bedingung aus der Kontrollstruktur . . . . . . . . .
Extraktion der Teilbedingungen aus der Kontrollstruktur . . . . . .
Bash-Skript zur Automatisierung der Tests . . . . . . . . . . . . .
.
.
.
.
.
.
.
18.
19.
20.
21.
Der für die Berechnung verwendete Testdatensatz . . . . . . . .
Ablaufdiagramm des CG-Verfahrens (gekürzt) . . . . . . . . . .
Testergebnisse für die Programmflusskontrolle . . . . . . . . . .
Der relative Fehler (links) und die Anzahl an Neustarts (rechts)
Genauigkeit von = 10−3 und = 10−5 . . . . . . . . . . . . .
Der relative Fehler (links) und die Anzahl an Neustarts (rechts)
Genauigkeit von = 10−10 . . . . . . . . . . . . . . . . . . . . .
Der relative Fehler (links) und die Anzahl an Neustarts (rechts)
Genauigkeit von = 10−15 . . . . . . . . . . . . . . . . . . . . .
. . .
. . .
. . .
einer
. . .
einer
. . .
einer
. . .
22.
23.
. .
. .
. .
bei
. .
bei
. .
bei
. .
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
13
14
15
16
23
24
25
25
26
26
27
. 29
. 30
. 33
. 35
. 36
. 37
41
Literaturverzeichnis
Literaturverzeichnis
[1] Burnstein, Ilene: Practical Software Testing. Springer Science+Business Media,
Inc., 2003 (Springer Professional Computing)
[2] Firesmith, Donald G.: A Comparison of Defensive Development and Design by
Contract. In: Technology of Object-Oriented Languages and Systems, IEEE Computer Society, August 1999, S. 258 – 267
[3] GTB Working Party Glossary: ISTQB/GTB Standardglossar der Testbegriffe.
German Testing Board e.V., 2013
[4] Heing-Becker, Marcel: Bitfehlerinjektion in Register auf der Basis von FITIn.
Hamburg, Technische Universität Hamburg-Harburg, Bachelorarbeit, Juni 2013
[5] Joint Technical Committee, Subcommittee SC 22: ISO/IEC 9899:TC2.
Mai 2006 , Kapitel 6.3.1.2 Boolean Type, S. 55
[6] Karnik, Tanay; Hazucha, Peter ; Patel, Jagdish: Characterization of soft errors caused by single event upsets in CMOS processes. In: Dependable and Secure
Computing, IEEE Transactions on 1 (2004), April, Nr. 2, S. 128–143
[7] Myers, Glenford J.; Sandler, Corey ; Badgett, Tom: The art of software testing.
3. Ausgabe. New Jersey : John Wiley & Sons, Inc., 2012
[8] Nocedal, Jorge; Wright, Stephen J.: Conjugate Gradient Methods. In: Numerical
Optimization. 2. Ausgabe. Springer New York, 2006 (Springer Series in Operations
Research and Financial Engineering), Kapitel 5, S. 101–134
[9] Oboril, Fabian; Tahoori, Mehdi B.; Heuveline, Vincent; Lukarski, Dimitar
; Weiss, Jan-Philipp: Numerical Defect Correction as an Algorithm-Based FaultTolerance Technique for Iterative Solvers. In: 17th IEEE Pacific Rim International
Symposium on Dependable Computing, IEEE Computer Society, Dezember 2011, S.
144–153
[10] Pless, V.: Introduction to the Theory of Error-Correcting Codes. Wiley, 1998 (A
Wiley-interscience publication)
[11] Qin, Feng; Lu, S. ; Zhou, Yuanyuan: SafeMem: exploiting ECC-memory for detecting memory leaks and memory corruption during production runs. In: HighPerformance Computer Architecture, 2005. HPCA-11. 11th International Symposium on, 2005, S. 291–302
[12] Shewchuk, Jonathan Richard: An Introduction to the Conjugate Gradient Method
Without the Agonizing Pain. August 1994. – Carnegie Mellon University
43
Literaturverzeichnis
[13] Stevenson, David et al.: IEEE Standard for Binary Floating-Point Arithmetic.
In: ANSI/IEEE Std 754-1985 (1985)
[14] Tu, Jiyuan; Yeoh, Guang Heng ; Liu, Chaoqun: Computational Fluid Dynamics.
2. Auflage. Butterworth-Heinemann, 2012
[15] Universität Ulm, Fakultät Mathematik:
CG-Verfahren.
Internet.
http://www.mathematik.uni-ulm.de/numerik/teaching/ws07/NUM1b/prog/
anleitung01/. Version: 2007/2008, Abruf: 22. Juli 2014
44
Literaturverzeichnis
Begriffe und Abkürzungen
CG-Verfahren
ECC
GCC
MSB
LGS
LSB
VM
Verfahren der konjugierten Gradienten
Error Correction Code
GNU C Compiler
Most Significant Bit, deutsch: höchstwertigstes Bit
Lineares Gleichungssystem
Least Signifcant Bit, deutsch: niedrigstwertigstes Bit
Virtuelle Maschine
45
A. Anhang
A.1. Die Lösung von Ax = b minimiert die quadratische
Form
Sei A symmetrisch. Sei x ein Punkt, der der linearen Gleichung A ∗ x = b (1) genügt
und die quadratische Form f (x) = 12 xT Ax − bT x + c (2) minimiert. e sei ein Fehlerterm.
Dann gilt:
1
f (x + e) = (x + e)T A(x + e) − bT (x + e) + c
2
1 T
1
= x Ax + eT Ax + eT Ae − bT x − bT e + c
2
2
1
1
= xT Ax − bT x + c + eT b + eT Ae − bT e
2
2
1 T
= f (x) + e Ae
2
[12, S. 54]
47
A. Anhang
A.2. Implementierung der Matrix- und Vektoroperationen
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
/∗ A d d i e r t z w e i Vektoren e l e m e n t w e i s e ∗/
void add ( double ∗a , double ∗b , double ∗ s o l )
{
int i = 0 ;
double ∗tmp = m a l l o c ( s i z e o f ( double ) ∗ N ) ;
f o r ( i = 0 ; i < N; i ++)
{
tmp [ i ] = a [ i ] + b [ i ] ;
}
f o r ( i = 0 ; i < N; i ++)
{
s o l [ i ] = tmp [ i ] ;
}
f r e e ( tmp ) ;
}
/∗ S u b t r a h i e r t z w e i Vektoren e l e m e n t w e i s e ∗/
void s u b t r a c t ( double ∗a , double ∗b , double ∗ s o l )
{
double ∗tmp = m a l l o c ( s i z e o f ( double ) ∗ N ) ;
int i = 0 ;
f o r ( i = 0 ; i < N; i ++)
{
tmp [ i ] = a [ i ] − b [ i ] ;
}
f o r ( i = 0 ; i < N; i ++)
{
s o l [ i ] = tmp [ i ] ;
}
f r e e ( tmp ) ;
}
/∗ M u l t i p l i z i e r t e i n e n Vektor mit einem S k a l a r ∗/
void mvs ( double ∗a , double x , double ∗ s o l )
{
int i = 0 ;
double ∗tmp = m a l l o c ( s i z e o f ( double ) ∗ N ) ;
f o r ( i = 0 ; i < N; i ++) tmp [ i ] = 0 ;
f o r ( i = 0 ; i < N; i ++)
48
A.2. Implementierung der Matrix- und Vektoroperationen
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
{
tmp [ i ] = a [ i ] ∗ x ;
}
fo r ( i = 0 ; i < N; i ++)
{
s o l [ i ] = tmp [ i ] ;
}
f r e e ( tmp ) ;
}
/∗ M u l t i p l i z i e r t e i n e Matrix mit einem Vektor ∗/
void mmv ( double ∗∗A, double ∗b , double ∗ s o l )
{
int i = 0 , j = 0 ;
double ∗tmp = m a l l o c ( s i z e o f ( double ) ∗ N ) ;
fo r ( i = 0 ; i < N; i ++) tmp [ i ] = 0 ;
fo r ( i = 0 ; i < N; i ++)
{
fo r ( j = 0 ; j < N; j ++)
{
tmp [ i ] += A[ i ] [ j ] ∗ b [ j ] ;
}
}
fo r ( i = 0 ; i < N; i ++)
{
s o l [ i ] = tmp [ i ] ;
}
f r e e ( tmp ) ;
}
/∗ B i l d e t d i e E u l e r s c h e Norm e i n e s V e k t o r s ∗/
double norm ( double ∗a )
{
double r e s = 0 ;
int i = 0 ;
fo r ( i = 0 ; i < N; i ++)
{
r e s += a [ i ] ∗ a [ i ] ;
}
res = sqrt ( res );
return r e s ;
}
49
A. Anhang
86
87
88
89
90
91
92
93
94
95
96
97
98
99
/∗ B i l d e t das S k a l a r −Produkt z w e i e r Vektoren ∗/
double s c a l a r _ p r o d u c t ( double ∗a , double ∗b )
{
double r e s = 0 ;
int i = 0 ;
f o r ( i = 0 ; i < N; i ++)
{
r e s += a [ i ] ∗ b [ i ] ;
}
return r e s ;
}
A.3. Beispiel eines Kompilierungbefehls
1 g c c −s t d=c89 −g −O1 −I " . / v a l g r i n d − f i t i n / i n c l u d e / v a l g r i n d " \
2 −Wall −Wextra −o CM_Condition ∗ . c −lm
A.4. Inhalte des digitalen Mediums
Auf dem mitgelieferten digitalen Medium ist das Folgende enthalten:
• eine elektronische Version dieser Bachelorarbeit
• Quellcode, Kompilierungsbefehle und Tests der Software aus dieser Bachelorarbeit
Das Medium enthält eine Ordnerstruktur, in der der Quellcode und die Tests der Programme zu finden sind, die für diese Arbeit implementiert wurden. Ausgehend vom Wurzelverzeichnis bachelor folgt das Verzeichnis cg. Für die folgenden Skripte wird davon
ausgegangen, dass in dem Verzeichnis bachelor ein Unterverzeichnis valgrind-fitin
mit der Installation von Valgrind und dem Tool FITIn zu finden ist. In dem Verzeichnis
cg liegt der Quellcode. Während testCG_CM.c die Annotation der Programmflusskontrolle zur Beeinflussung der Bedingung enthält, ist in testCG_CM_step.c der Code für
die Beeinflussung der Schrittweite vorhanden. Des Weiteren ist in testCG_NF.c der Code
für die numerische Fehlerkorrektur enthalten.
Zusätzlich befindet sich im Ordner cg ein Ordner tests, der in zwei weitere Ordner aufgeteilt ist: CM und NF. CM enthält die Steuerungsskripte, Kompilier- und Ausführungsdateien für die verschiedenen Testfälle. Zur Kompilierung wird entweder compile_condition
oder compile_step verwendet; zur Ausführung kann der entsprechende Testfall aufgerufen werden. Analog dazu enthält NF die Tests und den Kompilierungsbefehl für die numerische Fehlerkorrektur. Die Kompilierungsbefehle und Tests sind unter Ubuntu lauffähig
(siehe Kapitel 9.1).
50

Documents pareils