首先,我知道这个问题听起来真的好像我没有搜索,但我做了很多。
我为 C# 编写了一个小的 Mandelbrot 绘图代码,它基本上是一个带有 PictureBox 的 Windows 窗体,我在其上绘制了 Mandelbrot 集。
我的问题是,它很慢。如果没有深度缩放,它会做得很好,并且移动和缩放非常流畅,每张图只需不到一秒钟的时间,但是一旦我开始放大一点并到达需要更多计算的地方,它就会变得非常慢。
在其他 Mandelbrot 应用程序中,我的计算机在我的应用程序中运行速度慢得多的地方运行得非常好,所以我猜我可以做很多事情来提高速度。
我做了以下事情来优化它:
我没有在位图对象上使用 SetPixel GetPixel 方法,而是使用 LockBits 方法直接写入内存,这使事情变得更快。
我没有使用复数对象(使用我自己创建的类,而不是内置类),而是使用 2 个变量 re 和 im 来模拟复数。这样做让我减少了乘法,因为对实部和虚部求平方是在计算过程中完成的几次,所以我只是将平方保存在一个变量中并重用结果而无需重新计算它。
我使用 4 个线程来绘制 Mandelbrot,每个线程执行图像的不同四分之一,并且它们都同时工作。据我了解,这意味着我的 CPU 将使用其 4 个内核来绘制图像。
我使用 Escape Time 算法,据我所知,这是最快的?
这是我在像素之间移动和计算的方式,它被注释掉了,所以我希望它是可以理解的:
//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;
}
}
我能做些什么来改善这一点?您在我的代码中发现任何明显的优化问题吗?
现在有两种方法我知道我可以改进它:
我需要对数字使用不同的类型,double 的准确性受到限制,我确信有更好的非内置替代类型更快(它们乘法和加法更快)并且具有更高的准确性,我只需要有人来指出我需要看的地方并告诉我这是不是真的。
我可以将处理转移到 GPU。我不知道如何做到这一点(也许是OpenGL?DirectX?它甚至那么简单还是我需要学习很多东西?)。如果有人可以向我发送有关此主题的适当教程的链接,或者总体上告诉我,那就太好了。
非常感谢您阅读这么远,希望您能帮助我:)