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

Performanzproblem

 

studentTU

Gast


Beiträge: ---
Anmeldedatum: ---
Wohnort: ---
Version: ---
     Beitrag Verfasst am: 05.07.2011, 10:24     Titel: Performanzproblem
  Antworten mit Zitat      
Hallo,
wie das Thema schon sagt habe ich ein kleines Problemchen. Weiß jemand wie man anstatt mit for-Schleifen mit Matrizen rechnet. Ich möchte ein Beispiel sehen. Mein Code ist zu langsam (also braucht ca. 4 Tage) da ich drei for-schleifen habe. Es ist mir klar, dass ich insgesamt 500.000.000 Durchläufe habe. Aber das hätte trotzdem in Java viel schneller funktioniert. Weiß jemand wie ich den Code optimieren könnte. Sollte irgendwie mit Matrizen schneller gehen.
Vielen Dank im Voraus.
Code:
PD=0.025;  % 0.001  0.01 0.2 0.025  0.05  0.1
T=5;    % 5  7  10  20 50
n=1000;  % 100000
Kredit_Anz=1000; % 500 1000 10000 50000
Ausfall=0;
NichtAusfall=0;
AnzAusfall=0;
AnzNicht=0;
Ausfall_3_dim=0;
NichtAusfall_3_dim=0;
lambda=zeros(n,T, Kredit_Anz);
rho=0.12*((1-exp(-50*PD))/(1-exp(-50)))+0.24*(1-(1-exp(-50*PD))/(1-exp(-50)));
b=(0.11852-0.05478*log(PD))*(0.11852-0.05478*log(PD));
F2=(1+(T-2.5)*b)/(1-1.5*b);
F=randn(n,T);
erg = zeros(n);
B = zeros (n, Kredit_Anz);
rho_new = (n);
lambda_new = zeros(n, T);
erg_new = zeros (n);
for numberOfCredits = 1:Kredit_Anz
    if (mod (numberOfCredits,5)==0)
          disp(numberOfCredits)
          %timestamp
    end
  for k=1:n      
     
     for i=1:T
       lambda(k,i, numberOfCredits)=normcdf((norminv(PD,0,1)-sqrt(rho)*F(k,i))/sqrt(1-rho));
       erg(k)=(lambda(k,i)-PD)*F2; % True Kapitalpuffer
      % help(i)=lambda(k,i);
      % B(k)=mean(help(i));     % Mittelwert der Zeile
       B(k, numberOfCredits)=mean(lambda(k,i,:),3); % Mittelwert über 2.Dim
       rho_new(k)=0.12*((1-exp(-50*B(k)))/(1-exp(-50)))+0.24*(1-(1-exp(-50*B(k)))/(1-exp(-50)));
       lambda_new(k,i)=normcdf((norminv(B(k),0,1)-sqrt(rho_new)*F(k,i))/sqrt(1-rho_new));
       b_new=(0.11852-0.05478*log(B(k)))*(0.11852-0.05478*log(B(k)));
       F2_new=(1+(T-2.5)*b_new)/(1-1.5*b_new);
       erg_new(k)=(lambda_new(k,i)-B(k))*F2_new; % Simulated Kapitalpuffer
     end      
  end
end


Thomas84
Forum-Meister

Forum-Meister


Beiträge: 546
Anmeldedatum: 10.02.10
Wohnort: ---
Version: ---
     Beitrag Verfasst am: 05.07.2011, 12:20     Titel:
  Antworten mit Zitat      
soweit ich das sehe steht auf der rechten Seite nie numberOfCredits.

lambda (:,:,i) = lambda(:,:,j)

wahrscheinlich macht der code also noch nicht was er soll.
Private Nachricht senden Benutzer-Profile anzeigen
 
Andreas Goser
Forum-Meister

Forum-Meister


Beiträge: 3.654
Anmeldedatum: 04.12.08
Wohnort: Ismaning
Version: 1.0
     Beitrag Verfasst am: 05.07.2011, 12:27     Titel:
  Antworten mit Zitat      
Bei dem Code gibt es einige Möglichkeiten. Ich habe mal den Profiler genutzt und sehe, dass NORMCDF und NORMINV am meisten fressen.
Code:

norminv(PD,0,1)
 

ist konstant und kann vor allen Schleifen gesetzt werden.
Code:

norminv(B(k),0,1)
 

scheint für jedes k gleich zu sein -> ebenso.

Die Frage ist inwiefern da was interativ berechnet wird oder nicht.

Andreas[/code]
Private Nachricht senden Benutzer-Profile anzeigen E-Mail senden
 
studentTU

Gast


Beiträge: ---
Anmeldedatum: ---
Wohnort: ---
Version: ---
     Beitrag Verfasst am: 05.07.2011, 21:22     Titel:
  Antworten mit Zitat      
