Skip to main content
gamedev.net
🔒 Locked

Need help for optimizing code

Started by madsravn 3 replies 1.1k views
Original Post
madsravn
madsravn
Hey there... I have just made some mandelbrot thingy, but it runs slow as an old man with a cane. So I was wondering if anyone had any tips for optimizing it? Code is here: #include <iostream> #include <cmath> #include <GL/glut.h> struct compnumber { public: float x; float y; }; float a=6.0f; float diff=0.001f; float distance(compnumber z) { return sqrt(z.x*z.x+z.y*z.y); } float add_real(compnumber z, compnumber q) { return q.x+z.x; } float add_complex(compnumber z, compnumber q) { return q.y+z.y; } float times_real(compnumber z, compnumber q) { return z.x*q.x-q.y*z.y; } float times_complex(compnumber z, compnumber q) { return q.x*z.y+q.y*z.x; } compnumber c,z,z1; void changeSize(int w, int h) { // Prevent a divide by zero, when window is too short // (you cant make a window of zero width). if(h == 0) h = 1; float ratio = 1.0* w / h; // Reset the coordinate system before modifying glMatrixMode(GL_PROJECTION); glLoadIdentity(); // Set the viewport to be the entire window glViewport(0, 0, w, h); // Set the correct perspective. gluPerspective(45,ratio,1,1000); glMatrixMode(GL_MODELVIEW); glLoadIdentity(); gluLookAt(0.0,0.0,4.0, 0.0,0.0,0.0, 0.0f,1.0f,0.0f); } void processNormalKeys(unsigned char key, int x, int y) { if (key == 27) exit(0); } void renderScene(void) { float i,k; float step=0.005; int iter=15; int count; glClearColor(1.0f,1.0f,1.0,1.0f); glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); // x axis glColor3f(0.0f,0.0f,0.0f); glBegin(GL_LINES); glVertex3f(-2.0,0.0,0.0); glVertex3f(2.0,0.0,0.0); glEnd(); // y axis glBegin(GL_LINES); glVertex3f(0.0,-2.0,0.0); glVertex3f(0.0,2.0,0.0); glEnd(); // Plot function glBegin(GL_POINTS); for(i=-2.0;i<2.1;i+=step) { for(k=-2.0;k<2.1;k+=step) { c.x=i; c.y=k; z.x=0; z.y=0; //We do this for all points from (-2.0,-2.0,0.0) to (2.0,2.0,0.0) for(count=0;count<iter;count++) { z1.x=times_real(z,z)+c.x; z1.y=times_complex(z,z)+c.y; z.x=z1.x; z.y=z1.y; } if(distance(z1)>distance(c)) { glColor3f(1.0f,0.0f,0.0); glVertex3f(c.x,c.y,0.0); } if(distance(z1)<distance(c)) { glColor3f(0.0f,1.0f,0.0); glVertex3f(c.x,c.y,0.0); } } } glEnd(); glutSwapBuffers(); } int main(int argc, char **argv) { c.x=1.0f; c.y=2.0f; glutInit(&argc, argv); glutInitDisplayMode(GLUT_DEPTH | GLUT_DOUBLE | GLUT_RGBA); glutInitWindowPosition(100,100); glutInitWindowSize(320,320); glutCreateWindow("Functions"); glutKeyboardFunc(processNormalKeys); glutDisplayFunc(renderScene); glutIdleFunc(renderScene); glutReshapeFunc(changeSize); glutMainLoop(); return 0; } I'd really appreciate your help. thanks. *EDIT* Or here if you want it indented: http://cpp.sourceforge.net/?show=33623 *EDIT*
Degra
Degra
This piece of code is being looped through 672,400 times per frame, so you're doing 672,400 * 15 real and complex number calculations, 672,400 * 4 square roots and drawing 672,400 vertices... every frame. That is most likely the reason it's running slowly.

                c.x=i;                 c.y=k;                 z.x=0;                 z.y=0;                 //We do this for all points from (-2.0,-2.0,0.0) to (2.0,2.0,0.0)                 for(count=0;count<iter;count++)                 {                     z1.x=times_real(z,z)+c.x;                     z1.y=times_complex(z,z)+c.y;                     z.x=z1.x;                     z.y=z1.y;                 }                 if(distance(z1)>distance(c))                 {                     glColor3f(1.0f,0.0f,0.0);                     glVertex3f(c.x,c.y,0.0);                 }                 if(distance(z1)<distance(c))                 {                     glColor3f(0.0f,1.0f,0.0);                     glVertex3f(c.x,c.y,0.0);                 } 


Square roots are very expensive instructions to use. You can save on the 2,689,600 square roots by simply not square rooting, it won't change the result of your distance comparison ifs if you don't square root. I'm not sure how much of a difference that'll make overall, but it's a start.

[Edit - corrected for miscalculation]

Degra
madsravn
madsravn
thanks. Did a little, but not very much. I can't see how I can make it more precise and more fast at the same time ;S
Lord_Evil
Lord_Evil
You're obviously CPU bound. There are some things that you might try:

1) Function calls may be a slowdown if called *many* times per frame. Try to inline your trivial functions like add_real or remove them and replace the function calls with the contents of those functions.

2) Precompute what you will use multiple times, e.g. distance(z1), distance(c). This will save you at least two function calls per vertex.

3) Use vertex arrays or vertex buffer objects instead of immediate mode. Immediate mode has a huge driver overhead. If you create and fill a vertex array in memory and then send it down the pipeline once per frame you'd save approx. 2680000 glXXX calls per frame.
If I was helpful, feel free to rate me up ;)If I wasn't and you feel to rate me down, please let me know why!
Skizz
Skizz
Your code is highly inefficent. You appear to be creating a grid of 800x800 points1 where each point is either red or green depending on the result of a fractal computation2. Thise array of points never changes from frame to frame, so why recalculate it? Use a display list.

However, when the window size is less than 800 is either direction, you will get pixels drawn to multiple times (i.e. a waste of effort); greater than 800 you'll get gaps in the image. Why not pre-compute the image and store it in a texture and then draw a textured quad?

Also, why use floating point calculations for the fractal maths. Integer would be far quicker. Here's a program that uses lots of integer maths to do fractals.

Skizz

1) Except for those points where: distance (z1) == distance (c)
2) An odd result check at that - the distance is normally checked against a constant. In those multicoloured images, the number of iterations before the distance exceeds a defined constant is used as a colour index.

Topic Locked

This topic has been locked by a moderator. New replies are not allowed.

Sign in to reply to this topic.