Perché la velocità di questo SOR risolutore dipende l'ingresso?
-
25-09-2019 - |
Domanda
In relazione al mio altra domanda , ho ora modifica la matrice sparse risolutore di utilizzare il metodo SOR (successive over relaxation). Il codice è ora la seguente:
void SORSolver::step() {
float const omega = 1.0f;
float const
*b = &d_b(1, 1),
*w = &d_w(1, 1), *e = &d_e(1, 1), *s = &d_s(1, 1), *n = &d_n(1, 1),
*xw = &d_x(0, 1), *xe = &d_x(2, 1), *xs = &d_x(1, 0), *xn = &d_x(1, 2);
float *xc = &d_x(1, 1);
for (size_t y = 1; y < d_ny - 1; ++y) {
for (size_t x = 1; x < d_nx - 1; ++x) {
float diff = *b
- *xc
- *e * *xe
- *s * *xs - *n * *xn
- *w * *xw;
*xc += omega * diff;
++b;
++w; ++e; ++s; ++n;
++xw; ++xe; ++xs; ++xn;
++xc;
}
b += 2;
w += 2; e += 2; s += 2; n += 2;
xw += 2; xe += 2; xs += 2; xn += 2;
xc += 2;
}
}
Ora la cosa strana è: se io aumento omega
(il fattore di rilassamento), inizia la velocità di esecuzione per dipendono drammaticamente sui valori all'interno delle varie matrici
Per omega = 1.0f
, il tempo di esecuzione è più o meno costante. Per omega = 1.8
, la prima volta, richiede in genere, dire, 5 millisecondi per eseguire questo step()
10 volte, ma questo aumenta gradualmente fino a circa 100 ms durante la simulazione. Se ho impostato omega = 1.0001f
, vedo una conseguenza lieve aumento dei tempi di esecuzione; il omega
più alto va, il tempo di esecuzione più veloce aumenta durante la simulazione.
Dal momento che tutto questo è incorporato all'interno del risolutore fluido, è difficile venire con un esempio standalone. Ma ho salvato lo stato iniziale e rieseguire il risolutore in quello stato ogni passo del tempo, così come la risoluzione per la fase di tempo effettivo. Per lo stato iniziale che è veloce, per il tempo successive fasi incrementalmente più lento. Poiché tutto è parità di altre condizioni, che dimostra che la velocità di esecuzione di questo codice dipende dai valori in quei sei array.
Questo è riproducibile su Ubuntu con g ++, nonché a 64 bit Windows 7 durante la compilazione per 32 bit con VS2008.
ho sentito che valori NaN e Inf può essere più lento per calcoli in virgola mobile, ma non NaN o Infs sono presenti. E 'possibile che la velocità di calcoli galleggiante altrimenti dipende dai valori dei numeri di ingresso?
Soluzione
La risposta breve alla tua ultima domanda è "sì" - denormalizzati (molto vicino a zero) i numeri richiedono un trattamento speciale e possono essere molto più lento. La mia ipotesi è che sono strisciante nella simulazione col passare del tempo. Vedi questo post correlati SO: calcoli in virgola mobile Tempo di esecuzione
Impostazione del controllo a virgola mobile denormals filo a zero dovrebbe prendere cura delle cose con un imapct trascurabile sulla qualità simulazione.
Altri suggerimenti
di Celion risposta risulta essere quella corretta. Il post si collega a dice di accendere filo a zero dei valori denormalizzati:
#include <float.h>
_controlfp(_MCW_DN, _DN_FLUSH);
Tuttavia, questo è solo per Windows. Utilizzando gcc su Linux, ho fatto la stessa cosa con un soffio di linea di montaggio:
int mxcsr;
__asm__("stmxcsr %0" : "=m"(mxcsr) : :);
mxcsr |= (1 << 15); // set bit 15: flush-to-zero mode
__asm__("ldmxcsr %0" : : "m"(mxcsr) :);
Questa è la mia prima x86 assemblaggio mai, in modo che possa probabilmente essere migliorato. Ma lo fa il trucco per me.