Günther's profileGünther Foidl (gfoidl)PhotosBlogGuestbookMore ![]() | Help |
|
|
December 07 Winter break Hi everybody, now it's gonna be racing time until early May 2010. Informations are available here. I won't report about the races in this blog because this one should remain scientific. ![]() I wish you all the best! Cheers, Günther November 26 Farbkonvertierung RGB <-> HSV und RGB <-> CIE-LabUnter http://www.mycsharp.de/wbb2/thread.php?threadid=78941 gibt es den Code und Erklärungen dazu. Gruss Günther Warum wechselte ich von Fortran nach C#?Fortran ist eine wunderbare Programmiersprache die nur eines kann: Rechnen – und das sehr schnell. Mehr kann Fortran nicht. Vor allem für numerische Aufgaben bietet die Sprache von Fortran sehr viele eingebaute Funktionen und dies ist ungemein hilfreich. Die Compiler (ich habe den Lahey Fujitsu Fortran Compiler verwendet) sind hochoptimierend. Bei dem von mir verwendeten Lahey-Paket sind weiters hoch optimierte Numerik-Packages inkludiert mit denen sich richtiger Hochleistungscode erstellen lässt – und das habe ich auch gemacht. Es stellten sich mir immer die selben Fragen:
Von Fortran selbst gibt es nur Unterstützung für das Lesen und Schreiben von Dateien, sowohl ASCII als auch binär. Gut mit dem ASCII-Format lassen sich CSV-Dateien verarbeiten, aber das reicht in der heutigen Zeit nicht unbedingt aus. Wie wäre es mit direktem Zugriff auf eine Datenbank? Geht über ein Zusatzpaket wie f90SQL, allerdings arbeitet man da ganz unten auf der ODBC-Ebene und ist somit wenig komfortabel – geht allerdings. XML? Über den ASCII-Weg lösbar – praktisch ist dies aber nicht. Das Ergebnis einer Berechnung sind Zahlen – nackte Zahlen die nicht viel Aussagen. Ein Bild wäre hier sehr angebracht. Das ist aber nicht ohne weiters möglich, denn die Sprache sieht dafür nichts vor. Für Fortran gibt es sehr viel OpenSource-Code der zusammengesucht werden will um sich somit eine Art “Framework” zu erstellen. Dies ist aber eine sehr mühselige Aufgabe – davon abgesehen dass man wissen muss was es gibt denn zielloses Suchen nach irgendwelchen Neuigkeiten führt selten zum Ziel ;) Vor fast zwei Jahren und im Zuge eines neuen Projektes stieß ich mit Fortran an die Grenzen. Ich wusste dass es Fortran.net gibt und meine Lahey-Installation bot dies auch. Mehr als ein wenig rumspielen war für mich nicht drin, denn die für .net erweiterte Syntax von Fortran war sehr gewöhnungsbedürfig und machte mir keinen Spass. Die grundlegende Syntax von Fortran ist sehr logisch und einfach aufgebaut. Englischkenntnisse reichen um die Sprache zu beherrschen. Gut ein wenig mehr gehört schon dazu ;) Durch die Erweiterungen für .net wurde die Sprache ein wenig vergewaltigt. Um es auf den Punkt zu bringen: Fortran ist dafür nicht gedacht. Seit jeher entwickelte ich meine Fortran-Programme mit Hilfe von Modulen um eine gewisse Ordnung und Wiederverwendbarkeit zu erzielen. Dieser Stil war auch von OOP inspiriert obgleich es mit OOP nichts zu tun hatte. Meiner Meinung nach lassen sich größere Projekte ohne OOP nur sehr schwer umsetzen und daher ergibt es sich fast zwangsläufig sich in diese Richtung zu orientieren. Wie erwähnt stieß ich mit Fortran an die Grenzen und ich hielt Ausschau nach Alternativen. .net war mir durch die Spielerei mit Fortran.net ein wenig bekannt und ganz besonders gefiel mir das Framework, welches für die meisten wiederkehrenden Aufgaben vorgefertigten Code anbot. Zudem lässt sich mit “der” .net-Sprache C# auch wunderschön OO programmieren. Somit sind/waren meine Hauptbeweggründe C# zu lernen und zu verwenden
Der C#-Compiler ist zwar dumm denn er übersetzt den Code “nur” nach IL-Code und der JITer fürht wenige Optimierungen durch – da dies zur Laufzeit geschieht und somit ein Kompromiss zwischen Verzögerung und Optimierung gefunden werden musste – und dennoch ist C# mittlerweile meine Standardsprache für numerische Berechnungen. Die Zeit für die Berechnung hinkt zwar jener im Vergleich zu Fortran weit hinterher, aber die Berechnung ist nur ein Teil der Gesamtaufgabe und diese gilt es zu betrachten. Dazu gehören Einlesen von Daten, Berechnungen und letztendlich die Ausgabe. Über diesen Zyklus gesehen ist C# im Vorteil. Betrachtet man auch noch den Programmieraufwand der sich bei C# durch die Klassen des Framework im Vergleich zu Fortran erheblich verkürzt ergibt sich ein weiterer bedeutenden Vorteil. Dies geht auch Hand in Hand mit den Vorteilen die sich durch OOP ergeben. Warum nicht Fortran.net? Was wünsche ich mir von .net/C#?
All dies lässt sich zwar selbst im Code durchführen (auch durch eigene Methode, Klassen) aber dies macht den Code nicht unbedingt leserlicher. Leserlicher Code sollte jedoch immer im Vordergrund stehen! Daher ist es naheliegend dass der Compiler dies übernimmt und dabei kann auch unleserlicher IL-Code entstehen. Nichts anderes passiert zB beim yield-Schlüsselwort und bei LINQ. Daher sehe ich kein Problem darin.
Kurz zusammengefasst kann ich festhalten:
Gruss, November 18 Simulated Annealing Auf myCSharp.de habe ich einen Artikel über Simulated Annealing veröffentlich. Siehe http://www.mycsharp.de/wbb2/thread.php?threadid=78641 Viel Spass! November 01 Ich bin auf WikipediaAnders als gewohnt einmal kein Beitrag im Sinne der Programmierung:
Dank Jürgen Thomas gibt es einen Wikipedia-Artikel über mich und meine Speedski-Karriere. Siehe: Günther Foidl Ich fühle mich geehrt da ich Jürgen sehr schätze obwohl ich ihn persönlich nicht kenne - die Bekanntschaft basiert auf unserer gemeinsamen Tätigkeit in Programmier-Foren. Auf diesem Wege bedanke ich mich recht herzlich bei ihm. October 18 Sammon's Projection Sammon's projection is a nonlinear projection method to map a high dimensional space onto a space of lower dimensionality. The full article: Sammon Projecton on codeproject. Happy projecting ;) October 17 Bees algorithm I've just encountered a interesting looking algorithm for optimization: The Bee algorithm. Quite easy to implement - but I have to do further studies on this algorithm to provide more information. The principle is - what a wonder - inspired by bees. Mathematically speaking it can said that the search space is split into smaller spaces whereupon these spaces are explored by the bees. The best position in each space is kept and a next iteration is done until a quality criterion is met. The above link provides further information and some visual demos on how the algorithm works. Sssss September 14 Particle swarm optimization - an improvement to the algorithm?See also: Particle swarm optimization for function optimization A short introduction to my idea of improving the algorithm - further studies have to be done before a full-article can be provided. The general rule for updating the particles velocity is: In the literature two options are common:
The latter lets the algorithm converge faster but the possibility to get stuck (or trapped) in a local optimum raisen. The first option is the classic approach and the exploration of the search-space is higher. In my proposed improvement there’s added another term in the equation for updating the velocity: In this formula c3 is the acceleration coefficient giving the tendency to follow the best solution found so far – aBest (absolute Best), r3 is a even distributed random number in the interval 0 to 1 and x the current position. When c3 = 0 the term vanishes and so the equation is equal to the general rule. c3 = 1 & c2 = 0 goes to the second option. Therefore it’s possible to take the advantages of both option into account. Starting with c3 = 1 to converge fast in the first iterations and then decrease c3 towards 0 so the exploration increases, thus avoiding getting stucked in local optima. As mentioned above further investigation have to be done – I’m going to post updates until the article is ready.
Happy coding September 10 Particle swarm optimization - Article, and other algorithms As promised in the previous post I've writte an article at codeproject: Particle swarm optimization for function optimization There exists other fascinating algorithms for optimizing functions such as:
On performance considerations simulated annealing is my favorite. It's so fast that I can't provide a video for minimizing functions. But when you're familiar to the traveling salesman problem than you know how long the classic combinatorial approch takes. When a computer would take one hour for 30 cities then it would take 40 days for 32 cities. Incredible that a computer needs so long. Watch the video and see how simulated annealing finds the solution for 500 (yes really 500) cities within seconds. I haven't used the classic simulated annealing algorithm, but instead an improved version of mine. Therefore I won't show the code right now - maybe later, now it's may baby ;) The next video shows the same problem - but wiht 100 cities only - with a genetic algorithm (GA) on the left side and simulated annealing (SA) on the right side. You may wonder why SA is by times faster than the GA. The most obvious reason is that SA uses one solution-vector whereas GA uses on vector for each chromosome. A the population used consists of 1000 chromosomes. Thus the GA needs to store 1000 times the solution vector which reduces the speed. When compared by iterations/generations the GA is the one that needs less cycles. Oh, I've stuck to writing - now the video... I can't promise but I've planned to produce a series of posts concerning computational intelligence. Coverd will be:
Happy coding September 08 Particle swarm optimization - A primerWhile playing around with particle swarms I've created a small application that visualizes how the swarm searches for a global minimum in function R² -> R. It fascinated me looking on the behaviour of the artificial swarm. The video shows how a particle swarm searches for the global minimum. Every yellow dot is a particle and the red dot shows the global minimum found so far. The function plot colors high values in red while low values are blue. So the swarm should find the global minimum in a deep blue region. Severel cycles are shown. When I have mor spare time I'm going to provide a guide to "particle swarm optimization". It sounds very difficulty - but it isn't. Compressing the idea behind particle swarms the I can write:
Cu, Günther September 07 Performancevergleich Fortran – C#Unter http://www.mycsharp.de/wbb2/thread.php?threadid=75886 führe ich eine interessante Diskussion (oder Monolog? ;) über die Performance von C# im Vergleich mit Fortran 95. Weiterführende Betrachtung basierend auf diesem Artikel sind in Thomas Enzinger's blog zu finden. Happy coding ;) August 31 HashSet<T> und eigene TypenAnmerkung: Selbiges gilt auch für den Schlüssel TKey im Dictionary<TKey, TValue>! Das HashSet<T> stellt eine leistungsstarke Auflistung dar bei Operationen wie Hinzufügen, Prüfung ob ein Element bereits vorhanden ist, etc. einen O(1)-Vorgang dar. Im Vergleich dazu wären diese Operationen bei einer List<T> O(n)-Vorgänge. Für die .net-Standardtypen kann das HashSet<T> problemlos verwendet werden. Wie schaut die Sache aber mit eigenen Typen aus? Schauen wir uns ein Beispiel an: Der eigene Typ: 1: class FooWrong 2: {3: public int n { get; set; } 4: }Der erste Versuch mit dem HashSet<T> zu arbeiten: 1: FooWrong fooWrong1 = new FooWrong { n = 3 }; 2: FooWrong fooWrong2 = new FooWrong { n = 3 }; 3: int hash1 = fooWrong1.GetHashCode(); 4: int hash2 = fooWrong2.GetHashCode(); 5: 6: HashSet<FooWrong> hsWrong = new HashSet<FooWrong>(); 7: bool add1 = hsWrong.Add(fooWrong1); 8: bool add2 = hsWrong.Add(fooWrong2); Es werden Instanzen des eigenen Typs erstellt mit den jeweils identen Werten. So erwarten wir dass beide Instanzen ident sind. Werden nun aber diese Instanzen zum HashSet hinzugefügt so sind beide enthalten – komisch denn das HashSet sollte doch nur Elemente haben die einzigartig sind. Woher kommt das? Nun kann dem HashSet eine Instanz eines IEqualityComparers<T> übergeben werden oder die Default-Eigenschaft erstellt die Instanz von selbst wenn der Typ die IEquatable<T>-Schnittstelle implementiert. Um obiges Beispiel korrekt zu machen sollte der Code also wie folgt geschrieben werden: Der eigene Typ (implementiert IEquatable<T>): 1: class FooCorrect : IEquatable<FooCorrect> 2: {3: public int n { get; set; } 4: 5: public override int GetHashCode() 6: {7: return n.GetHashCode(); 8: } 9: 10: #region IEquatable<FooCorrect> Member 11: public bool Equals(FooCorrect other) 12: {13: if (other == null) 14: return false; 15: 16: return this.n == other.n; 17: }18: #endregion 19: }Gewünschte Arbeit des HashSets: 1: FooCorrect fooCorrect1 = new FooCorrect { n = 3 }; 2: FooCorrect fooCorrect2 = new FooCorrect { n = 3 }; 3: hash1 = fooCorrect1.GetHashCode(); 4: hash2 = fooCorrect2.GetHashCode(); 5: 6: HashSet<FooCorrect> hsCorrect = new HashSet<FooCorrect>(); 7: add1 = hsCorrect.Add(fooCorrect1); 8: add2 = hsCorrect.Add(fooCorrect2);Da dem HashSet keine Instanz eines Vergleichs übergeben wird verwendet das HashSet eine Instanz des Comparers der über die IEquatable<T>.Default-Eigenschaft erstellt wird. Wie bereits erwähnt wird diese Instanz aus der Schnittstelle IEquatable<T> erstellt. Happy coding ;) August 20 Ausdrucksbäume erleichtern die Arbeit (Exception-Handling)Wie bereits im Blog-Eintrag zu INotifyPropertyChanged verwendet und gezeigt können Ausdrucksbäume auch für das Exception-Handling verwendet werden. Beispiel für eine typische Methode: 1: public void Foo(object argument) 2: {3: if (argument == null) 4: throw new ArgumentNullException("argument"); 5: ... 6: }Mich stört daran wieder dass ich im Konstruktor für ArgumentNullException der Paramater als String-Literal angegeben werden muss. Vor allem wenn der Code rafactored wird gibt es Probleme. Durch Verwendung von Lambda-Ausdrücken kann dies sicherer geschrieben werden. Dazu erstelle ich mir eine (statische) Hilfsklasse: 1: internal static class ExceptionHelper 2: {3: internal static ArgumentNullException ArgumentNull<T>(Expression<Func<T>> exp) 4: {5: return new ArgumentNullException(GetParamName(exp)); 6: }7: //--------------------------------------------------------------------- 8: private static string GetParamName<T>(Expression<Func<T>> exp) 9: {10: MemberExpression me = exp.Body as MemberExpression; 11: return me.Member.Name; 12: } 13: }In dieser Klasse wird in der Methode GetParamName<T> die Expression “zerlegt” und der Bezeichner des Members als String zurückgegeben. Die Methode Foo (das Beispiel) änder sich zu: 1: public void Foo(object argument) 2: {3: if (argument == null) 4: throw ExceptionHelper.ArgumentNull(() => argument); 5: }Es ist ersichtlich dass beim Refactoring die Exception korrekt geworfen wird – eine Änderung des String-Literals (da nicht vorhanden) ist nicht nötig. Happy coding ;) August 14 Kritische Gedanken zur Task Parallel Library (TPL)Mit .net 4.0 ist es für jeden möglich Parallelverarbeitung durchzuführen ohne dass die grundlegenden Kenntnisse von Threading existieren. Dieses und weitere solcher Probleme werden in Zukunft immer öfter auftreten da es sehr verlockend und als Hype gilt mit mehreren Threads zu arbeiten. Ich bin dennoch der Meinung dass dieses Werkzeug nur dann sinnvoll eingesetzt werden kann wenn die Grundlagen wie zB Threadsynchronisation verstanden werden - auch wenn das Werkzeug viel von den Mechanismen die im Hintergrund tätig sind wegabstrahiert. Ich habe zB noch keinen Artikel über das Task-Parallel-Library gesehen der bewusst darauf eingeht welche Probleme sich parallelisieren und nicht parallelisieren lassen. Es ist gut zu überlegen ob die zu verarbeitenden Daten unabhängig voneinander sind - nur dann ist eine Parallelisierung möglich. Die TPL ist also ein Werkzeug das Fluch und Segen gemeinsam ist – je nachdem ob man die Hintergründe kennt oder nicht. Happy hacking ;) August 08 Anonyme Methoden und Closures1: static void Main(string[] args) 2: {3: int i = 0; 4: Action myAction = delegate 5: { 6: Console.WriteLine(i); 7: }; 8: 9: myAction(); 10: i = 666; 11: myAction(); 12: 13: Console.ReadKey(); 14: }In diesem Snippet wird eine anonyme Methode erstellt welche auf den Wert der Variablen i zugreift. Wie kann jedoch auf den Wert zugegriffen werden wenn dieser im Kontext der anonymen Method nicht existiert – er wird ja nicht per Parameter übergeben? Dies wird dadurch gelöst dass die Variable i auf dem Heap erstellt wird (statt auf dem Stack). Dazu erzeugt der Compiler eine Klasse (werden DisplayClass…) genannt welche als öffentliches Feld i hat. Somit kann sowohl in der Main-Methode sowie in der anonymen Methode zugegriffen werden. Dieses Prinzip ähnelt dem der Closures. Definition einer Closure gem. Wikipedia:
Die Definition wird von C# nicht ganz erfüllt denn wie im obigen Beispiel gezeigt wenn sich der Wert von i ändert so ist der Wert in der anonymen Methode auch geändert - i wurde ja auf dem Heap erstellt. Dieser Umstand ist zu berücksichtigen denn die “äußere Variable wird gefangen”. Die Berücksichtigung dessen erfolgt indem eine lokale Kopie der äußeren Variable angelegt wird. Inkorrektes Beispiel1: static void Incorrect() 2: {3: for (int i = 0; i < 10; i++) 4: ThreadPool.QueueUserWorkItem(delegate 5: { 6: Console.WriteLine(i); 7: }); 8: 9: Console.ReadKey(); 10: }Das Beispiel wird in folgenden sinngemäßen Code kompiliert: 1: static void IncorrectCompiled() 2: {3: DisplayClass display = new DisplayClass(); 4: display.i = 0;5: for (display.i = 0; display.i < 10; display.i++) 6: {7: ThreadPool.QueueUserWorkItem(delegate 8: { 9: Console.WriteLine(display.i); 10: }); 11: } 12: 13: Console.ReadKey(); 14: }15: //--------------------------------------------------------------------- 16: private sealed class DisplayClass 17: {18: public int i; 19: //----------------------------------------------------------------- 20: public void Action() 21: { 22: Console.WriteLine(i); 23: } 24: }Es wird somit immer der Wert 10 ausgegeben da dieser Wert nach Beendigung der Schleife dem Wert des öffentlichen Feldes des DisplayClass-Objektes entspricht. Korrektes BeispielUm ein korrekte Ausgabe der Werte von [0, 10) zu erhalten muss wie oben angemerkt die äußere Variable lokal kopiert werden. 1: static void Correct() 2: {3: for (int i = 0; i < 10; i++) 4: {5: int j = i; 6: ThreadPool.QueueUserWorkItem(delegate 7: { 8: Console.WriteLine(j); 9: }); 10: } 11: 12: Console.ReadKey(); 13: }Dieser Code liefert das korrekte Ergebnis und wird zu folgendem kompiliert: 1: static void CorrectCompiled() 2: {3: for (int i = 0; i < 10; i++) 4: {5: DisplayClass displayClass = new DisplayClass(); 6: displayClass.i = i;7: ThreadPool.QueueUserWorkItem(delegate 8: { 9: Console.WriteLine(displayClass.i); 10: }); 11: } 12: 13: Console.ReadKey(); 14: }Es werden also mehrere DisplayClass-Objekte erstellt um den äußeren Zustand gemäß Definition zu fangen. Die Ausgabe ist daher korrekt. Wichtiger HinweisDas Verhalten von Closures muss berücksichtigt werden. Dies gilt auch für LINQ-Abfragen – bei diesen wird ja eine anonyme Methode übergeben und somit müssen Closures berücksichtigt werden. August 06 Visualisierung der Daten einer MatrixIm Entwickler-Forum hab ich einen Beitrag zum Thema Visualisieren der Daten einer Matrix verfasst. Der Link zum Thema: http://entwickler-forum.de/showthread.php?p=201316#post201316. Es ist auch das Demo-Projekt angehängt. Verwendung findet es im konkreten Anwendungsfall in der Visualisierung von Messdaten eines Sensors. Nachfolgend dargestellt ist einmal die Graustufendarstellung und die Darstellung mit Verwendung einer Farbskala. Happy visualizing ;) August 03 Vergleich von GleitkommazahlenIch merke immer wieder dass vielen das Verständnis von Gleitkommazahlen fehlt und deshalb oft eine Vergleich mit == durchgeführt wird. Dies ist aber nicht korrekt. Beispiel: double d1 = 3.3; Beim Ausführen des Code wird die korrekte Ausgabe “gleich” erwartet, es erscheint jedoch “ungleich”. Wie ist das möglich? Ist meine CPU defekt? Die Begründung in diesem Verhalten liegt darin dass Gleitkommazahlen (float, double) im Rechner nur als Näherung einer reellen Zahl dargestellt werden. Es treten also Rundungsfehler auf. In der Numerik gibt es ganze Kapitel über die Behandlung von Fehlern und der Fortpflanzung. So weit gehe ich hier aber nicht. Durchläuft man obigen Code mit dem Debugger und schaut sich die Werte von d1 und d2 an so kann festgehalten werden: d1 3.3 double Also existiert nur ein kleiner Unterschied in beiden Werten, der Vergleich mit == liefert somit korrekt das falsche Ergebnis. Wie werden Gleitkommazahlen verglichen?Es liegt somit Nahe einen Vergleich mit einer Toleranz durchzuführen. Dieses Toleranz wird in der Numerik üblicherweise als Epsilon bezeichnet. Somit muss obiger Code geändert werden zu: if (Math.Abs(d1 - d2) < epsilon) Dies stellt allerdings nur die einfachste (und oft auch falsche Variante) dar. Eine detailliertere Betrachtung hab ich in diesem Foren-Beitrag gegeben. Wie groß soll Epsilon gewählt werden?Die Datentypen System.Single (float) und System.Double (double) bietet eine Konstante namens Epsilon an. Diese entspricht aber nicht der Definition von Epsilon im Sinne der Numerik. Dieses Epsilon stellt die kleinste positive von 0 verschiedene Zahl dar. Epsilon im Sinne der Numerik wird wie folgt berechnet: public static double Epsilon() Es wird die Schleife so lange durchgeführt bis zwei Gleitkommazahlen als gleich erachtet werden. Dieses Epsilon (kann natürlich auch für float errechnet werden) sollte für Vergleiche von Gleitkommazahlen verwendet werden. Epsilon für float: 1,192093E-07 Happy coding ;) August 02 PEX – Tool mit dem Unit-Test automatisch generiert werdenEin sagenhaftes Tool von Microsoft Research. PEX – ein Blick für jeden Unit-Tester - und die es werden wollen lohnt - sich. Geht auch im CommandLine-Modus super. Da ich mich gerade mit diesem Tool spiele kann ich noch keine Beispiele posten – ist aber auch nicht nötig denn die Dokumention beschreibt alles ausführlich (oder im Getting Started ausreichend) so dass durch “spielendes Lernen” keine Anleitung nötig sein sollte. Das einzige was ich schade finde ist dass ich jetzt auf NUnit verzichten kann – welch ein schönes Tool das war….;) Happy testing ;) Rechnen mit der Grafikkarte (GPGPU)In heutigen PCs steckt mit der Grafikkarte gewaltiges Rechenpotential das nicht nur für Computergrafik verwenden werden kann. Nachfolgend wird beispielhaft gezeigt wie mit der Grafikkarte Matritzen multipliziert werden können. Warum mit der Grafikkarte rechnen?Beim Vergleich der Leistungdaten einer Grafikkarte wie zB die Geforce GTX 285 mit einer Leistung von 1062,7 GigaFLOPS [1] und einem Pentium 4 mit 3,2 GHz der “nur” auf 6,4 GigaFLOPS kommt wird klar dass dieses Potential genutzt werden kann. Warum ist die Grafikkarte (GPU – graphics processing unit) so schnell?Eine CPU ist universell ausgelegt und kann prinzipiell alles berechnen während GPUs auf Computergrafik optimiert sind. Zudem arbeiten GPUs als Vektorprozessoren und sind somit hochgradig parallel. Wie kann mit der Grafikkarte gerechnet werden?In den Anfängen von GPGPU wurden Float-Arrays in Bitmaps verpackt um somit eine beliebige Anwendung als Grafikproblem zu tarnen. Wie man sich leicht vorstellen kann ist das Tarnen als Bitmap eine eher schwierige Aufgabe denn das Ergebnis wieder korrekt aus dem Bitmap zu entpacken ist schon eine Kunst. Mit dem Projekt Accelerator von Microsoft Research wird dieses Verfahren verwendet. Firmen wie zB Nvidia haben erkannt dass GPGPU ein neues Geschäftsfeld sein kann und bieten eine Programmierschnittstelle (API) an. Im Falle von Nvidia ist dies die Compute Unified Device Architecture [2]. CUDA ist eine Erweiterung für die Programmiersprache C aber es gibt glücklicherweise einen Wrapper für C# – CUDA.net. Diese Variante kann nur verwendet werden wenn eine Nvidia-Grafikkarte vorhanden ist. Zusätzlich muss das SDK dazu während der Entwicklung vorhanden sein. Mit diesen zwei Projekten steht die Möglichkeit für GPGPU für jeden zur Verfügung. Es liegt aber beim Entwickler abzuwägen ob die Aufgabe für GPGPU geeignet ist. Ich finde die Verwendung von Accelerator angenehmer da diese auf DirectX aufsetzt und somit keine Bindung zu einer spezifischen Grafikkarte existiert. Bei CUDA ist es außerdem nachteilig dass in einer C++-ähnlichen Syntax mit der Grafikkarte interagiert werden muss. BeispielAls Beispiel sei der “Klassiker” für die Parallelisierung – die Matritzenmultiplikation – mit dem Accelerator-Projekt implementiert. Das Projekt besteht nur aus einer DLL und ist somit einfach zu verwenden – es braucht nur die Assembly eingebunden werden (Verweis hinzufügen). 1: public float[,] MatMul(float[,] a, float[,] b) 2: {3: // GPU aktivieren: 4: ParallelArrays.InitGPU(); 5: 6: // Die Matritzen für die GPU erstellen: 7: DisposableFloatParallelArray x = new DisposableFloatParallelArray(a); 8: DisposableFloatParallelArray y = new DisposableFloatParallelArray(b); 9: 10: // Matrix Multiplikation durchführen: 11: FloatParallelArray z = ParallelArrays.Multiply(x, y); 12: 13: // Das Ergebnis der GPU-Berechnung "greifbar" machen: 14: float[,] c; 15: ParallelArrays.ToArray(z, out c); 16: 17: // Speicher freigeben: 18: x.Dispose(); 19: y.Dispose(); 20: 21: // GPU deaktivieren: 22: ParallelArrays.UnInit(); 23: 24: return c; 25: }
Siehe auchQuellenverzeichnis:
|
|
|