WICHTIG: Der Betrieb von goMatlab.de wird privat finanziert fortgesetzt. - Mehr Infos...

Mein MATLAB Forum - goMatlab.de

Mein MATLAB Forum

 
Gast > Registrieren       Autologin?   

Partner:




Forum
      Option
[Erweitert]
  • Diese Seite per Mail weiterempfehlen
     


Gehe zu:  
Neues Thema eröffnen Neue Antwort erstellen

Matlab Monte Carlo Code Optimieren

 

knuck1e$_

Gast


Beiträge: ---
Anmeldedatum: ---
Wohnort: ---
Version: ---
     Beitrag Verfasst am: 01.12.2011, 19:40     Titel: Matlab Monte Carlo Code Optimieren
  Antworten mit Zitat      
Hallo liebe Leute,

ich bin ein Matlab Anfänger, weiß aucher auch, dass Matlab schleifen nur sehr langsam abarbeitet. Viel effizienter wäre eine vektorielle Lösung, kann mir aber leider keine für mein Problem vorstellen.

Code:

function [ ] = MC(N,sigma)
S0=1000;
T=5; %Zeit in Jahren
n=356; %Steps / Jahr
dt=1/n;
r=1.05;
k=2700;
dlh=zeros(1,T*n);
Durchschnitt=0;
alphaa=0;
        for i=1:N
                for j=1:T*n
                   if(j==1) dlh(1,j)=S0*exp((r/n-sigma^2/2)*dt+sigma*sqrt(dt)*randn());
                   else dlh(1,j)=dlh(1,j-1)*exp((r/n-0.5*sigma^2)*dt+sigma*sqrt(dt)*randn());
                   end  
                end
            i
            f(i)=sum(dlh)/(T*n);
            alphaa=alphaa+f(i);
        end
alphaa=alphaa/N
        for k=1:N
            dlhh(k)=(f(k)-alphaa)^2;
        end
sc=sqrt(sum(dlhh)/(N-1))
end
 


Das sollte eine Monte Carlo Simulation einer asiatischen Option sein. DH ich brauch die Aktienkurse die vom vorhergehenden abhängen, sowohl die Mittelwerte.

Da ich aber bis zu 10 Mio Simulationen durchführen soll, dauert das schon eine ganze Weile.
Ich hoffe ihr könnt mir helfen, da ich diese Simulation einigemale durchführen sollte und ich nicht jedesmal Stunden warten möchte.

MFG
knuck1e$


Jan S
Moderator

Moderator


Beiträge: 11.057
Anmeldedatum: 08.07.10
Wohnort: Heidelberg
Version: 2009a, 2016b
     Beitrag Verfasst am: 01.12.2011, 23:00     Titel: Re: Matlab Monte Carlo Code Optimieren
  Antworten mit Zitat      
Hallo knuck1e$_,

Es stimmt, dass Matlab bei Schleifen sehr langsam ist - für die Matlab-Versionen vor 6.5 (Juli 2002). Seitdem sorgt die JIT-Acceleration für eine ordentliche Performance. Wenn die Vektorisierung dazu führt, das optimierte BLAS-Funktionen verwendet werden können, kann eine deutlich schnellere Ausführung bedeuten - muss aber nicht. Falls die Vektorisierung nämlich große temporäre Arrays benötigt, ist der schöne Vorteil schnell dahin, da der Zugriff auf den Speicher weitaus länger dauert als eine kleine Schleife, die vollständig in den Prozessor-Cache passt.

Wenn ich Deinen Code im Editor anschaue, meldet MLint schon einige Probleme. Hast Du eine moderne Matlab-Version? Zumindest seit R2006a sollte man unbedingt auf die MLint-Warnungen hören, wenn man effizienten Code schreiben möchte.

"k=2700;" Löschen, es wird nicht benutzt.
"Durchschnitt=0;" Löschen, ungenutzt.
Ein BEfehl pro Zeile und die JIT-Compilation nicht zu behindern.
Keine Ausgaben ins Command-Window, da dies viel Zeit kostet.
Pre-allocation! "dlhh" in jeder Zeile wachsen zu lassen erzeugt eine exponentiell Laufzeitverlängerung - sehr tückisch.
Du rechnest in jeder Iteration SQRT(dt) aus - einmal reicht. Man kann aber auch gleich das ganze Argument der EXP-Funktion als Konstanten formulieren.
Eine FOR-Schleifen und die erste Iteration per IF umleiten ist teuer. Es ist schneller, den Fall j==1 explizit zu formulieren und die Schleife ab 2 laufen zu lassen.