erstmal vielen Dank.
Jetzt bin ich weiter gekommen. Zuerst musste ich die äußerste Schleife löschen (mit numberOfCredits). Nun habe ich den folgenden Code (ich habe zeilenweise aus den Schleifen rausgenommen)
Code:
PD=0.01;  % 0.001  0.01 0.2 0.025  0.05  0.1
T=50;    % 5  7  10  20 50
n=10;  % 100000
rho=0.12*((1-exp(-50*PD))/(1-exp(-50)))+0.24*(1-(1-exp(-50*PD))/(1-exp(-50)));
b=(0.11852-0.05478*log(PD))*(0.11852-0.05478*log(PD));
F2=(1+(T-2.5)*b)/(1-1.5*b);
F=randn(n,T);
% ab hier wurden die Zeilen aus der Schleife extrahiert
lambda = normcdf((norminv(PD,0,1)-sqrt(rho)*F(:,:))/sqrt(1-rho));
erg=(lambda(:,:)-PD)*F2;
B=mean(lambda(1:n,:),2); % Mittelwert über 2.Dim
rho_new=0.12*((1-exp(-50*B(:)))/(1-exp(-50)))+0.24*(1-(1-exp(-50*B(:)))/(1-exp(-50)));
% hier beginnt das Problem
lambda_new=normcdf((norminv(B,0,1)-sqrt(rho_new)*F)/sqrt(1-rho_new));
for k=1:n
      if (mod(k,1000)==0)
             disp(k)
      end
     for i=1:T        
       %lambda(k,i, numberOfCredits)=normcdf((norminv(PD,0,1)-sqrt(rho)*F(k,i))/sqrt(1-rho));
       %erg(k)=(lambda(k,i)-PD)*F2; % True Kapitalpuffer
       %B(k)=mean(lambda(k,:),2); % Mittelwert über 2.Dim
       %rho_new(k)=0.12*((1-exp(-50*B(k)))/(1-exp(-50)))+0.24*(1-(1-exp(-50*B(k)))/(1-exp(-50)));
       %lambda_new(k,i)=normcdf((norminv(B(k),0,1)-sqrt(rho_new(k))*F(k,i))/sqrt(1-rho_new(k)));
       b_new(k)=(0.11852-0.05478*log(B(k)))*(0.11852-0.05478*log(B(k)));
       F2_new(k)=(1+(T-2.5)*b_new(k))/(1-1.5*b_new(k));
       erg_new(k,i)=(lambda_new(k,i)-B(k))*F2_new(k); % Simulated Kapitalpuffer
     end      
  end
 

Als ich lambda_new extrahiert hab, bekam ich das Problem folgender Art:
Code:
vector = [5,4,3,2,1];
matrix = [5,4,3,2,1;1,2,3,4,5;6,7,8,9,10;10,9,8,7,6];
 

das ist bei mir in lambda_new sqrt(rho_new)*F. Nun will ich sie so multiplizieren:
Code:
vector(1)*matrix(1,:);
vector(2)*matrix(2,:)
vector(3)*matrix(3,:)
vector(4)*matrix(4,:)
vector(5)*matrix(5,:)
 

Geht das irgendwie in einer Zeile?
 
Martin1986
Forum-Century

Forum-Century


Beiträge: 121
Anmeldedatum: 20.06.11
Wohnort: ---
Version: Win 2016b Linux 2016b
     Beitrag Verfasst am: 05.07.2011, 21:43     Titel:
  Antworten mit Zitat      
Code:
      b_new(k)=(0.11852-0.05478*log(B(k)))*(0.11852-0.05478*log(B(k)));
       F2_new(k)=(1+(T-2.5)*b_new(k))/(1-1.5*b_new(k));
 

warum berechnest du das i mal? reicht doch wenn du es für k einmal berechnest...
ein weiteres perfomance nogo ist das erg_new und co in der for schleife größer werden

also wenn du schon statt matrixenbefehlen schleifen nutzt Wink genau prüfen was wann berechnet werden muss und matrixen und vektoren bitte vorher allokieren Wink
Private Nachricht senden Benutzer-Profile anzeigen
 
studentTU

Gast


Beiträge: ---
Anmeldedatum: ---
Wohnort: ---
Version: ---
     Beitrag Verfasst am: 06.07.2011, 13:33     Titel:
  Antworten mit Zitat      
und noch mal vielen Dank sieht schon deutlich besser aus.
Code:
PD=0.01;  % 0.001  0.01 0.2 0.025  0.05  0.1
T=50;    % 5  7  10  20 50
n=10;  % 100000
rho=0.12*((1-exp(-50*PD))/(1-exp(-50)))+0.24*(1-(1-exp(-50*PD))/(1-exp(-50)));
b=(0.11852-0.05478*log(PD))*(0.11852-0.05478*log(PD));
F2=(1+(T-2.5)*b)/(1-1.5*b);
F=randn(n,T);

