Прежде всего, я знаю, что этот вопрос действительно звучит так, как будто я не искал, но я сделал, много.Выполнение чертежа C# mandelbrot более эффективно
Я написал небольшой код чертежа Мандельброта для C#, это в основном форма окна с PictureBox, на которой я рисую набор Мандельброта.
Моя проблема в том, что она довольно медленная. Без глубокого масштабирования он выполняет довольно хорошую работу и перемещается, а масштабирование довольно плавное, занимает меньше секунды за каждый рисунок, но как только я начинаю немного увеличиваться и попадаю в места, требующие больших вычислений, он становится очень медленным.
В других приложениях Mandelbrot мой компьютер действительно отлично работает в местах, которые работают намного медленнее в моем приложении, поэтому я предполагаю, что я могу многое сделать, чтобы улучшить скорость.
Я сделал следующие вещи, чтобы оптимизировать его:
Вместо использования методов SetPixel GetPixel на растровый объект, я использовал метод LockBits писать непосредственно в памяти, который сделал вещи намного быстрее.
Вместо использования сложных числовых объектов (с классами, которые я сделал сам, а не со встроенными), я эмулировал комплексные числа, используя 2 переменные, re и im. Это позволило мне сократить количество умножений, потому что возведение в квадрат реальной части и воображаемой части - это то, что выполняется несколько раз во время вычисления, поэтому я просто сохраняю квадрат в переменной и повторно использую результат без необходимости его пересчета.
Я использую 4 нити для рисования Мандельброта, каждая нить выполняет разную четверть изображения, и все они работают одновременно. Как я понял, это означает, что мой процессор будет использовать 4 его ядра для рисования изображения.
Я использую алгоритм Escape Time Algorithm, который, как я понял, является самым быстрым?
Вот мой, как я двигаюсь между пикселями и вычислить, он прокомментировал так, я надеюсь, что это понятно:
//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;
}
}
Что я могу сделать, чтобы улучшить это? Вы обнаружите какие-либо очевидные проблемы оптимизации в моем коде?
Прямо сейчас есть 2 способа, я знаю, что могу улучшить его:
мне нужно использовать другой тип для чисел, двойной ограничено с точностью, и я уверен, что есть лучше незастроенные - В альтернативных типах, которые быстрее (они умножаются и добавляются быстрее) и имеют большую точность, мне просто нужно, чтобы кто-то указал мне, где мне нужно посмотреть и сказать, если это правда.
Я могу переместить обработку на GPU. Я не знаю, как это сделать (OpenGL, может быть, DirectX - это даже так просто или мне нужно будет многому научиться?). Если кто-то может отправить мне ссылки на соответствующие учебные пособия по этому вопросу или сказать мне в целом об этом, это было бы здорово.
Большое спасибо за чтение, что далеко, и надеюсь, что вы можете мне помочь :)
float обычно быстрее, хотя я думаю, что это зависит от того, какой процессор вы используете. float обычно быстрее, чем двойной, если вы используете gpu. – sav