Ergebnis:
Code:
function sc = MC(N, sigma)
S0 = 1000;
T  = 5;      % Zeit in Jahren
n  = 356;    % Steps / Jahr
dt = 1/n;
r  = 1.05;
Tn = T * n;  % Once only!

C1 = sigma * sqrt(dt);
C2 = (r / n - 0.5 * sigma * sigma) * dt;

f = zeros(1, N);
for i = 1:N
   a = S0 * exp(C2 + C1 * randn);
   S = 0;
   for j = 2:Tn
      b = a * exp(C2 + C1 * randn);
      S = S + b;
      a = b;
   end
   f(i) = S / Tn;
end
alphaa = sum(f);

dlhh = f - alphaa / N;
sc   = sqrt(sum(dlhh .* dlhh) / (N - 1));
end
 

So komme ich bei 10 Wiederholungen for MC(1000, 4) von 7.0 auf 2.1 Sekunden.
Das vektorisieren ist übrigens nicht trivial, da jedes Element der Summe sich auf sein vorhergehendes bezieht. Eine C-Mex-Funktion wäre sinnvoller als eine Vektorisierung.

Gruß, Jan

PS. Bist Du sicher, dass das Jahr 356 Steps enthält?
Private Nachricht senden Benutzer-Profile anzeigen
 
Harald
Forum-Meister

Forum-Meister


Beiträge: 24.501
Anmeldedatum: 26.03.09
Wohnort: Nähe München
Version: ab 2017b
     Beitrag Verfasst am: 01.12.2011, 23:28     Titel:
  Antworten mit Zitat      
Hallo,

mit Vektorisierung sähe es etwa so aus:
Code:
function sc = MC2(N, sigma)
S0 = 1000;
T  = 5;      % Zeit in Jahren
n  = 356;    % Steps / Jahr
dt = 1/n;
r  = 1.05;
Tn = T * n;  % Once only!

C1 = sigma * sqrt(dt);
C2 = (r / n - 0.5 * sigma * sigma) * dt;

f = zeros(1, N);
for i = 1:N
   S = sum(S0*cumprod(exp(C2 + C1*randn(1, Tn-1))));
   f(i) = S / Tn;
end
alphaa = sum(f);

dlhh = f - alphaa / N;
sc   = sqrt(sum(dlhh .* dlhh) / (N - 1));
end

oder noch vektorisierter:
Code:
function sc = MC3(N, sigma)
S0 = 1000;
T  = 5;      % Zeit in Jahren
n  = 356;    % Steps / Jahr
dt = 1/n;
r  = 1.05;
Tn = T * n;  % Once only!

C1 = sigma * sqrt(dt);
C2 = (r / n - 0.5 * sigma * sigma) * dt;


S = sum(S0*cumprod(exp(C2 + C1*randn(Tn-1, N))));
f = S / Tn;
alphaa = sum(f);

dlhh = f - alphaa / N;
sc   = sqrt(sum(dlhh .* dlhh) / (N - 1));
end


Bitte sicherheitshalber überprüfen, ob der Code noch dasselbe macht Wink

Ob Vektorisierung hier sinnvoll ist und in welchem Maße, wird von der Anzahl der Simulationen, der MATLAB-Version und letztlich auch dem Rechner abhängen.
1 Mio. Simulationen könnten z.B. in der Version MC3 den Speicher sprengen Wink Da würde ich dann evtl. auf eine Mischung aus vektorisierter und "normaler" Version zurückgreifen.

Grüße,
Harald
Private Nachricht senden Benutzer-Profile anzeigen
 
Jan S
Moderator

Moderator


Beiträge: 11.057
Anmeldedatum: 08.07.10
Wohnort: Heidelberg
Version: 2009a, 2016b
     Beitrag Verfasst am: 02.12.2011, 01:19     Titel:
  Antworten mit Zitat      
Hallo Harald,

Man kann S0 aus CUMPROD herausziehen, um viele Multiplikationen zu sparen.
Ein kleiner Bug: Man benötigt Tn Terme, nicht Tn-1:

Code:
function sc = MC2(N, sigma)
...
for i = 1:N
   S  = S0 * sum(cumprod(exp(C2 + C1*randn(1, Tn))));
   f(i) = S / Tn;
end
...

Damit komme ich unter Matlab 2009a von 2.19 auf 1.36 Sekunden für MC(1000, 4).
Bzw. für die voll-vektorisierte Funktion:
Code:
...
S = S0 * sum(cumprod(exp(C2 + C1*randn(Tn, N))));
...

