Multithreaded physics

Discuss any questions about BEPUphysics or problems encountered.
nindim
Posts: 10
Joined: Thu Nov 06, 2008 1:40 pm

Multithreaded physics

Post by nindim »

I have noticed that in the new version you metion that parts of the engine are now thread safe:

"-Buffered states for momentum and velocity, along with improvements to the previously added buffered states, now provide thread safe entity access.
-Common engine access points now thread safe."

Does this mean that I can put BEPUphysics in it's own thread without any problems?

Is there anything I would need to pay sepcial attention to or any gotchas in doing this?

I haven't done much multi threading in the past, but I would imagine the best way to approach running the physics in parallel to the rendering would be to link the rendering with the previous scene's physics results? i.e. the physics linked to the dispalyed objects would be one frame old as otherwise the program would still be waiting on reults of physics calculations so you could render the obejcts with the correct world matrix.

I have read in previous posts that you had planned internal multithreading, when is this palnned for and would this interfere with an implementation similar to what I am discussing above?

Any help or ideas/pseudo code would be more than appreciated.
User avatar
Zukarakox
Not a Site Admin
Posts: 426
Joined: Mon Jul 10, 2006 4:28 am

Re: Multithreaded physics

Post by Zukarakox »

I dont know anything about multithreading, but the internal multithreading of the engine won't be around for awhile, probably a few months at least.
i has multiple toes
Norbo
Site Admin
Posts: 4929
Joined: Tue Jul 04, 2006 4:45 am

Re: Multithreaded physics

Post by Norbo »

Most of the gotchas should now be taken care of; if you encounter a case where protection isn't internally provided and is needed for your application, the space has synchronization objects that you can lock.

The centerPosition, linearVelocity, and other states will give you the latest available value in a thread safe manner, so you won't have to worry about managing it externally. The internalCenterPosition, internalLinearVelocity and other unbuffered states let you access them in a direct, non thread safe way if needed.

Combining the thread-safe entity state properties with internal timestepping (space.simulationSettings.useInternalTimeStepping = true) will keep things running smoothly since the physics thread will be most likely running with nonuniform amounts of time between each frame. This time will have to be kept track of and be passed into the space.Update method each frame.

The internal multithreading will not interfere at all with this set up. When it's added, the only significant external difference will be the ability to give the engine an arbitrary number of threads to work with. I hope to have this completed sooner rather than later; I'm aiming for somewhere in between late December and mid January for v0.8.0. There's also going to be a v0.7.1 to address some of the things left out of v0.7.0.
nindim
Posts: 10
Joined: Thu Nov 06, 2008 1:40 pm

Re: Multithreaded physics

Post by nindim »

Hmm, I have tried what you suggested using System.Diagnostics.StopWatch to measure the time elapsed (I'm not sure if this was accurate enough though as a lot of the time the time elapsed in milliseconds was 0. I tried to rectify this by checking if time elapsed was greater than 0, if it is not keep timing till it is, then call the space's update) and I also set the useInternalTimeStepping to true but still no luck, the movement is very jerky and in slow motion, it approaches normality when I pass in milliseconds, but I though the update method took seconds....

Not sure what I'm doing wrong :( any chance of including this in an updated demo so I can see it in action and hopefully figure out where I'm going wrong? Thanks for your time so far!
Norbo
Site Admin
Posts: 4929
Joined: Tue Jul 04, 2006 4:45 am

Re: Multithreaded physics

Post by Norbo »

Releasing a demo specifically of putting the physics on another thread would probably be a good idea. I actually had a offloaded version of the demos using the Stopwatch for timing, but it was a little too messy to release. I'll probably make a clean stripped down version to show how to offload it at some point.

As for the problem at hand, I believe I've seen similar behavior when the timer grabs the time out of order, leading to a very small time between frames despite the actual calculation taking significantly longer. What is the time between frames that the timer is indicating when using the TotalSeconds method (to include fractions)? It will be very, very tiny if the above is the problem.
Norbo
Site Admin
Posts: 4929
Joined: Tue Jul 04, 2006 4:45 am

