OpenMPでOpenGLを使ったマンデルブロ集合のプログラムを高速化しようとしてこけた

マンデルブロ集合を描画するプログラムをOpenMPで高速化しようとして驚いた。gccOpenMPを有効にしてコンパイルして実行するとノイズだらけの乱れた画像が生成された。




ネット上を調べてみると

OpenGLはマルチスレッドを考慮した作りになっていないので、マルチスレッドで動作させるにはレンダリングコンテクストをスレッド間で共有しなければならない

らしい。あとで調べる。

追記:OpenMPのディレクティブに問題があった。スレッド間で共有されるべきでない変数が共有されていたので修正した。

#include<cmath>
#include<complex>
#include<GL/glut.h>
using namespace std;

typedef complex<double> cox_t;

int scale=2000;
double m=2.0;

void mandelbrot()
{
	int i;
	int x, y;
	double limit = 1e8;
	int iter = 50;
	double color;

	for(x=-scale; x<scale; x++){
		// OpenMPを有効にすると生成するグラフィックが乱れる。
		// マルチスレッド考慮されていないステートマシンのOpenGLの内部でコマンドが混乱するのだと思われる.
		// 下の1行を削除するだけで正常動作する。
		# pragma omp parallel 
		for(y=-scale; y<scale; y++){
			cox_t c((x*1./scale)*m, (y*1./scale)*m), z(0, 0);

			for(i=0; i<iter; i++){
				z = z*z + c;
				if(abs(z) > limit){
					// 発散
					color = (double)i/iter;
					glColor3d(color, color, color);
					glVertex2d((x*1./scale), (y*1./scale));
					break;
				}
			}
			if(i==iter){
				glColor3d(0,0,0); glVertex2d((x*1./scale), (y*1./scale));
			}
		}
	}
}

void display()
{
	glClear(GL_COLOR_BUFFER_BIT);
	glBegin(GL_POINT);
	mandelbrot();
	glEnd();
}

int main(int argc, char **argv)
{
	glutInit(&argc, argv);
	glutCreateWindow("mandelbrot");
	glutDisplayFunc(display);
	glClearColor(0,0,0,0);
	glClear(GL_COLOR_BUFFER_BIT);
	glFlush();
	glutMainLoop();
	return 0;
}