まず第一に、この質問はまるで私が検索していないかのように聞こえることを認識していますが、私はたくさん検索しました。
私は C# 用の小さなマンデルブロー描画コードを書きました。これは基本的に、マンデルブロー セットを描画する PictureBox を備えた Windows フォームです。
私の問題は、それがかなり遅いということです。深いズームがなければ、かなりうまく機能し、移動とズームは非常にスムーズで、描画ごとに1秒もかかりませんが、少しズームインし始めて、より多くの計算が必要な場所に到達すると、非常に遅くなります.
他のマンデルブロー アプリケーションでは、アプリケーション内で動作が非常に遅い場所でも、私のコンピューターは問題なく動作するため、速度を改善するためにできることはたくさんあると思います。
最適化するために次のことを行いました。
ビットマップ オブジェクトで SetPixel GetPixel メソッドを使用する代わりに、LockBits メソッドを使用してメモリに直接書き込み、処理を大幅に高速化しました。
複素数オブジェクト (組み込みのクラスではなく、自分で作成したクラス) を使用する代わりに、2 つの変数 re と im を使用して複素数をエミュレートしました。実数部と虚数部の 2 乗は計算中に数回行われるため、これを行うことで乗算を減らすことができました。そのため、2 乗を変数に保存し、再計算する必要なく結果を再利用するだけです。
私は 4 つのスレッドを使用してマンデルブロを描画します。各スレッドは画像の異なる 4 分の 1 を処理し、すべて同時に機能します。私が理解したように、それは私のCPUが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つの方法があります。
数値には別の型を使用する必要があります。 double は精度に制限があり、より高速 (乗算と加算が高速) で精度の高い、より優れた非組み込みの代替型があると確信しています。どこを見る必要があるかを教えて、それが本当かどうか教えてください。
処理を GPU に移動できます。これを行う方法がわかりません (OpenGL でしょうか? DirectX? そんなに単純なのか、それとも多くのことを学ぶ必要があるのでしょうか?)。誰かがこの主題に関する適切なチュートリアルへのリンクを送ってくれたり、それについて一般的に教えてくれたりしたら、それは素晴らしいことです.
ここまで読んでくれてありがとう。助けてくれることを願っている:)