Dies benötigt 1.20 Sekunden. (Mit S0 innerhalb der Summe übrigens auch 1.36 Sekunden).
Prima Zeit, Harald!

Bei MC(100000,80) stieg Matlab bei der voll-vektoriesierten (kleiner Scherz) Fassung wegen Speicherproblemen aus (1.3GB freies RAM), während meine gereinigte FOR-Methode immer noch fast die doppelte Zeit Deiner halb-vektorisierten Methde benötigt.

Aber man sieht noch etwas anderes: Das Bereinigen und Vereinfachen des Codes sparte 70% Laufzeit und machte den Code so übersichtlich, dass die Vektorisierung deutlich einfacher wurde. Die teil-vektorisierte Fassung sparte 85% der Laufzeit und die voll-vektorisierte 86%.
Das Vereinfachen macht also zunächst den größten Anteil aus, hat aber auch noch den Vorteil, dass das Debuggen leichter fällt. Zudem lassen sich die Methoden zur Simplifizierung auf alle anderen Programmiersprachen (und auch den Rest des Lebens...) anwenden.

Gruß, Jan
Private Nachricht senden Benutzer-Profile anzeigen
 
knuck1e$_

Gast


Beiträge: ---
Anmeldedatum: ---
Wohnort: ---
Version: ---
     Beitrag Verfasst am: 02.12.2011, 10:22     Titel:
  Antworten mit Zitat      
Vielen dank für die große Beteiligung und die Mithilfe!

Ich hätte noch eine Frage.
Zum Code Teil:
Code:

alphaa = sum(f);

dlhh = f - alphaa / N;
sc   = sqrt(sum(dlhh .* dlhh) / (N - 1));
end
 
 

was macht der .* Operator genau?!
LG
 
Winkow
Moderator

Moderator



Beiträge: 3.842
Anmeldedatum: 04.11.11
Wohnort: Dresden
Version: R2014a 2015a
     Beitrag Verfasst am: 02.12.2011, 10:36     Titel:
  Antworten mit Zitat      
Code:
Private Nachricht senden Benutzer-Profile anzeigen
 
knuck1e$_

Gast


Beiträge: ---
Anmeldedatum: ---
Wohnort: ---
Version: ---
     Beitrag Verfasst am: 02.12.2011, 10:46     Titel:
  Antworten mit Zitat      
Entschuldigung auf das hab ich vergessen. Habs mit google probiert und keine Treffer bekommen.
War im nachhinein wohl auch zu unkonkret.

Habs jetzt nochmal laufen lassen und eigentlich keine merkliche Geschwindgkeitsgewinne feststellen können. Meine Prozessorleistung ist bei 50%, trotz der Einstellung Echtzeit und die Laufvariable steigt "gemächlich". Die 10 Millionen Simulationen die mir mein Bachelorbetreuer vorgeschrieben hat, würde so sicher einige Stunden in Anspruch nehmen. Bin ich an den Grenzen von Matlab oder nur an den Grenzen meiner Intelligenz?

hier nochmal der Code und danke für eure liebe Mithilfe!

Code:

function sc = MC2(N, sigma)
S0 = 1000;
T  = 5;      % Zeit in Jahren
n  = 356;    % Steps / Jahr
dt = 1/n;
r  = 1.05;
Tn = T * n;  % Once only!

C1 = sigma * sqrt(dt);
C2 = (r / n - 0.5 * sigma * sigma) * dt;
for i = 1:N
    i
   S  = S0 * sum(cumprod(exp(C2 + C1*randn(1, Tn))));
   f(i) = S / Tn;
end
alphaa = sum(f)/N
dlhh = f - alphaa;
sc   = sqrt(sum(dlhh .* dlhh) / (N - 1));
end



 
 
Winkow
Moderator

Moderator



Beiträge: 3.842
Anmeldedatum: 04.11.11
Wohnort: Dresden
Version: R2014a 2015a
     Beitrag Verfasst am: 02.12.2011, 11:04     Titel:
  Antworten mit Zitat      
Code:
function sc = MC2(N, sigma)
S0 = 1000;
T  = 5;      % Zeit in Jahren
n  = 356;    % Steps / Jahr
dt = 1/n;
r  = 1.05;
Tn = T * n;  % Once only!

C1 = sigma * sqrt(dt);
C2 = (r / n - 0.5 * sigma * sigma) * dt;
f=zeros(N,1)
for i = 1:N
   S  = S0 * sum(cumprod(exp(C2 + C1*randn(1, Tn))));
   f(i) = S / Tn;
