2009-07-06 17 views
8

Meine aktuelle Aufgabe besteht darin, einen Monte Carlo Simulation zu optimieren, der Kapitaladäquanzzahlen nach Region für eine Reihe von Obligors berechnet.C# Monte Carlo Incremental Risk Berechnungsoptimierung, Zufallszahlen, parallele Ausführung

Es läuft ungefähr 10 x zu langsam für wo es in der Produktion sein muss und Anzahl oder tägliche Läufe erforderlich sind. Zusätzlich muss die Granularität der Ergebniszahlen irgendwann bis auf den Schreibtisch, möglicherweise auf Buchebene, verbessert werden. Der Code, den ich erhalten habe, ist im Grunde ein Prototyp, der von Geschäftseinheiten in einer Semi-Produktionskapazität verwendet wird.

Die Anwendung ist zur Zeit Single-Threaded so werde ich es machen müssen Multi-Threaded, bei System.Threading.ThreadPool oder die Microsoft aussehen Parallel Extensions Bibliothek, aber ich bin zu .NET 2 auf dem Server beschränkt auf Diese Bank, so muss ich vielleicht den Hafen dieses Kerls, http://www.codeproject.com/KB/cs/aforge_parallel.aspx betrachten.

Ich versuche mein Bestes, um sie auf .NET 3.5 SP1 zu aktualisieren, aber es ist eine große Übung in einer Organisation dieser Größe und möglicherweise nicht in meinen Vertragszeitrahmen möglich.

Ich habe die Anwendung Profil die Studie von dotTrace (http://www.jetbrains.com/profiler) verwendet wird. Welche anderen guten Profiler gibt es? Freie?

Ein Großteil der Ausführungszeit wird ausgegeben Generierung von einheitlichen Zufallszahlen und dann übersetzen diese in eine normalverteilte Zufallszahl. Sie verwenden eine C# Mersenne twister Implementierung. Ich bin mir nicht sicher, wo sie es hinbekommen haben oder ob es der beste Weg ist, um diese (oder die beste Implementierung) zu erreichen, um die einheitlichen Zufallszahlen zu erzeugen. Dann ist dies übersetzt in eine normal verteilte Version für die Verwendung in der Berechnung (Ich habe noch nicht in den Übersetzungscode eingetaucht).

Auch was ist die Erfahrung mit den folgenden?

Alle Alternativen, die Sie kennen? Ich bin ein C# -Entwickler also würde C# bevorzugen, aber ein Wrapper zu C++ sollte kein Problem sein, sollte es?

Vielleicht noch schneller die C++ - Implementierungen zu nutzen. Ich denke, einige dieser Bibliotheken haben die schnellste Methode, um normal verteilte Zufallszahlen ohne den Übersetzungsschritt direkt zu erzeugen. Sie können auch einige andere Funktionen haben, die bei den nachfolgenden Berechnungen hilfreich sind.

Auch macht der Rechner eingeschaltet ist ein Quad-Core Opteron 275, 8 GB Speicher, aber Windows Server 2003 Unternehmen 32-Bit-. Sollte ich ihnen raten, auf ein 64 bit OS zu aktualisieren?Irgendwelche Links zu Artikeln, die diese Entscheidung unterstützen, würden wirklich geschätzt werden.

Wie auch immer, jeder Rat und jede Hilfe, die Sie haben können, wird wirklich geschätzt.

+2

Warum glauben Sie, dass das Werfen weiterer Threads das Problem verbessern wird? –

+0

Derzeit ist der Code single-threaded auf einer Quad-Core-Box, Opteron 275 um genau zu sein. Der Code wird so geschrieben, dass er sequenziell ausgeführt wird. Entweder der Compiler oder der CLR- oder der CPU-Befehlssatz kann den Code am besten erraten und versuchen, Teile davon parallel auszuführen, um die Leistung zu verbessern. Oder ich kann diesen Code so schreiben, dass er in einem parallelen Threaded-Modell ausgeführt wird, was der CLR, dem Compiler und der CPU nahe legt, was gleichzeitig ausgeführt werden kann und diese Anweisungen auf niedrigerer Ebene die Ausführung optimieren lassen. Ihre Gedanken? – m3ntat

+1

8 GB Speicher ist 4 GB Abfall auf 32 Bit ... –

Antwort

4

Ich habe festgestellt, dass der Mersenne Twister schnell ist. Das Problem könnte im Algorithmus (Box-Muller) liegen, um die gleichmäßige Verteilung in Gaußsche Verteilung zu transformieren. Der Standard-Algorithmus wie folgt aussieht:

y1 = sqrt(- 2 ln(x1)) cos(2 pi x2) 
y2 = sqrt(- 2 ln(x1)) sin(2 pi x2) 

Wo x1 und x2 sind einheitliche Zufallszahlen und y1 und y2 die Gaußsche Verteilung Ausgänge sind.

Die Quadratwurzeln sind langsam, aber die trig ist schlimmer, und es ist instabil nahe 0 Taygeta's page zu dem Thema eines schnelleren (in Pseudo-Code) ergibt:

  float x1, x2, w, y1, y2; 

    do { 
      x1 = 2.0 * ranf() - 1.0; 
      x2 = 2.0 * ranf() - 1.0; 
      w = x1 * x1 + x2 * x2; 
    } while (w >= 1.0); 

    w = sqrt((-2.0 * ln(w))/w); 
    y1 = x1 * w; 
    y2 = x2 * w; 

Wenn sie sich nicht verwenden etwas in der Art, können Sie etwas beschleunigen, indem Sie die trigonometrischen Funktionen vermeiden oder sogar die Zufallszahlen vorgenerieren.

+0

Als eine Anmerkung, viele moderne Prozessoren haben eine Montageanleitung für die gleichzeitige Berechnung von sin und cos, und es ist viel billiger als beide sequenziell aufrufen. Es ist in keiner Standardbibliothek, afaik, verfügbar, da es sich um eine prozessorspezifische Funktion handelt. –

+0

Danke @R Ubben, ist dein Vorschlag der gleiche wie dieser http://en.wikipedia.org/wiki/Box-Muller_transformation oder ist das etwas anderes? – m3ntat

+0

Ja, die polare Form, die sie beschreiben. Es ist eine Ablehnungsprobe, also werft man ein paar Zahlen weg, aber es endet immer noch viel schneller. Obwohl ich auch im Bankwesen arbeite, machte ich das zum Vergnügen - globale Beleuchtung in einem Raytracer. Es hat einen Unterschied gemacht. Wenn die Geschwindigkeit immer noch ein Problem ist, könnten Sie mehrere hundert Millionen offline zwischen täglichen Läufen generieren, abhängig davon, wie viel der Lauf verwendet, und sie nur bei Bedarf einlesen. Fällt dann der Vorrat auf die Generation zurück, wenn der Laden erschöpft ist. –

1

Haben Sie in Betracht gezogen, a profiler at your code zu zeigen? Ich habe Fälle gesehen, in denen einfache Korrekturen sehr deutliche Verbesserungen bringen. Wie ein paar Eigenschaften zu Feldern wechseln.

+0

Ich habe versucht, mit dem Test von Dottrace, aber die Ergebnisse waren nicht so granular, werde ich einen Versuch mit RedGate haben, wenn sie eine kostenlose Testversion haben? – m3ntat

+0

Ich denke, sie haben, Ants hat mir den Tag eine Menge Zeit gerettet. –

0

Being eingeschränkt .Net in erster Linie für eine groß angelegte Simulation zu verwenden, werden Sie einiges an Leistung kostet ganz vorne ... aber das sagt ...

Wenn Sie Wenn Sie eine reine C# -Implementierung des Mersenne Twisters ausführen, wird es Ihnen wahrscheinlich schwer fallen, all die Leistung zu optimieren, die Sie daraus ziehen können. Wenn Sie sich den Mersenne Twister reference implementation anschauen, werden Sie feststellen, dass er eine C-Version hat, die stark für SSE-fähige Prozessoren optimiert ist - das ist sehr schnell. Ich glaube nicht, dass es in C# möglich ist (oder zumindest weiß ich nicht, wie), die Verwendung von SSE-Anweisungen mit dieser Optimierungsebene zu erzwingen. Ich würde vorschlagen, einen C++/CLI-Wrapper (oder einen P/Invoke-Wrapper) um die Mersenne Twister-Bibliotheken zu schreiben und zu sehen, wie sich das auf Ihre Leistung auswirkt. Allerdings müssen Sie vorsichtig mit Managed-unmanaged Marshsalling sein, was sich auf Ihre Performance auswirkt, da ich hier in SO weitere Beiträge zu diesem Thema gesehen habe (obwohl ich sie im Moment anscheinend nicht finden kann ...).

Ich kann einige Flamme erzeugen, um das zu sagen, aber wenn Leistung in Ihrer Anwendung ein wichtiges Anliegen ist, wird gut geschriebenes C oder C++ fast immer einer verwalteten oder interpretierten Sprache vorzuziehen sein.

+2

Ich stimme tatsächlich ziemlich stark mit Ihrer letzten Aussage ... C# kann sehr, sehr gut. Es erfordert Profiling, aber nach meiner Erfahrung ist es viel einfacher, C# zu profilieren und es so weit zu verbessern, dass es C und C++ übertreffen kann - besonders wenn Sie die Vorteile der richtigen Bibliotheken nutzen und verstehen, wie man engen, hoch performanten Code schreibt in C#. –

+1

Ich möchte auch konstruktiv nicht zustimmen :) – peterchen

