Prima di tutto, sono consapevole che questa domanda sembra davvero come se non avessi cercato, ma l'ho fatto, molto.Rendere il disegno di C# mandelbrot più efficiente
Ho scritto un piccolo codice di disegno Mandelbrot per C#, è fondamentalmente un modulo di Windows con un PictureBox su cui disegno il set Mandelbrot.
Il mio problema è che è piuttosto lento. Senza uno zoom profondo, fa un buon lavoro e spostarsi e zoomare è abbastanza fluido, richiede meno di un secondo per disegno, ma una volta che comincio a ingrandire un po 'e raggiungere luoghi che richiedono più calcoli, diventa molto lento.
Su altre applicazioni Mandelbrot il mio computer funziona molto bene su luoghi che funzionano molto più lentamente nella mia applicazione, quindi immagino ci sia molto che posso fare per migliorare la velocità.
ho fatto le seguenti cose per ottimizzarlo:
Invece di usare i metodi SetPixel GetPixel sul oggetto bitmap, ho usato LockBits metodo per scrivere direttamente sulla memoria, che ha reso le cose molto più veloce.
Invece di utilizzare oggetti numerici complessi (con le classi che ho creato io stesso, non quelle incorporate), ho emulato numeri complessi utilizzando 2 variabili, re e im. Questo mi ha permesso di ridurre le moltiplicazioni perché quadrare la parte reale e la parte immaginaria è qualcosa che viene fatto un po 'di tempo durante il calcolo, quindi mi limito a salvare il quadrato in una variabile e riutilizzare il risultato senza bisogno di ricalcolarlo.
Io uso 4 fili per disegnare il Mandelbrot, ogni filo fa un diverso quarto dell'immagine e tutti funzionano simultaneamente. Come ho capito, ciò significa che la mia CPU userà 4 dei suoi core per disegnare l'immagine.
Uso l'algoritmo del tempo di fuga, che come ho capito è il più veloce?
Ecco la mia come mi muovo tra i pixel e calcolare, è commentata quindi spero è comprensibile:
//Pixel by pixel loop:
for (int r = rRes; r < wTo; r++)
{
for (int i = iRes; i < hTo; i++)
{
//These calculations are to determine what complex number corresponds to the (r,i) pixel.
double re = (r - (w/2))*step + zeroX ;
double im = (i - (h/2))*step - zeroY;
//Create the Z complex number
double zRe = 0;
double zIm = 0;
//Variables to store the squares of the real and imaginary part.
double multZre = 0;
double multZim = 0;
//Start iterating the with the complex number to determine it's escape time (mandelValue)
int mandelValue = 0;
while (multZre + multZim < 4 && mandelValue < iters)
{
/*The new real part equals re(z)^2 - im(z)^2 + re(c), we store it in a temp variable
tempRe because we still need re(z) in the next calculation
*/
double tempRe = multZre - multZim + re;
/*The new imaginary part is equal to 2*re(z)*im(z) + im(c)
* Instead of multiplying these by 2 I add re(z) to itself and then multiply by im(z), which
* means I just do 1 multiplication instead of 2.
*/
zRe += zRe;
zIm = zRe * zIm + im;
zRe = tempRe; // We can now put the temp value in its place.
// Do the squaring now, they will be used in the next calculation.
multZre = zRe * zRe;
multZim = zIm * zIm;
//Increase the mandelValue by one, because the iteration is now finished.
mandelValue += 1;
}
//After the mandelValue is found, this colors its pixel accordingly (unsafe code, accesses memory directly):
//(Unimportant for my question, I doubt the problem is with this because my code becomes really slow
// as the number of ITERATIONS grow, this only executes more as the number of pixels grow).
Byte* pos = px + (i * str) + (pixelSize * r);
byte col = (byte)((1 - ((double)mandelValue/iters)) * 255);
pos[0] = col;
pos[1] = col;
pos[2] = col;
}
}
Cosa posso fare per migliorare questa? Trovi ovvi problemi di ottimizzazione nel mio codice?
In questo momento ci sono 2 modi so che posso migliorare:
ho bisogno di usare un tipo diverso per i numeri, doppia è limitato con precisione e sono sicuro che ci sono meglio non-built -in tipi alternativi che sono più veloci (si moltiplicano e si aggiungono più velocemente) e hanno maggiore precisione, ho solo bisogno di qualcuno che mi indichi dove ho bisogno di guardare e dirmi se è vero.
Posso spostare l'elaborazione nella GPU. Non ho idea di come fare questo (OpenGL forse? DirectX? È anche così semplice o avrò bisogno di imparare un sacco di cose?). Se qualcuno può inviarmi link a tutorial appropriati su questo argomento o dirmi in generale che sarebbe fantastico.
Grazie mille per la lettura così lontano e spero che me :)
float è in genere più veloce, anche se penso che dipenda dal processore utilizzato. float è in genere più veloce del doppio se usi una gpu. – sav