end
alphaa = sum(f)/N
dlhh = f - alphaa;
sc   = sqrt(sum(dlhh .* dlhh) / (N - 1));
end

speicher vorher für f schonmal anlegen und ausgabe ins commandwindow in der schleife lassen ^^
Private Nachricht senden Benutzer-Profile anzeigen
 
Harald
Forum-Meister

Forum-Meister


Beiträge: 24.501
Anmeldedatum: 26.03.09
Wohnort: Nähe München
Version: ab 2017b
     Beitrag Verfasst am: 02.12.2011, 11:09     Titel:
  Antworten mit Zitat      
Hallo,

die Speichervorbelegung ist wichtig und sollte nicht weggelassen werden!
Code:


Es hilft natürlich immer, einen ordentlichen Rechner zu haben. Mein lieber Laptop braucht für 1e5 Simulationen gerade mal 6,5 Sekunden. Auf 1e7 Simulationen wären das rund 10 Minuten, also im Vergleich zur Dauer einer Bachelor-Arbeit recht erträglich.

Mit der Anzeige von i in jeder Iteration braucht der Code bei mir rund doppelt so lang; das würde ich also definitiv lassen. Wenn man einen Fortschrittsbalken will, bietet sich WAITBAR an. Aber Achtung: auch der waitbar sollte nicht in jeder Iteration aktualisiert werden, da das sonst länger dauert als die Rechnung an sich.

Wenn du die Parallel Computing Toolbox hast, kannst du die for-Schleifen parallel ablaufen lassen.
http://www.mathworks.de/products/pa.....-computing/tutorials.html
Das "Quick Success"-Beispiel (3. Teil) sollte für deine Zwecke ausreichen.

Mit dieser kleinen Änderung (MATLAB-Pool öffnen, for --> parfor) komme ich für die Programmlaufzeit auf 2,7 Sekunden.

Für deine Arbeit müssen alleine 3,56*10^12 (!!) Zufallszahlen erzeugt werden, und gearbeitet werden muss natürlich auch noch damit. Das geht also einfach nicht im Millisekundenbereich.

Grüße,
Harald

P.S.: Nochmal die Nachfrage: willst du wirklich mit 356 Tagen rechnen? Das Jahr hat nunmal 365, und wenn du nur mit Geschäftstagen rechnest, wären wir eher bei 256 als 356.
Private Nachricht senden Benutzer-Profile anzeigen
 
Jan S
Moderator

Moderator


Beiträge: 11.057
Anmeldedatum: 08.07.10
Wohnort: Heidelberg
Version: 2009a, 2016b
     Beitrag Verfasst am: 02.12.2011, 11:35     Titel:
  Antworten mit Zitat      
Hallo Harald,

Wieviele Kerne hat Dein Laptop-Prozessor?
Eine Beschleunigung von 6.5 auf 2.7 Sekunden klingt interessant.

Gruß, Jan
Private Nachricht senden Benutzer-Profile anzeigen
 
Harald
Forum-Meister

Forum-Meister


Beiträge: 24.501
Anmeldedatum: 26.03.09
Wohnort: Nähe München
Version: ab 2017b
     Beitrag Verfasst am: 02.12.2011, 11:49     Titel:
  Antworten mit Zitat      
Hallo Jan,

vier Kerne. Ich hätte da natürlich gerne eine noch etwas bessere Beschleunigung, aber man nimmt, was man bekommt.

Grüße,
Harald
Private Nachricht senden Benutzer-Profile anzeigen
 
knuck1e$_

Gast


Beiträge: ---
Anmeldedatum: ---
Wohnort: ---
Version: ---
     Beitrag Verfasst am: 02.12.2011, 12:42     Titel:
  Antworten mit Zitat      
Ps: zu den Tagen, natürlich meinte ich 365 ^^ Sah es schon gar nicht mehr diesen Ziffernsturz! Danke
 
matlabbrig
Forum-Fortgeschrittener

Forum-Fortgeschrittener


Beiträge: 52
Anmeldedatum: 17.06.12
Wohnort: ---
Version: ---
     Beitrag Verfasst am: 09.11.2012, 16:30     Titel:
  Antworten mit Zitat      
Hallo liebes Forum,

ich habe mal diesen alten Thread hochgeholt da es bei mir ebenso um eine MC-Simulation geht und ich Unterstützung in Sachen Laufzeit brauche Smile Bei der erforderlichen Anzahl an Simulationsläufen für meinen gesamten Datensatz lande ich momentan grob überschlagen bei 22 Tagen Rechenzeit Shocked Laughing Embarassed

Meine Simulation soll Folgendes machen:

