2009-07-06 12 views
8

Il mio compito corrente è quello di ottimizzare uno Monte Carlo Simulation che calcola le cifre di Adeguatezza del capitale per regione per un insieme di Obbligatori.C# Monte Carlo Incremental Risk Calcolo ottimizzazione, numeri casuali, esecuzione parallela

è in esecuzione circa 10 x troppo lento per cui si dovrà essere in produzione e il numero o corse giornaliere necessarie. Inoltre, la granularità delle cifre dei risultati dovrà essere migliorata fino ad arrivare a un livello possibile, a un certo punto, il codice che ho ricevuto è fondamentalmente un prototipo che viene utilizzato dalle unità aziendali in una capacità di semi produzione.

L'applicazione è attualmente single threaded ne avrei bisogno di renderlo multi-threaded, può guardare System.Threading.ThreadPool o Microsoft Parallel Extensions biblioteca ma sto costretto a .NET 2 sul server al questa banca quindi dovrei considerare la porta di questo ragazzo, http://www.codeproject.com/KB/cs/aforge_parallel.aspx.

Sto facendo del mio meglio per farli passare a .NET 3.5 SP1, ma è un esercizio importante in un'organizzazione di queste dimensioni e potrebbe non essere possibile nei miei tempi di contratto.

ho fatto il profilo dell'applicazione utilizzando il processo a dotTrace (http://www.jetbrains.com/profiler). Quali altri buoni profiler esistono? Quelli gratuiti?

Molto del tempo di esecuzione è trascorso generazione di numeri casuali uniformi e poi tradurre a un numero casuale distribuzione normale. Stanno usando un'implementazione C# Mersenne twister. Non sono sicuro di dove l'hanno ottenuto o se è il modo migliore per fare questo (o la migliore implementazione) per generare numeri casuali uniformi. Allora questo è tradotto in un versione normalmente distribuito per l'uso nel calcolo (non ho ancora approfondito il codice di traduzione).

Anche ciò che è l'esperienza utilizzando la seguente?

Eventuali alternative conoscete? Sono uno sviluppatore C# in modo preferirebbe C#, ma un wrapper per C++ non dovrebbe essere un problema, dovrebbe?

Forse ancora più velocemente sfruttando le implementazioni C++. Sto pensando che alcune di queste librerie avranno il metodo più veloce per generare direttamente numeri casuali distribuiti normalmente, senza il passo della traduzione. Inoltre possono avere alcune altre funzioni che saranno utili nei calcoli successivi.

Anche il computer è su è un Quad Core Opteron 275, 8 GB di memoria, ma Windows Server 2003 Enterprise32 bit. Devo consigliare loro di passare a un sistema operativo a 64 bit?Qualsiasi link ad articoli che supportano questa decisione sarebbe davvero apprezzato.

In ogni caso, qualsiasi consiglio e aiuto che si possa avere è molto apprezzato.

+2

Perché credi che buttare più discussioni sul problema migliorerà le cose? –

+0

Attualmente il codice è single threaded in esecuzione su una scatola quad core, Opteron 275 per la precisione. Il codice viene scritto per essere eseguito in sequenza, sia il compilatore che il CLR o il set di istruzioni della CPU possono prendere la migliore ipotesi su come prendere questo codice e tentare di eseguirne alcune parti in parallelo per migliorare le prestazioni. Oppure posso scrivere questo codice per eseguirlo in un modello parallelo filettato in modo efficace suggerendo al CLR, al compilatore, alla CPU cosa può essere eseguito contemporaneamente e lasciare che queste istruzioni di livello inferiore ottimizzino l'esecuzione. I tuoi pensieri? – m3ntat

+1

8 GB di memoria sono 4 GB di rifiuti su 32 bit ... –

risposta

4

Ho trovato il Mersenne Twister essere veloce. Il problema potrebbe essere nell'algoritmo (Box-Muller) per trasformare la distribuzione uniforme in distribuzione gaussiana. L'algoritmo standard assomiglia:

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

Dove X1 e X2 sono numeri casuali uniformi e Y1 e Y2 sono le uscite distribuzione gaussiana.

Le radici quadrate sono lenti, ma il trig è peggio, ed è instabile vicino a 0. Taygeta's page sull'argomento dà uno più veloce (in pseudocodice):

  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; 

Se essi non stanno usando qualcosa del genere, potresti essere in grado di accelerare un po 'le cose evitando le funzioni trigonometriche o anche pre-generando i numeri casuali.

