gpt4 book ai didi

c# - 使 C# mandelbrot 绘图更高效

转载 作者:太空狗 更新时间:2023-10-29 17:50:48 26 4
gpt4 key购买 nike

首先,我知道这个问题听起来好像我没有搜索过,但我搜索了很多。

我为 C# 编写了一个小的 Mandelbrot 绘图代码,它基本上是一个带有 PictureBox 的窗口窗体,我在上面绘制了 Mandelbrot 集。

我的问题是,它太慢了。没有深度缩放它做得很好,四处移动和缩放非常流畅,每张图花费不到一秒钟,但是一旦我开始稍微放大并到达需要更多计算的地方,它就会变得非常慢。

在其他 Mandelbrot 应用程序上,我的计算机在我的应用程序中运行速度慢得多的地方确实做得很好,所以我猜我可以做很多事情来提高速度。

我做了以下事情来优化它:

  • 我没有在位图对象上使用 SetPixel GetPixel 方法,而是使用 LockBits 方法直接写入内存,这样速度更快。

  • 我没有使用复数对象(使用我自己创建的类,而不是内置的类),而是使用 2 个变量 re 和 im 模拟复数。这样做让我减少了乘法运算,因为实部和虚部的平方是在计算过程中多次完成的事情,所以我只是将平方保存在一个变量中并重复使用结果而不需要重新计算它。

  • 我使用 4 个线程绘制 Mandelbrot,每个线程处理图像的不同四分之一,它们都同时工作。据我了解,这意味着我的 CPU 将使用其 4 个核心来绘制图像。

  • 我使用逃逸时间算法,据我所知这是最快的?

这是我在像素之间移动和计算的方式,它被注释掉了,所以我希望它是可以理解的:

        //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;

}
}

我可以做些什么来改善这一点?你在我的代码中发现任何明显的优化问题吗?

现在我知道有两种方法可以改进它:

  1. 我需要为数字使用不同的类型,double 的精度有限,我确信有更好的非内置替代类型,它们更快(它们乘法和加法更快)并且具有更高的精度,我只需要有人指出我需要查看的位置并告诉我它是否属实。

  2. 我可以将处理转移到 GPU。我不知道该怎么做(也许是 OpenGL?DirectX?就这么简单吗?还是我需要学习很多东西?)。如果有人可以向我发送有关此主题的适当教程的链接,或者告诉我有关它的一般情况,那就太好了。

非常感谢您阅读到这里,希望您能帮助我 :)

最佳答案

如果您决定将处理转移到 GPU,您可以从多个选项中进行选择。由于您使用的是 C#,XNA 将允许您使用 HLSL。 RB Whitaker如果您选择此选项,它有最简单的 XNA 教程。另一个选项是 OpenCL . OpenTK附带一个 julia 集分形的演示程序。这将非常容易修改以显示 mandlebrot 集。参见 here请记住找到源代码附带的 GLSL 着色器。

About the GPU, examples are no help for me because I have absolutely no idea about this topic, how does it even work and what kind of calculations the GPU can do (or how is it even accessed?)

不同的 GPU 软件的工作方式不同......

通常,程序员会使用 HLSL、GLSL 或 OpenCL 等着色器语言为 GPU 编写程序。用 C# 编写的程序将加载着色器代码并对其进行编译,然后使用 API 中的函数向 GPU 发送作业并随后取回结果。

看看FX Composer或者渲染猴子,如果你想使用着色器进行一些练习而不必担心 API。

如果您使用的是 HLSL,则渲染管道如下所示。

pipeline

顶点着色器负责获取 3D 空间中的点并计算它们在 2D 视野中的位置。 (因为你在 2D 中工作,所以对你来说不是什么大问题)

像素着色器负责在顶点着色器完成后将着色器效果应用于像素。

OpenCL 是另一回事,它面向通用 GPU 计算(即:不仅仅是图形)。它的功能更强大,可用于 GPU、DSP 和构建 super 计算机。

关于c# - 使 C# mandelbrot 绘图更高效,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/17406474/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com