-Mittels Rolling-Window die Kovarianzmatrix der Aktien ermitteln
-Tageweise multivariate Zufallszahlen mit mu = 0 und sigma = kovarianzmatrix erzeugen
-prüfen ob die generierte Zufallszahl am entsprechenden Tag und für das entsprechende Unternehmen kleiner-gleich oder größer als die zugehörige PD (Ausfallswahrscheinlichkeit) ist
- wenn kleiner-gleich soll sie an der entsprechenden Stelle eine 1 für "Ausfall des Unternehmens" eintragen, andernfalls eine 0
-anschließend die Ausfallsumme berechnen pro Tag, und nach dem Größenanteil des Unternehmens am Gesamtwert der Unternehmen gewichten
-die Ergebnisse eines Tages addieren und als "F" in das Hauptfile zurückgeben Arrow Speicherung pro Durchlauf zwecks Mittelwertbildung erfolgt im Hauptfile


Code:
function F = MC1test(AR, window,PDs,AVs,alldates,numbanks, LGD)
zufallsMat = zeros(numbanks, 1);
F = zeros(1, numel(alldates)-window);
covMat = NaN(numbanks);


for i = 1: numel(alldates)-window
%Asset-Returns pro Durchlauf des Rolling Window einlesen
X = AR(i:i+window,1:numbanks);

%PD und Asset-Value für den Tag nach dem Rolling Window
PD = PDs(i+window, 1:numbanks)';
AV = AVs(i+window, 1:numbanks)';
%Gewichtung nach Assetwert-Anteil am Gesamtwert
total = nansum(AV);
weigth = AV/total;
X(isnan(X)) = [0];
covMat = cov(X);
MU = zeros(1, length(covMat));
SIGMA = covMat;
zufallsMat = mvnrnd(MU, SIGMA)';
%Ausfall = 1, Nichtausfall = 0
zufallsMat(zufallsMat<=PD)=1;
zufallsMat(zufallsMat<1)=0;
temp = zufallsMat.*AV*LGD;
F(1,i) = nansum(temp.*weigth);



end

end

 


Wäre sehr erfreut wenn mir jemand helfen kann wie man das schneller hinbekommt Smile
Private Nachricht senden Benutzer-Profile anzeigen
 
Harald
Forum-Meister

Forum-Meister


Beiträge: 24.501
Anmeldedatum: 26.03.09
Wohnort: Nähe München
Version: ab 2017b
     Beitrag Verfasst am: 09.11.2012, 21:33     Titel:
  Antworten mit Zitat      
Hallo,

auf den ersten Blick schwierig.
Kannst du Testdaten zur Verfügung stellen?
Hast du mal den Profiler drüberlaufen lassen um zu sehen, welche Zeilen die meiste Zeit brauchen?

Grüße,
Harald
Private Nachricht senden Benutzer-Profile anzeigen
 
matlabbrig
Forum-Fortgeschrittener

Forum-Fortgeschrittener


Beiträge: 52
Anmeldedatum: 17.06.12
Wohnort: ---
Version: ---
     Beitrag Verfasst am: 09.11.2012, 21:39     Titel:
  Antworten mit Zitat      
Hallo Harald,

ich werde erstmal den profiler testen, kannte ich noch gar nicht! Melde mich dann gleich nochmal.

Danke!
Private Nachricht senden Benutzer-Profile anzeigen
 
Neues Thema eröffnen Neue Antwort erstellen

Gehe zu Seite 1, 2  Weiter

Einstellungen und Berechtigungen
Beiträge der letzten Zeit anzeigen:

Du kannst Beiträge in dieses Forum schreiben.
Du kannst auf Beiträge in diesem Forum antworten.
Du kannst deine Beiträge in diesem Forum nicht bearbeiten.
Du kannst deine Beiträge in diesem Forum nicht löschen.
Du kannst an Umfragen in diesem Forum nicht mitmachen.
Du kannst Dateien in diesem Forum posten
Du kannst Dateien in diesem Forum herunterladen
.





 Impressum  | Nutzungsbedingungen  | Datenschutz | FAQ | goMatlab RSS Button RSS

Hosted by:


Copyright © 2007 - 2025 goMatlab.de | Dies ist keine offizielle Website der Firma The Mathworks

MATLAB, Simulink, Stateflow, Handle Graphics, Real-Time Workshop, SimBiology, SimHydraulics, SimEvents, and xPC TargetBox are registered trademarks and The MathWorks, the L-shaped membrane logo, and Embedded MATLAB are trademarks of The MathWorks, Inc.