Portable Subset

Discuss any questions about BEPUphysics or problems encountered.
Post Reply
toaster
Posts: 14
Joined: Sat Mar 21, 2015 3:44 pm

Portable Subset

Post by toaster »

Hi,

I'm extremely interested in a portable subset version of BEPU Physics. What's the likely hood of this happening soon? Would it be possible for me to port it over myself or is there a lot to change? I think the biggest thing would be the lack of threads. Perhaps we could work together to get this done?

Thanks,
-Toaster
Last edited by toaster on Sat Mar 21, 2015 10:28 pm, edited 1 time in total.
toaster
Posts: 14
Joined: Sat Mar 21, 2015 3:44 pm

Re: Portable Subset

Post by toaster »

I've downloaded the source code and modified it to work inside of a PCL. It wasn't too difficult. However I do have some questions. Is there a reason you didn't use .net's hashset? Because of .net 2.0 I suppose? Also there was this line:

loopFinished.Close();

Close does not exist for an AutoResetEvent I changed this to Dispose() instead. Is this acceptable? I tried looking online, but I couldn't find much.

Finally all the threads were changed to tasks and the Thread.Sleep was changed to Task.Delay inside of the spinlock class. The Thread.SpinWait was also changed to a Task.Delay, although if I read right between the differences in spinwait and sleep that is probably not the best thing to use, however I believe it should work correct?

I might try to port the samples over to monogame or maybe Paradox3D(which only uses PCL). That way I can test to see if it's working or not.

Thanks,
-Toaster
Norbo
Site Admin
Posts: 4929
Joined: Tue Jul 04, 2006 4:45 am

Re: Portable Subset

Post by Norbo »

Is there a reason you didn't use .net's hashset? Because of .net 2.0 I suppose?
.NET's HashSet is used in a few places, unless you're talking about an older version that had a conditional "HashSet" wrapper around Dictionary due to API holes on the Xbox360's compact framework.

If you're referring to the QuickSet, then it's mostly for minor performance reasons:
1) It offers greater reusability of underlying arrays. Resizing doesn't generate garbage, and a QuickSet<int> and a QuickList<int> can pull from the same pool of arrays.
2) It avoids GC involvement at the instance level by being a value type (while biting the bullet on all the complications that entails).
3) QuickSet's implementation is focused on enumeration speed. The elements are stored in a contiguous array, so enumeration does not require any memory hopping. Adds/removes are still competitive with the regular HashSet on most types.
4) The Quick collections are very raw and expose their guts. For example, the elements array can be accessed directly. This can be helpful when wanting to modify the state of a value type stored inside the set without removing and readding it.
Also there was this line:

loopFinished.Close();

Close does not exist for an AutoResetEvent I changed this to Dispose() instead. Is this acceptable? I tried looking online, but I couldn't find much.
Yup, that's fine. Close and Dispose do exactly the same thing on the desktop framework. If I remember correctly, I only used Close because of some old platform issue.
Finally all the threads were changed to tasks
You could also just delete the ParallelLooper entirely and supply another IParallelLooper implementation that wraps existing thread pools if they offer an efficient parallel for loop. The TPL's Parallel.For works great for this purpose; I only implemented the ParallelLooper because of platform holes.
Thread.Sleep was changed to Task.Delay inside of the spinlock class. The Thread.SpinWait was also changed to a Task.Delay, although if I read right between the differences in spinwait and sleep that is probably not the best thing to use, however I believe it should work correct?
I am not entirely familiar with the underlying mechanics of Task.Delay, but if it's functionally similar to Thread.Sleep, then it will work correctly. However, performance may be a problem. Certainly in the case of the spin wait, a Sleep or a blocking wait could produce nasty results, like surrendering the time slice too aggressively. The waiting portion of the SpinLock is probably best replaced by the SpinWait structure.

However, I would recommend just getting rid of the custom SpinLock entirely, and replacing its usages with the PCL-included SpinLock. This is yet another spot where the custom implementation only exists because of old platform support holes.
I'm extremely interested in a portable subset version of BEPU Physics. What's the likely hood of this happening soon? Would it be possible for me to port it over myself or is there a lot to change?
As you've encountered, there's not too much, just these areas left over from ye olde early XNA days. Reducing or eliminating the pain for PCL is something I'd like to do, but I have a history of doing a poor/slow job at maintaining compatibility across a lot of simultaneous targets. It's looking like v1.4.0, which I expect to package up as the stable release in the next couple of months, is going to be the last version which tries to maintain backwards compatibility with Xbox360 and WP7.