Re: Multithreaded physics

Post by Norbo »

Here's some code to set up the second thread and the timing:

Code: Select all

        Thread physicsThread;
        Stopwatch stopwatch = new Stopwatch();
        double previousTime = 0;

        public void physicsUpdate()
        {
            while (true)
            {
                double currentTime = stopwatch.Elapsed.TotalSeconds;
                double elapsedTime = currentTime - previousTime;
                previousTime = currentTime;
                space.update((float)elapsedTime);
                
            }
        }
And here's how to start it up in the initialization:

Code: Select all

            space.simulationSettings.useInternalTimeStepping = true;
            stopwatch = Stopwatch.StartNew();
            physicsThread = new Thread(physicsUpdate);
            physicsThread.IsBackground = true;
            physicsThread.Start();

If you get an exception with 'enumeration modified' from the engine, there's a very high chance it's caused by interference with the engine while it is in the middle of an update. You can fix this almost always by locking the space.lockerUpdate object or one of the other more specific objects if you know which is causing it.

There are a few instances where you might encounter these exceptions and they don't seem like they should occur- one known case is the Explosion's explode method. In v0.7.0, this can occasionally modify data improperly even though it seems like it should 'just work.' If you find unintuitive things similar to this, let me know and I'll see if I can fix it.

Some aspects of the demos don't work perfectly when offloading physics (some rendering problems with compoundbodies are noticable, for example). Also, if you have any issues with the internal timestepping when dealing with slow simulations (requiring many internal steps per update), let me know. I think its behavior could be improved.
nindim
Posts: 10
Joined: Thu Nov 06, 2008 1:40 pm

Re: Multithreaded physics

Post by nindim »

Hmm, well the code you gave me works much more smoothly on the PC, but it is still stuttering very badly on the 360. Even on the PC it does not seem as smooth or as consistent as the single threaded update method.

It looks like the problem before came from the fact that my StopWatch code was only counting full milliseconds, whereas your code counts fractionally as well. You mentioned previously that the time would be very small if the timer was grabbing the time out of order, not 100% sure what you mean by this, but the time did seem very very very low, even with your timer code. I will post exact numbers a little later today.
nindim
Posts: 10
Joined: Thu Nov 06, 2008 1:40 pm

Re: Multithreaded physics

Post by nindim »

Ok, so I've printed out the value for elapsedTime whilst running in debug, herer is the ouput (in seconds):

Elapsed Time: 0.0010151
Elapsed Time: 0.0046922
Elapsed Time: 0.0002091
Elapsed Time: 0.0001789
Elapsed Time: 0.0002514
Elapsed Time: 0.000194
Elapsed Time: 0.000321
Elapsed Time: 0.0002616
Elapsed Time: 0.0001784
Elapsed Time: 0.0001762
Elapsed Time: 0.0002013
Elapsed Time: 0.0002839
Elapsed Time: 0.0002405
Elapsed Time: 0.0005208
Elapsed Time: 0.0255983
Elapsed Time: 0.046822
Elapsed Time: 0.0137066
Elapsed Time: 0.039821
Elapsed Time: 0.0245282
Elapsed Time: 0.0069718
Elapsed Time: 0.0244624
Elapsed Time: 0.0151529
Elapsed Time: 0.0084732
Elapsed Time: 0.0003097
Elapsed Time: 0.0009454
Elapsed Time: 0.0003082
Elapsed Time: 0.0004115
Elapsed Time: 0.0004894
Elapsed Time: 0.0362495
Elapsed Time: 0.0325165
Elapsed Time: 0.0110226

That's from the astart of my app. I have the playground model from the demo as a StaticTriangleGroup and am dropping 100 of the bepu crates on it. I also have a plane above the terrain with the jenga demo on it.

