-
-
Notifications
You must be signed in to change notification settings - Fork 260
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Improve determinism with inserting by Entity order #233
base: master
Are you sure you want to change the base?
Conversation
Thanks for looking into this one. I'm currently working on some simulations myself and found differing results from the same builds on different platforms. For your first point, I would prefer this to be included within the feature for "enhanced-determinism" with the option to turn it off. By doing so, cross-platform determinism would work "out of box" and would prevent further confusion. |
forked from PR dimforge#233
@sebcrozet I am ready for this to be reviewed. I selected the feature flag for this purpose because it makes the I implemented sorts on these queries because they have inserts on variables within the context (entity2body, etc). |
7f8e112
to
fd861d7
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
These changes are not doing what you expect. For example:
#[cfg(feature = "enhanced-determinism")]
{
let mut impulse_joints: Vec<(Entity, &ImpulseJoint)> = impulse_joints.iter().collect();
impulse_joints.sort_by_key(|f| f.0);
}
for (entity, joint) in impulse_joints.iter() {
Will create a new impluse_joints
vec and sort it. Then that vec runs out of scope and is dropped (because of the { ... }
), so the impulse_joints.iter()
is still iterating through the unsorted query.
Ah, yes, you are right. I was testing this on a different branch and added all of the feature checks after-the-fact and was not working against the correct branch. My apologies. Is there much point to putting this behind a feature flag at all? |
e88b9ab
to
775e0a0
Compare
775e0a0
to
d447417
Compare
d447417
to
537b1b8
Compare
c98a68f
to
435242a
Compare
Hi @sebcrozet, just wanted to ping you on this PR again. Please let me know if there's anything else I can do to improve this change. Thanks! |
Looking for feedback on this approach. I understand this likely requires additional changes before acceptance.
I have a physics simulation that, when ran twice side-by-side, can produce slightly different data between the two simulations. I determine this data desync by serializing the RapierContext (using bincode) on each frame and then hashing the result. However, after the very first frame, when the SyncBackend systems get to run for the first time, my two simulations return two different hashes. I have the physics and query systems disabled to start, so it is not from StepSimulation yet. I have "enhanced-determinism" on and have a guaranteed creation order of Entities. I have exactly 100 Entities with both RigidBody and a Collider.
This non-determinism in the hash stems from Bevy not having a guaranteed Entity order for Queries, and I have found it fruitful to enforce that constraint in Rapier's systems. This PR shows how I have handled this in my fork. Doing a sort on the Queries as I have done in this PR seems to ensure that all of Rapier's internal data are initialized in exactly the same order, and thus the hashes returned are always the same.
Open questions I have are:
What is the best way to introduce this without also adding performance concerns to users? An option on the RapierConfiguration? There is a feature for "enhanced-determinism", but that has always seemed like a way to select packages to me.
Is there a more efficient way to sort these by Entity?
I feel sorting by Entity is the best way to accomplish this for my purposes, but are there other ways a user may want/need to sort these?