v2.0.0 will probably be the next version and will toss out as much cruft as possible, so it should be easier. (That, and early fiddling implies it will probably be at least twice as fast on many simulations, before taking into account SIMD types :))
toaster
Posts: 14
Joined: Sat Mar 21, 2015 3:44 pm

Re: Portable Subset

Post by toaster »

The file still exists in the folder and when I created my new project I added it in not realizing it. The quick set is still there for sure.
You could also just delete the ParallelLooper entirely and supply another IParallelLooper implementation that wraps existing thread pools if they offer an efficient parallel for loop. The TPL's Parallel.For works great for this purpose; I only implemented the ParallelLooper because of platform holes.
I might change this in the future.
However, I would recommend just getting rid of the custom SpinLock entirely, and replacing its usages with the PCL-included SpinLock.
Quite an easy fix as well just renamed the SpinLock class and added in the missing references.

Hopefully I can test it out soon! I'll try to post some screenshots/video/code when I get a chance.
Norbo
Site Admin
Posts: 4929
Joined: Tue Jul 04, 2006 4:45 am

Re: Portable Subset

Post by Norbo »

The file still exists in the folder and when I created my new project I added it in not realizing it. The quick set is still there for sure.
Oops, yup- for some reason I thought the Xbox360 had eventually added that. Guess not! The QuickSet is expected.

Notably, the WINDOWS compilation symbol should be safe to use when compiling for PCL. It's a bit of a misnomer in these post-XNA times; it just stops the HashSet wrapper from being used as well as a few other Xbox360/WP7 oddities.
toaster
Posts: 14
Joined: Sat Mar 21, 2015 3:44 pm

Re: Portable Subset

Post by toaster »

I'm getting an error on locker.Exit():

Error: Unexpected exception while executing a micro-thread. Reason: System.Threading.SynchronizationLockException: The calling thread does not hold the lock.

The stack trace:

at BEPUutilities.DataStructures.ConcurrentDeque`1.TryDequeueFirst(T& item) in BEPUutilities\DataStructures\ConcurrentDeque.cs:line 114
at BEPUutilities.ResourceManagement.LockingResourcePool`1.Take() in BEPUutilities\ResourceManagement\LockingResourcePool.cs:line 95
at BEPUphysics.PhysicsResources.GetSimulationIslandConnection() in BEPUphysics\PhysicsResources.cs:line 171
at BEPUphysics.Constraints.SolverUpdateable..ctor() in BEPUphysics\Constraints\SolverUpdateable.cs:line 141

The line numbers might be slightly off from the original code after my edits. I tried to look up the error but I am afraid it's a bit outside of my threading knowledge. Any ideas for this issue?
Norbo
Site Admin
Posts: 4929
Joined: Tue Jul 04, 2006 4:45 am

Re: Portable Subset

Post by Norbo »

That is peculiar; it implies that locker.Enter was not called. I would recommend first verifying that TryDequeueFirst calls Enter properly... but if it does, then I'm not sure.
toaster
Posts: 14
Joined: Sat Mar 21, 2015 3:44 pm

Re: Portable Subset

Post by toaster »

I tried:

Code: Select all

        public bool TryDequeueFirst(out T item)
        {
            bool taken = false;
            //locker.Enter(ref taken);
            locker.Enter(ref taken);

            if (taken)
            {
                try
                {
                    if (count > 0)
                    {
                        item = array[firstIndex];
                        array[firstIndex] = default(T);
                        firstIndex++;
                        if (firstIndex == array.Length)
                            firstIndex = 0;
                        count--;
                        return true;
                    }
                    item = default(T);
                    return false;
                }
                finally
                {
                    locker.Exit();
                    //locker.Exit();
                }
            }

            item = default(T);
            return false;
        }
but no luck still fails on the locker.Exit(); which is odd if it successfully locked.
Norbo
Site Admin
Posts: 4929
Joined: Tue Jul 04, 2006 4:45 am

Re: Portable Subset

Post by Norbo »

Oops, I remember now:
1) The PCL SpinLock is a struct.
2) The locker field is readonly.
3) Calling Enter mutates the struct.
4) The attempted mutation of the struct creates a local mutable copy that isn't stored back into the readonly field.
5) Later Exit operates on the unmutated field value.

So, if you remove the readonly it should work.
toaster
Posts: 14
Joined: Sat Mar 21, 2015 3:44 pm

Re: Portable Subset

Post by toaster »

Perfect I have a character controller interacting with my static world mesh. It seems to work perfectly! I'll try to get the code uploaded as soon as I port over the character controller demo.
Post Reply