+1

@Reed - Lassen Sie mich abklären - ich spreche nicht über die Leichtigkeit der Profilierung, noch die Tools zur Verfügung, noch die Schwierigkeit der Optimierung. Ich behaupte, dass für jedes Programm, das in einer interpretierten oder verwalteten Sprache geschrieben wird, bewiesen werden kann, dass ein funktional gleiches Programm mit gleicher oder besserer Leistung in einer nicht verwalteten Sprache geschrieben werden kann. –

0

Meine Erfahrung ist, dass die relative Leistung von C# vs. C++ weitgehend davon abhängt, was Sie tun. Eine große Diskussion dieser hier:

C++ performance vs. Java/C#

Für enge Schleifen Mathe tun (sagen Vektor Physik-Berechnungen) C++ ist ein 2-3-mal schneller als C#, obwohl die perf kann durch die zugrunde liegenden Funktionen wie Sqrt dominiert werden ().

Ich habe einen gemischten Ansatz gewählt, den langsamsten Code in C++/OpenMP mit einem verwalteten C++/CLI-Wrapper (wieder) zu implementieren. So können Sie nur "für das bezahlen, was Sie verwenden".

Es gibt eine Zusammenfassung, wie native C/C einzuwickeln ++ mit C++/CLI hier:

http://msdn.microsoft.com/en-us/library/ms235281.aspx

Sobald Sie den Dreh von C++/CLI bekommen es ist ziemlich leicht, die Dinge zum Laufen zu bekommen.

Verwandte Themen