Zunächst einmal ist mir bewusst, dass diese Frage wirklich klingt, als ob ich nicht suchte, aber ich tat, viel.Making C# Mandelbrot Zeichnung effizienter
Ich habe einen kleinen Mandelbrot-Zeichencode für C# geschrieben, es ist im Grunde eine Windows-Form mit einer PictureBox, auf der ich das Mandelbrot-Set zeichne.
Mein Problem ist, dass es ziemlich langsam ist. Ohne einen tiefen Zoom macht es einen ziemlich guten Job und das Bewegen und Zoomen ist ziemlich glatt, dauert weniger als eine Sekunde pro Zeichnung, aber sobald ich anfange, ein wenig zu zoomen und zu Orten zu kommen, die mehr Berechnungen erfordern, wird es wirklich langsam.
Bei anderen Mandelbrot-Anwendungen funktioniert mein Computer sehr gut an Orten, die in meiner Anwendung viel langsamer arbeiten, also denke ich, dass es viel gibt, was ich tun kann, um die Geschwindigkeit zu verbessern.
ich folgende Dinge tat, es zu optimieren:
Statt die SetPixel GetPixel Methoden auf das Bitmap-Objekt verwenden, benutzte ich LockBits Verfahren direkt in den Speicher zu schreiben, die Dinge viel schneller gemacht.
Anstatt komplexe Zahlenobjekte zu verwenden (mit Klassen, die ich selbst gemacht habe, nicht die eingebauten), emulierte ich komplexe Zahlen mit 2 Variablen, re und im. Dies ermöglichte es mir, Multiplikationen zu reduzieren, da die Quadratur des Realteils und des Imaginärteils während der Berechnung einige Zeit dauert. Daher speichere ich das Quadrat in einer Variablen und verwende das Ergebnis, ohne es neu berechnen zu müssen.
Ich benutze 4 Threads um das Mandelbrot zu zeichnen, jeder Thread macht ein anderes Viertel des Bildes und alle arbeiten gleichzeitig. Wie ich verstanden habe, bedeutet das, dass meine CPU 4 ihrer Kerne benutzt, um das Bild zu zeichnen.
Ich verwende den Escape Time Algorithm, den ich am schnellsten verstanden habe?
Hier ist mein, wie ich zwischen den Pixeln und berechnen zu bewegen, ist es kommentiert, so hoffe ich, es ist verständlich:
//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;
}
}
Was kann ich dies verbessern tun? Finden Sie irgendwelche offensichtlichen Optimierungsprobleme in meinem Code?
Im Moment gibt es zwei Möglichkeiten, wie ich weiß, dass ich es verbessern kann:
Ich brauche einen anderen Typ für Zahlen verwenden, doppelt mit Genauigkeit begrenzt und ich bin sicher, es gibt bessere unbebaut - in alternativen Typen, die schneller sind (sie multiplizieren und fügen schneller hinzu) und mehr Genauigkeit haben, brauche ich nur jemanden, der mir zeigt, wo ich hinschauen muss, und mir sagen, ob es wahr ist.
Ich kann die Verarbeitung auf die GPU verschieben. Ich habe keine Ahnung, wie ich das machen soll (OpenGL vielleicht? DirectX? Ist es überhaupt so einfach oder muss ich eine Menge lernen?). Wenn mir jemand Links zu passenden Tutorials zu diesem Thema schicken kann oder mir allgemein davon erzählen würde, wäre das super.
Vielen Dank für die weit Lesen und hoffen, dass Sie mich :)
Float ist normalerweise schneller, obwohl ich denke, es hängt davon ab, welchen Prozessor Sie verwenden. Float ist normalerweise schneller als doppelt, wenn Sie eine GPU verwenden. – sav