Programm fuer Intel Core Duo optimieren

seadevil schrieb:
Was mich interessieren würde:

Runge-Kutta 4. Ordnung und dann 1 - 5 Minuten Laufzeit? Wie viele Zeitschritte rechnest du?

Ist mir jetzt fast ein bisschen peinlich, aber es sind nur 2.500 Zeitschritte

Werde mich am Wochenende mal durch die angegebenen Webseiten wuehlen.
 
Ich hab die Programme jetzt mal auf meinem 1.33Ghz iBook laufen lassen und kann die Probleme soweit nicht nachvollziehen ...

g++: 6m48.826s
g++ -O2: 4m13.192s
g++ -O2 -mcpu=7450 -maltivec: 4m12.432s

g95: 21m56.837s

(alle Zeiten "user" vom time-Befehl)

Damit weiß ich wirklich nicht weiter ... Sieht ja fast so aus als liefe das ganze Programm unter Rosetta...
Unter Linux mit x86 ergibt sich ein etwas ausgewogeneres Bild (4s vs. 5s).


Optimieren kann man dennoch noch ganz ordentlich. Allerdings eher im Quelltext als in der Kommandozeile. Es wird nämlich einiges doppelt berechnet.

Code:
for (n=0; n<nmax; n++) {
  // Equation for the ground state
  F[n] = -uc*Omega*bef[n]*v[n+nmax];
  // C6 shift
  tmp1 = 0.0;
  for (m=0; m<nmax; m++) {
    tmp1 += VV( n, m, C6, R, dx )*pow( abs( v[m+nmax] ), 2 );
  }
  // Equation for the Rydberg state
  F[n+nmax] = -uc*(tmp1-delta)*v[n+nmax]-uc*Omega*bef[n]*v[n];
}

Mal ganz abgesehen davon, dass ich nicht wirklich Ahnung habe was da so alles passiert ;), sehe ich zumindest, dass da ziemlich oft das (sehr teure) abs der selben komplexen Zahlen gebildet wird. Berechnet man sie nur einmal ...

Code:
double abs2_v[nmax];
for (int i = 0; i < nmax; i++) {
  double a = abs(v[i+nmax]);
  abs2_v[i] = a*a;
}

for (n=0; n<nmax; n++) {
  // Equation for the ground state
  F[n] = -uc*Omega*bef[n]*v[n+nmax];
  // C6 shift
  tmp1 = 0.0;
  for (m=0; m<nmax; m++) {
    tmp1 += VV( n, m, C6, R, dx )*abs2_v[m];
  }
  // Equation for the Rydberg state
  F[n+nmax] = -uc*(tmp1-delta)*v[n+nmax]-uc*Omega*bef[n]*v[n];
}

wird's deutlich schneller.

Und pow(x, 6) schreibt man besser als (lohn allerdings auch nur, weil es sehr häufig aufgerufen wird)
Code:
double inline pow6(double base) {
	double res = base * base;
	return res * res * res;
}

Sowie pow(x, 2) als x * x.

Mit diesen kleinen Änderungen komme ich schon auf 0m34.244s Laufzeit.
 
Nächster Trick:

Code:
double VV_table[nmax * nmax];
for (int n = 0; n < nmax; n++)
  for (int m = 0; m < nmax; m++)
    VV_table[n * nmax + m] = VV(n, m, C6, R, dxBEC);

und alle Vorkommen von
Code:
VV( n, m, C6, R, dx )
durch
Code:
VV_table[n * nmax + m]

Laufzeit: 0m4.027s

;) Jetzt dürfte es auch auf deinem ollen Core Duo flott genug sein.
 
Jo, vielen Dank fuer die Tipps.
Insbesondere, dass das Potenzial V(...) unnoetig oft berechnet wird weiss ich und wollte es auch aendern, dann koennte ich den Code allerdings nicht mehr mit Fortran vergleichen.
Fuer mich ist es (zugegeben) nicht nur interesant das Ding schneller zu machen, sondern rauszufinden warum Fortran so viel schneller ist.
Vielleicht kann man dann naemlich mit den selben Aenderungen bei Fortran noch einiges rausholen.

Was das Programm macht ist folgendes: ... Keine Sorge, ich erzaehls nicht, sonst wirds komatoes.

Vielen Dank auf jeden Fall!
 
booth schrieb:
Fuer mich ist es (zugegeben) nicht nur interesant das Ding schneller zu machen, sondern rauszufinden warum Fortran so viel schneller ist.
Da kann ich leider nicht helfen. Bei mir war überall C schneller...
 
Zurück
Oben Unten