%%%%%%%%%%%%%%%%%%%%%
lambda = normcdf((norminv(PD,0,1)-sqrt(rho)*F(:,:))/sqrt(1-rho));
erg=(lambda(:,:)-PD)*F2;
B=mean(lambda(1:n,:),2); % Mittelwert über 2.Dim
rho_new=0.12*((1-exp(-50*B(:)))/(1-exp(-50)))+0.24*(1-(1-exp(-50*B(:)))/(1-exp(-50)));
% lambda_new=normcdf((norminv(B,0,1)-sqrt(rho_new)*F)/sqrt(1-rho_new));
 %   if (mod (numberOfCredits,50)==0)
  %        disp(numberOfCredits)
   % end
  for k=1:n
      if (mod(k,1000)==0)
             disp(k)
      end
     b_new(k)=(0.11852-0.05478*log(B(k)))*(0.11852-0.05478*log(B(k)));
     F2_new(k)=(1+(T-2.5)*b_new(k))/(1-1.5*b_new(k));
     for i=1:T        
       % lambda(k,i, numberOfCredits)=normcdf((norminv(PD,0,1)-sqrt(rho)*F(k,i))/sqrt(1-rho));
       % erg(k)=(lambda(k,i)-PD)*F2; % True Kapitalpuffer
       % B(k)=mean(lambda(k,Smile,2); % Mittelwert über 2.Dim
       % rho_new(k)=0.12*((1-exp(-50*B(k)))/(1-exp(-50)))+0.24*(1-(1-exp(-50*B(k)))/(1-exp(-50)));
       lambda_new(k,i)=normcdf((norminv(B(k),0,1)-sqrt(rho_new(k))*F(k,i))/sqrt(1-rho_new(k)));      
       erg_new(k,i)=(lambda_new(k,i)-B(k))*F2_new(k); % Simulated Kapitalpuffer
     end      
  end
%end
 

Die Frage bleibt jedoch: kann man die Berechnung komplett aus der for-Schleife rausziehen? Also ist in meinem letzten Beitrag gestellte Frage lösbar?
 
Martin1986
Forum-Century

Forum-Century


Beiträge: 121
Anmeldedatum: 20.06.11
Wohnort: ---
Version: Win 2016b Linux 2016b
     Beitrag Verfasst am: 06.07.2011, 17:50     Titel:
  Antworten mit Zitat      
Code:
clear all;
clc;
PD=0.01;  % 0.001  0.01 0.2 0.025  0.05  0.1
T=50;    % 5  7  10  20 50
n=10;  % 100000
rho=0.12*((1-exp(-50*PD))/(1-exp(-50)))+0.24*(1-(1-exp(-50*PD))/(1-exp(-50)));
b=(0.11852-0.05478*log(PD))*(0.11852-0.05478*log(PD));
F2=(1+(T-2.5)*b)/(1-1.5*b);
F=randn(n,T);

%%%%%%%%%%%%%%%%%%%%%
lambda = normcdf((norminv(PD,0,1)-sqrt(rho)*F(:,:))/sqrt(1-rho));
erg=(lambda(:,:)-PD)*F2;
B=mean(lambda(1:n,:),2); % Mittelwert über 2.Dim
rho_new=0.12*((1-exp(-50*B(:)))/(1-exp(-50)))+0.24*(1-(1-exp(-50*B(:)))/(1-exp(-50)));
% lambda_new=normcdf((norminv(B,0,1)-sqrt(rho_new)*F)/sqrt(1-rho_new));
 %   if (mod (numberOfCredits,50)==0)
  %        disp(numberOfCredits)
   % end

   rho_mat_new=repmat(rho_new,1,50);
   B_mat=repmat(B,1,50);
   b_mat_new=(0.11852-0.05478.*log(B(:))).*(0.11852-0.05478.*log(B(:)));
   F2_vec_new=(1+(T-2.5).*b_mat_new(:))./(1-1.5.*b_mat_new(:));
   F2_mat_new=repmat(F2_vec_new,1,50);
   lambda_mat_new=normcdf((norminv(B_mat(:,:),0,1)-sqrt(rho_mat_new(:,:)).*F(:,:))./sqrt(1-rho_mat_new(:,:)));
   erg_mat_new=(lambda_mat_new(:,:)-B_mat(:,:)).*F2_mat_new(:,:);

so sieht das ohne schleifen aus inweit das schneller ist weiß ich nicht die repmat sind sicher nicht so optimal aber sonst weiß ich nicht wie ich einen vektor anders elementweise mit einer Matrix multiplizieren sollte
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: 06.07.2011, 18:52     Titel:
  Antworten mit Zitat      
Hallo Martin1986,

Mit BSXFUN kann man Matrizen und Vektoren elementweise multiplizieren, ohne den Vektor zunächst per REPMAT aufblähen zu müssen.

F(:, :) ist langsamer als F ohne Indizierung zu verwenden.

Gruß, Jan
Private Nachricht senden Benutzer-Profile anzeigen
 
Martin1986
Forum-Century

Forum-Century


Beiträge: 121
Anmeldedatum: 20.06.11
Wohnort: ---
Version: Win 2016b Linux 2016b
     Beitrag Verfasst am: 06.07.2011, 19:16     Titel:
  Antworten mit Zitat      
danke gut zuwissen XD dachte mir schon das nicht der stein der Weisen war mit dem repmats XD aber ich habe das mal getestet
Code:

b_vec_new=(0.11852-0.05478.*log(B)).*(0.11852-0.05478.*log(B));
F2_vec_new=(1+(T-2.5).*b_vec_new(:))./(1-1.5.*b_vec_new(:));
lambda_mat_new=normcdf(bsxfun(@minus,norminv(B,0,1),sqrt(bsxfun(@rdivide,bsxfun(@times,rho_new,F),sqrt(1-rho_new)))));
 

geht leider nicht
ich bekomme folgenden fehler
??? Error using ==> erfc
Input must be real and full.

Error in ==> normcdf at 94
p(todo) = 0.5 * erfc(-z ./ sqrt(2));

Error in ==> perftest at 31
lambda_mat_new=normcdf(bsxfun(@minus,norminv(B,0,1),sqrt(bsxfun(@rdivide,bsxfun(@times,rho_new,F),sqrt(1-rho_new)))));
ohne das normcdf geht es noch und scheint auch minimal schneller zusein...
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: 06.07.2011, 20:41     Titel:
  Antworten mit Zitat      
Hallo StudentTU,

Ich bin von den unterschiedlichen Code-Blöcken in diesem Thread verwirrt. Kannst Du die aktuelle effizienteste Methode nochmal zusammenfassen und posten?

Man kann noch einiges verbessern: "clear all" raubt eine Menge Zeit, weil es alle bereits in den Speicher geladenen Funktionen wieder löscht. Ich habe bis heute noch kein Programm gesehen, in dem "clear all" irgendwie nützlich war.
Die LOG Funktion ist teuer, also wendet man "log(B)" am besten nur einmal an. SUM(X)/size(X,1) ist schneller als MEAN.

Die Ursache für diesen Fehler verstehe ich nicht:
??? Error using ==> erfc
Input must be real and full.

Vielleicht wird das im zusammengefassten Code klar.

Gruß, Jan
Private Nachricht senden Benutzer-Profile anzeigen
 
Martin1986
Forum-Century

Forum-Century


Beiträge: 121
Anmeldedatum: 20.06.11
Wohnort: ---
Version: Win 2016b Linux 2016b
     Beitrag Verfasst am: 06.07.2011, 20:48     Titel:
  Antworten mit Zitat      
Code:
clear all;
clc;
tic
PD=0.01;  % 0.001  0.01 0.2 0.025  0.05  0.1
T=50;    % 5  7  10  20 50
n=10;  % 100000
rho=0.12*((1-exp(-50*PD))/(1-exp(-50)))+0.24*(1-(1-exp(-50*PD))/(1-exp(-50)));
b=(0.11852-0.05478*log(PD))*(0.11852-0.05478*log(PD));
F2=(1+(T-2.5)*b)/(1-1.5*b);
F=randn(n,T);

%%%%%%%%%%%%%%%%%%%%%
lambda = normcdf((norminv(PD,0,1)-sqrt(rho)*F(:,:))/sqrt(1-rho));
erg=(lambda(:,:)-PD)*F2;
B=mean(lambda(1:n,:),2); % Mittelwert über 2.Dim
rho_new=0.12*((1-exp(-50*B(:)))/(1-exp(-50)))+0.24*(1-(1-exp(-50*B(:)))/(1-exp(-50)));


b_vec_new=(0.11852-0.05478.*log(B)).*(0.11852-0.05478.*log(B));
F2_vec_new=(1+(T-2.5).*b_vec_new(:))./(1-1.5.*b_vec_new(:));
lambda_mat_new=normcdf(bsxfun(@minus,norminv(B,0,1),sqrt(bsxfun(@rdivide,bsxfun(@times,rho_new,F),sqrt(1-rho_new)))));

 toc;


ähm das mit den logsachen habe ich noch nicht geändert, die clear all und clc sind nur drin damit ich sicher sein kann das es nicht nur läuft weil noch was gelanden war das kann später noch raus
Private Nachricht senden Benutzer-Profile anzeigen
 
Neues Thema eröffnen Neue Antwort erstellen



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.