Star Trek 11: Unendliche Weiten Wissenschafliche Software mit .NET <<Presentation Title>> Star Trek 11: Unendliche Weiten Wissenschafliche Software mit .NET Bernd Marquardt Microsoft C++ MVP Microsoft Regional Director Germany Software+Consulting berndm@go-sky.de http://www.go-sky.de
Agenda Einführung .NET-Performance allgemein Die unendlichen Weiten… Ein Beispiel: FFT Die unendlichen Weiten… CCD-Kameras und Bilder Bildbearbeitung, Pixel-Verfahren mit C# Spektroskopie Gauss-Fit von Peaks in einem Spektrum Performance und MT (I/O, OpenMP) Zusammenfassung
Einführung .NET war neu (vor einigen Jahren) Version 1.0, 1.1, 2.0 vom Framework Es sollte mittlerweile ganz gut funktionieren Wie steht es mit der Performance von .NET? Mathematische Funktionen System.Math Rechengenauigkeit IEEE 754 Grafik (2D, 3D) unter Windows DirectX Ausführungsgeschwindigkeit ??? I/O-Performance ???
Einführung Wenn es um schnelles Rechnen ging, gab es immer bestimmte Preferenzen Historie: Maschinensprache (lang, lang ist‘s her) FORTRAN (lang ist‘s her) C (schon mal gehört) C++ (kennt man) .NET??? (in Zukunft??) FORTRAN ist noch nicht ganz aus dem Rennen: Fortran für .NET (Lahey)
Einführung Performance-Probleme können sehr vielschichtig sein: Mangelnde Skalierbarkeit Zu wenig Arbeitsspeicher Langsames Netzwerk Zu langsame Server Schlechtes Scheduling Langsame Peripherie Falsche Programmstruktur Multithreading-Probleme Langsamer Prozessor
System.Math Vielfältige mathematische Funktionen Ca. 30 Methoden und Properties Standard-Mathematik Das ist eigentlich NICHT so viel Kann aber leicht erweitert werden Eigene statische Klassen mit statischen Methoden Siehe „Numerical Reciepts“
Rechengenauigkeit Float: 32 bit Double: 64 bit Decimal: 128 bit Ca. 7 signifikante Stellen -3.402823 x 1038 bis +3.402823 x 1038 Double: 64 bit Ca. 15 signifikante Stellen -1.79769313486232 x 10308 bis +1.79769313486232 x 10308 Decimal: 128 bit -79,228,162,514,264,337,593,543,950,335 bis +79,228,162,514,264,337,593,543,950,335
Rechengenauigkeit Demo: TestIEEE Decimal-Typ ist eher für Finanz-Rechnungen mit großen Zahlen erforderlich Genauigkeit ist über einen bestimmten Wertebereich sehr gut Decimal = Integer (96 bit) + Skalierung + Vorzeichen Und wie ist die Performance? Demo: TestIEEE
Nicht mathematisch, aber wichtig: Strings Hier kommt der Garbage-Collector ins Spiel Verwalteter Speicher Verwaltung kostet Zeit! Gefährlich: string += string; Häufiges Neuanlegen und Zerstören von Objekten TestString TestStringBuilder
String + StringBuilder
StringBuilder Bei vielen (mehr als 5) String-Operationen StringBuilder benutzen Umwandlung in string kostet nichts StringBuilder-Klasse enthält wichtige Methoden Konvertieren nicht immer erforderlich Z.B.: Replace
Generics – oder doch nicht? Früher: Alles mit Collections Generics können ihre Daten im „richtigen“ Typ speichern Kein Boxing und Unboxing nötig (System.Object) Das bringt Performance-Gewinne… …und Typsicherheit TestGenerics
Performance: Allgemein Runtime und JIT-Compiler sind für alle Sprachen gleich Performance-Unterschiede können nur aus den sprach-eigenen Compilern entstehen Analysemöglichkeiten 1. Möglichkeit: Analyse des IL-Codes mit dem Tool ILDASM 2. Möglichkeit: Analyse des vom JIT-Compiler erzeugten Maschinencodes mit DebugBreak();
IL-Code-Unterschiede VB .NET ldc.i4.0 stloc.0 br.s IL_000e ldloc.0 ldc.i4.1 add ldc.i4.s 100 blt.s IL_0006 ldc.i4.0 stloc.0 ... ldloc.0 ldc.i4.1 add.ovf ldc.i4.s 99 ble.s IL_0004
Arithmetik (einfach!) ((double) i + (double) j) * 2.5 VB 6.0 50.610 sek VC++ 6.0 5.160 sek VC .NET unmng. 4.992 sek VC .NET mng. 5.359 sek C# 6.594 sek VB .NET (7.625) 6.598 sek VS 6.0 Asm. VS .NET CLR
Arithmetik (kompliziert!) (((double) i + (double) j) * 2.5) / (i + j + 1) VB 6.0 80.313 sek VC++ 6.0 5.244 sek VC .NET unmng. 5.156 sek VC .NET mng. 5.172 sek C# 5.156 sek VB .NET 5.146 sek VS 6.0 Asm. VS .NET CLR
Arithmetik (esotherisch!) Fast Fourier Transformation Sägezahn aus 65.536 Einzelwerten Daten-Array als lokale Variable VC++ unmng. (lok. Array) 63 msek VC++ mng. (lok. Array) 63 msek Allgemeine Ergebnisse: Mathematische Algorithmen sind sehr schnell – Rechenoperationen ohne Einschränkungen
Arithmetik (esotherisch!) Fast Fourier Transformation Sägezahn aus 1.048.576 Einzelwerten Daten-Array auf dem Heap (mit VC.NET unter Kontrolle des Garbage Collectors) VC++ unmng. (Heap) 2.250 sek VC++ mng. (GC) 2.609 sek Allgemeine Ergebnisse: Auch mit GC sind schnelle Berechnungen möglich
Arithmetik Je komplexer die Berechnungen, desto geringer werden die Unterschiede bei den CLR-Sprachen Allgemeines Ergebnis: Es wurde kein Testbeispiel gefunden, bei dem die CLR-Zeiten abnormal langsam waren Bei allen Testbeispielen waren die CLR-Zeiten immer wesentlich besser, als die Zeiten von VB 6
Optimierung des Codes d += (double) i1 + 7.5 * 11.2 / 2.5; Sprach-Compiler fasst zusammen for-Schleifen mit wenigen Durchgängen JIT macht Loop-Unrolling for(i = 5; i < 5; i++) JIT beachtet die Schleife nicht d += 3 + a – a; JIT erzeugt keinen Code für „+ a - a“ ....
…jetzt kommt die Unendlichkeit Hobby: Astronomie und Astrophysik Man fängt an… …einfach mit gucken… …dann fotografieren… …dann messen… …dann auswerten… …
Equipment
CCD-Technologie Früher: Normale Kleinbild-Kameras Nachteile: Unempfindlich Scharfstellung schwierig Objektpositionierung schwierig Nicht linear Vorteile: Großes Format Kein Notebook erforderlich Kein Strombedarf Farbbild: Einmal belichten
CCD-Technologie Einige Bilder... Heute: CCD-Kameras Chips werden jetzt immer größer (Kleinbildformat) Höchste Quanteneffizienz Man sieht sofort, was man bekommt Es gibt auch schon Farb-CCD‘s Auflösung ist sehr hoch Wichtig: Wenn man eine „gute“ Kamera hat, braucht man auch ein „gutes“ Notebook Einige Bilder...
Bild-Aufnahme Bearbeitung CCD-Kamera wird gekühlt Flat-Bild Dunkelbild Mehrere Rohbilder Final-Bild = (Rohbild – Dunkelbild) / Flat-Bild Alle Final-Bilder addieren Kontrast- und Helligkeitsverstärkung Bearbeitung
Bildbearbeitung Es gibt CCD-Chip mit über 10 Millionen Pixel!!! Alle Bildoperationen dauern entsprechend lange Beispiel: Download mit USB 2.0 ST-402ME 400,000 Pixel 0.8 sek ST-2000XME 2,000,000 Pixel 4.8 sek
Bildbearbeitung Anzahl der Pixel ist ebenfalls kritisch bei allen Bildbearbeitungsoperationen Kontrast und Helligkeit ändern Bild schärfen Bild weichzeichnen Rauschen entfernen Bilder addieren Bilder kalibrieren Dunkelbild und Flat-Bild
Bildbearbeitung BmpWork Zusätzliches Problem: Besser: GetPixel und SetPixel aus der Bitmap-Klasse sind sehr langsam Besser: unsafe-Code mit richtigen Zeigern IntPtr kann nicht benutzt werden: Zeigerarithmetik nicht erlaubt LockBits, Scan0, UnlockBits Deutlich schneller BmpWork
Bildbearbeitung Um das Letzte herauszuholen: Code in unmanaged C++ schreiben und kapseln .NET-Wrapper-Klassen um die öffentlichen C++-Klassen schreiben Aus belibigen .NET-Sprachen benutzen Achtung: Aufruf von unmanaged Code! Benutzung von Zeigern aus VB.NET-Projekten: Code (z.B.) in C#-Klassen kapseln und benutzen
Spektroskopie
Spektrokopie Zerlegung des Lichtes in seine farblichen Bestandteile (sichtbarer Bereich: blau, grün, gelb, rot) Es gibt auch unsichtbare Bereiche: UV-, IR-, Radio-, Röntgen-, Gamma-Strahlung Spezielle Detektoren sind erforderlich Nicht jede Strahlung kann von der Erde aus beobachtet werden Atmosphäre Weltraumbeobachtung von Satelitten aus Hubble, Cobe, Iras,…
Spektrokopie Kontinuierliches Spektrum (z.B. von einer Glühlampe): Spektrum des Sterns Wega im Sternbild Leier (Entf. ca. 30 Lichtjahre):
Spektroskopie Was kann man mit Spektroskopie ermitteln: Chemische Zusammensetzung Einer Sonnen-Atmosphäre (auch Druck) Einer Dunkelwolke Einer Molekülwolke Alter von Sternen Bewegungsgeschwindigkeiten (Doppler-Effekt) Rotationsbewegungen von Sternen Auflösung von Doppelsternen Exo-Planeten …
Spektroskopie Absorptionslinien Emissionlinien Hintergrund strahlt Kontinuum aus Davorliegendes Gas „entnimmt“ Licht um bestimmte angeregte Zustände zu erreichen Emissionlinien Ein Stern regt das umliegende Gas an Das Gas sendet Licht bestimmter Farbe aus, wenn es sich wieder „abregt“
Spektroskopie Einige Spektren... Vorgehensweise: Teleskop Spektrometer Kamera Auswertungs- software Einige Spektren...
Gauss-Fit Die Linien in Spektren sind Gauss-Funktionen 3 Größen: Mittelwert b Breite in halber Höhe a Höhe (hier: 1)
Gauss-Fit Ein Spektrum besteht aus mehreren Peaks Für jeden Peak müssen 3 Parameter bestimmt werden Verfahren: Nullstellensuche nach Newton-Rhapson Man braucht: Die 1. Ableitungen nach allen Parametern Die 2. Ableitungen (Hesse-Matrix) Gibt die Schrittweite bei der Suche an
Gauss-Fit Demo: GaussFit Man versucht, die Parameter einer Gauss-Funktion so zu wählen, dass die Abweichungen von den gemessenen Daten möglichst klein werden Demo: GaussFit
Performance und MT Gibt es Situationen, in denen auf einer Single-Prozessor-Maschine multithreaded Code schneller ist als seriell abgearbeiteter Code?
Performance und MT IO_Calc_MT Antwort: Ja! Besonders dann, wenn unterschiedliche Hardware ausgenutzt wird Rechnen und I/O Rechnen und Grafik … IO_Calc_MT
Performance und OpenMP OpenMP ist eine einfache Möglichkeit für Multithreading bei Algorithmen Für Fortran (Intel) Für C++ (Intel, VS 2005) In OpenMP: Steuerung der Parallelisierung durch C++-Pragma im Code Z.B.: #pragma omp parallel Steueranweisung stehen direkt im Code Mit nativem und mit managed Code Gut anwendbar für Algorithmen
OpenMP Es gibt unterschiedliche Arten der Parallelisierung: Parallelisierung von Schleifen Parallelisierung von Code-Regionen Nicht zu vergessen: Synchronisierung Und wie steht‘s mit der Performance?
Schleifen mit OpenMP Schleifen werden auf mehrere Threads automatisch aufgeteilt Anzahl kann angegeben werden oder ist vom System vorgegeben oder wird dynamisch ausgewählt void saxpy(double z[], double a, double x[], double y, int n) { #pragma omp parallel for for(int i = 0; i < n; i++) z[i] = a * x[i] + y; }
Schleifen mit OpenMP Serielle Ausführung im Master-Thread Parallele Ausführung Automatische Synchronisierung Serielle Ausführung im Master-Thread
Schleifen mit OpenMP Das Verfahren kann auch zu Problemen führen: void test(double x[], double z[], int n) { #pragma omp parallel for for(int i = 1; i < n; i++) z[i] = x[i] + z[i – 1]; // Fehler!!! }
Schleifen mit OpenMP DemoOpenMP Häufig braucht man „Reduktionen“ Es gibt mehrere Threads mit eigenen z-Variablen, die dann zum Schluss zum Endergebnis addiert werden double test(double x[], int n) { double z = 0.0; #pragma omp parallel for reduction(+:z) for(int i = 1; i < n; i++) z += x[i]; } return z; DemoOpenMP
Code-Regionen und -Sektionen Codeteile können ebenfalls parallel laufen Anzahl der Threads kann angegeben werden oder ist vom System vorgegeben Mehrere Sektionen können parallel laufen void test() { #pragma omp parallel num_threads(4) Console::WriteLine(„Hallo, TechTalk!“); }
OpenMP Das hört sich ja sehr einfach an… …es kann aber auch sehr kompliziert werden Das sprengt aber den Rahmen hier! Vorsicht beim Programmieren mit mehreren Threads ist IMMER wichtig Immer die Performance prüfen Immer die Ergebnisse prüfen OpenMP ist gut für Algorithmen OpenMP ist nicht gut für die Parallelisierung von User Interfaces
OpenMP-Performance ACHTUNG: Performance-Tests sind mit Beta-Versionen immer etwas kritisch!!! Trotzdem: Einige Versuche… …auf Single-Prozessor-Maschine (P4, 2.4 GHz, ohne HyperThreading, 400 MHz FSB) ... auf Single-Prozessor-Maschine (P4, 3.2 GHz, mit HyperThreading, 800 MHz FSB) …auf Dual-Prozessor-Maschine (P3, 600 MHz)
OpenMP-Performance Schleifen-Parallelisierung Inn. Schleife Threads ZeitSingle ZeitSingle-HT ZeitDual 20,000 4 2.844 sek 1.953 sek 9.937 sek 20,000 3 2.583 sek 1.360 sek 8.791 sek 20,000 2 2.393 sek 0.766 sek 5.953 sek 20,000 1 0.751 sek 0.625 sek 9.812 sek 20,000 Ohne 0.631 sek 0.532 sek 9.988 sek Single = Single Prozessor Single-HT = Single Prozessor mit Hyperthreading Dual = Dual Prozessor
OpenMP-Performance = ca. 15 % schneller! Schleife mit Reduktion Schleife Threads ZeitSingle ZeitSingle-HT ZeitDual 10,000,000 10 2.494 sek 1.843 sek 9.922 sek 10,000,000 6 2.484 sek 1.859 sek 9.906 sek 10,000,000 4 2.493 sek 1.829 sek 9.937 sek 10,000,000 3 2.473 sek 1.844 sek 9.921 sek 10,000,000 2 2.463 sek 1.844 sek 9.890 sek 10,000,000 1 2.524 sek 2.234 sek 16.219 sek 10,000,000 Ohne 2.444 sek 2.141 sek 15.853 sek = ca. 15 % schneller!
Zusammenfassung .NET ist performant Auch ausreichend für wissenschaftliche Berechnungen Trotzdem: Wenn man „alles rausholen“ will, vorher prüfen JITter werden immer besser Maschinencode: Nur x86-optimiert JIT in Zukunft: Optimierung auf bestimmten Prozessortyp (z.B.: P4-HT) Wissenschaftliche Software ist mit Windows-UI auch leichter zu bedienen
<<Presentation Title>> Questions and Answers