PDA

View Full Version : Multithreading



xerzi
06-29-2011, 08:52 PM
So I have my main program thread which does all my opengl rendering and camera calculations, but than I also need another thread that runs at a set fps. Basically like a physics thread so that I can set animation data and such. The problem is that when it's rendering it seems to flicker between frames as it seems to rendering faster than the animation data can be calculated. Is there any way I can set this up so that the main thread isn't jumping fps as it waiting for the physics thread to finish rendering?

Aleksandar
06-29-2011, 10:34 PM
If physics calculation is done purely on CPU, than standard synchronization mechanisms, like critical sections, are sufficient. If another thread also uses OpenGL, you need GL_ARB_sync extension (requires OpenGL 3.2+). Usage of other APIs imposes their own sync mechanisms.

xerzi
06-30-2011, 09:47 PM
That wasn't exactly what I was asking, yes the second thread does not use any opengl, the problem is I'm not sure how to render while another thread is editing data that is also used for rendering.

Alfonse Reinheart
06-30-2011, 11:39 PM
Note: ARB_sync does not require 3.2. There are many pre-3.x cards that can handle them.


the problem is I'm not sure how to render while another thread is editing data that is also used for rendering.

You don't. If you're using client arrays, then switch to buffer objects. Your textures are already in texture objects, so the non-OpenGL thread can't affect them.

xerzi
07-01-2011, 03:28 PM
I'm talking about animation data that I have set up. I have a basic structure:


struct{ vec3 position; quaternion rotation; };

Which is set by my physics thread, it does all the blending between animations etc... When I only have one thread for all this I am getting 1000 fps, but when I do this:



bool physics;

void OpenGL(){
if(!physics){
//generate matrices
//draw model using glDrawElements
}
}

void Physics(){
while(true){
//fps limiter here

physics = true;

//set and blend animation data

physics = false;
}
}


Now the fps becomes unstable and jumps from 30 to 130 fps. If I remove the check (the bool physics) than the rendering flickers. I hope this clears up what I am trying to do... I am not trying to load textures.

Alfonse Reinheart
07-01-2011, 04:45 PM
OK, your problem right now has nothing to do with OpenGL. Your threading code is... not good.

Threading is not a beginner or intermediate-level subject. Not in C or C++ (or in any language, no matter how much they try to tell you otherwise). Threading in any situation is going to require some serious research on your part before you are able to deal with the complexities of it.

For example, let's take your code.

You have a threaded function called "OpenGL" which checks a global boolean to see if it should do something. And you have, in another thread, "Physics" which sets that boolean value while it is doing stuff.

However, your CPU doesn't see "if(!physics)"; it sees the assembly language representation of this. That looks something like this:



SET reg1 TO LOAD_FROM_MEMORY(&physics)
TEST reg1 NEQ ZERO
...


Now, what do you suppose would happen to your code if between the first and second instructions, the "Physics" routine went and changed the value in "physics"? You test would have no way to know that this had happened, and it would no longer represent where the "Physics" routine was.

This is called a race condition: when two threads are trying to read/write the same memory. It is the bane of all threaded programming, and fixing them is not easy. Doing so usually requires using some threading intrinsics or something called a "mutex".

The best advice I've ever heard about threading (besides DON'T) is this: if your threading code is not provably correct, then it is wrong. Until you know enough about threading to know whether your threading code is provably correct, you shouldn't be messing with it. Go learn about threading, spend several months doing so, then come back to this.

Oh, and typically, the "set and blend animation data" part of the animation system is not considered part of physics. It's the animation system.

xerzi
07-01-2011, 09:39 PM
OK, your problem right now has nothing to do with OpenGL. Your threading code is... not good.
Yes I know it's incorrect which is why I am posting for help, sorry for posting in the wrong subsection. Which may have confused you.



However, your CPU doesn't see "if(!physics)"; it sees the assembly language representation of this. That looks something like this:



SET reg1 TO LOAD_FROM_MEMORY(&physics)
TEST reg1 NEQ ZERO
...


Now, what do you suppose would happen to your code if between the first and second instructions, the "Physics" routine went and changed the value in "physics"? You test would have no way to know that this had happened, and it would no longer represent where the "Physics" routine was.

Thanks for pointing that out except my code isn't setting physics to 0 so anywhere between the time it checks the value to the next time it checks the value the Physics thread could be doing something.

I fixed it with assembly, there are specific assembly commands just for multithreading :) (cmpxchg xchg), I get 1000 fps still and the animation thread runs at 30 fps like I want it to with no flickering. I like to try to avoid assembly when I can, makes the entire thing harder to read.



This is called a race condition: when two threads are trying to read/write the same memory. It is the bane of all threaded programming, and fixing them is not easy. Doing so usually requires using some threading intrinsics or something called a "mutex".

The best advice I've ever heard about threading (besides DON'T) is this: if your threading code is not provably correct, then it is wrong. Until you know enough about threading to know whether your threading code is provably correct, you shouldn't be messing with it. Go learn about threading, spend several months doing so, then come back to this.
Well I don't plan on writing in such a low language later on, I'll use a single thread per your suggestion.



Oh, and typically, the "set and blend animation data" part of the animation system is not considered part of physics. It's the animation system.
I have my physics calculations along with my animation calculations in the same thread as they both run at the same fps, my mistake.

ZbuffeR
07-02-2011, 01:54 AM
Just a side note, threading can be done in most high level languages too, assembly is not required.
But yes, do not go with threads unless you are experienced enough and you really need it, because it is very hard to do right.