I am running a Core 2 Duo 2.4GHZ with an ATI Radeon X1900XT.

The update time seems to range from 0.1762ms up to 46.822ms in the above sample! I ran it for a couple of minutes and that is representative of the rest of the app. If I understand correctly what you say about the timer getting the time out of order, I can understand this happening on the PC, but surely that shouldn't be an issue on the 360 as it has an in order CPU.... Not sure how to pirnt out the debug info though whilst running on 360, any ideas let me know!
Norbo
Site Admin
Posts: 4929
Joined: Tue Jul 04, 2006 4:45 am

Re: Multithreaded physics

Post by Norbo »

What I meant by out of order timing was just logic errors in the way the times are grabbed (measuring the time between the end of one frame and the beginning of the next accidently, for example; I did that a few times :D). Those times look to be about right since the engine is running at full blast. If something was wrong with the timing, it would print out the length of one or two timer ticks (like 1e-7).

The only problem I see in there are those jumps to 46 milliseconds. That implies that the simulation needed to run something like 4-10 times to catch up in terms of computational expense, but it doesn't seem like it had sufficiently large previous frames. I'll do some investigating.

The Xbox360 will run in the same way as the PC, just significantly slower due to the way it handles floating point calculations through the compact framework. It will magnify any issues that exist on the PC.
Eizon
Posts: 7
Joined: Sat Dec 20, 2008 8:12 pm

Re: Multithreaded physics

Post by Eizon »

I tried multi threading as well. It gave me some 2-10X performance increase on large scale scenes. However giving me a massive slowdown after 5-20 minutes depending on computer specifications.

No lag was shown, but gravity, velocity and momentum was reduced to about the fourth resulting in slow-motion, with fast motion controls.
Norbo
Site Admin
Posts: 4929
Joined: Tue Jul 04, 2006 4:45 am

Re: Multithreaded physics

Post by Norbo »

Was that using the internal timestepping, or was it one timestep per space.update call? My best guess right now is something else is causing the time between frames to rise.
Eizon
Posts: 7
Joined: Sat Dec 20, 2008 8:12 pm

Re: Multithreaded physics

Post by Eizon »

This is the code I used, it's somehow messy tough.

Code: Select all

void UpdatePhysics()
        {
            float lastTick = Environment.TickCount;
            float sinceLast;
            float refresh = 1000 / 100;
            while (true)
            {
                if (!pausePhysics)
                {
                    space.update(0);
                    sinceLast = Environment.TickCount - lastTick;
                    if (sinceLast < refresh)
                        Thread.Sleep(Convert.ToInt16(refresh - sinceLast));
                    lastTick = Environment.TickCount;
                }
            }
        }
User avatar
Zukarakox
Not a Site Admin
Posts: 426
Joined: Mon Jul 10, 2006 4:28 am

Re: Multithreaded physics

Post by Zukarakox »

space.update(0); is probably the culprit, try moving it to after 'sinceLast = ...' and then change it to space.update(sinceLast);

That might do the trick.
i has multiple toes
Eizon
Posts: 7
Joined: Sat Dec 20, 2008 8:12 pm

Re: Multithreaded physics

Post by Eizon »

Ah, makes sense! I'll try it next time, but I have a lot of other more important features to fix first. I don't really need threading on a game that runs 60fps on 600mHz.
Norbo
Site Admin
Posts: 4929
Joined: Tue Jul 04, 2006 4:45 am

Re: Multithreaded physics

Post by Norbo »

I believe your space.simulationSettings.useInternalTimeStepping is set to false. Setting it to true will be needed as well or else the engine will just do a single timestep every call.

There's some other miscellaneous issues that need to be addressed (timer resolution mainly). Environment.tickCount only provides a millisecond resolution if I'm not mistaken, which isn't quite smooth. I'm currently working on a little example of a good timing setup.
Post Reply