+0

Come nota, molti processori moderni hanno un'istruzione di assemblaggio per il calcolo simultaneo di sin e cos, ed è molto più economico che chiamare in sequenza. Non è disponibile in nessuna libreria standard, perché è una funzione specifica del processore. –

+0

Grazie a @R Ubben, la tua proposta è la stessa di questa http://en.wikipedia.org/wiki/Box-Muller_transformation o è qualcosa di diverso? – m3ntat

+0

Sì, la forma polare che descrivono. Si tratta di un campione di rifiuto, quindi si butta via qualche numero, ma finisce comunque molto più velocemente. Anche se lavoro anche nel settore bancario, lo stavo facendo per godimento: l'illuminazione globale in un raggio laser. Ha fatto la differenza. Se la velocità è ancora un problema, è possibile generare diverse centinaia di milioni di offline tra le esecuzioni giornaliere, a seconda del numero di esecuzioni, e leggerle semplicemente secondo le necessità. Quindi tornare alla generazione se il negozio è esaurito. –

1

Avete considerato il puntamento a profiler at your code? Ho visto casi in cui ci sono correzioni semplici ottenere miglioramenti molto significativi. Come cambiare un paio di proprietà nei campi.

+0

Ho provato con la prova di dottrace ma i risultati non erano così granulari, avrò una prova con RedGate se hanno una prova gratuita? – m3ntat

+0

Penso che lo facciano, le formiche mi hanno salvato un sacco di volte. –

0

Essere costretti a utilizzare .Net, in primo luogo per una simulazione su larga scala sta per costare un bel po 'di prestazioni proprio davanti ... ma che dire ...

Se sei eseguendo una pura implementazione in C# della Mersenne Twister, è probabile che avrai difficoltà a modificare tutte le prestazioni che puoi ottenere. Se controlli Mersenne Twister reference implementation vedrai che hanno una versione C che è fortemente ottimizzata per processori con capacità SSE - questo è molto veloce. Non credo sia possibile in C# (o almeno, non so come) forzare l'uso delle istruzioni SSE con quel livello di ottimizzazione. Suggerirei di scrivere un wrapper C++/CLI (o un wrapper P/Invoke) intorno alle librerie di Mersenne Twister e vedere come ciò influisce sulle tue prestazioni. Tuttavia, dovrai stare attento con le modifiche gestite non gestite che influiscono sul tuo rendimento, visto che ho visto altri post qui su SO su quel problema (anche se non riesco a trovarli adesso ...).

Posso generare un po 'di fiamma per dire questo, ma se le prestazioni sono una preoccupazione significativa nella vostra applicazione, C o C++ ben scritto sarà quasi sempre preferibile a qualsiasi linguaggio gestito o interpretato.

+2

In realtà non sono d'accordo abbastanza forte con la tua ultima affermazione ... C# può funzionare molto, molto bene. Richiede la profilazione, ma nella mia esperienza, è molto più semplice profilare il C# e migliorarlo fino al punto in cui può superare C e C++, specialmente se si sfruttano le librerie giuste e si capisce come scrivere codice molto compatto e altamente performante in C#. –

+1

Anche io non sono d'accordo costruttivo :) – peterchen

+1

@Reed - Lasciatemi chiarire - Non sto parlando della facilità di profilazione, né degli strumenti disponibili, né della difficoltà di ottimizzazione. Sto affermando che per qualsiasi programma scritto in un linguaggio interpretato o gestito, si può dimostrare che un programma funzionalmente uguale con prestazioni uguali o migliori può essere scritto in un linguaggio non gestito. –

0

La mia esperienza è che le prestazioni relative di C# rispetto a C++ dipendono in gran parte da ciò che si sta facendo. Una grande discussione di quella qui:

C++ performance vs. Java/C#

per cicli stretti facendo matematica (ad esempio calcoli di fisica vettoriale) C++ è un 2-3 volte più veloce di C#, anche se il perf può essere dominata dalle funzioni di base come sqrt ().

Ho adottato un approccio a linguaggio misto, (ri) implementando il codice più lento in C++/OpenMP con un wrapper C++/CLI gestito. Questo ti consente di "pagare solo per quello che usi".

C'è una sintesi di come avvolgere nativo C/C++ con C++/CLI qui:

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

Una volta a ottenere il blocco di C++/CLI è abbastanza facile per ottenere le cose in esecuzione.

Problemi correlati