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?

È stato utile?

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.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top