sofa-framework / sofa

Real-time multi-physics simulation with an emphasis on medical simulation.
https://www.sofa-framework.org
GNU Lesser General Public License v2.1
871 stars 297 forks source link

[Simulation.Core] Refactor DefaultAnimationLoop + multithreading #3959

Closed alxbilger closed 8 months ago

alxbilger commented 11 months ago

Split all pipeline steps into smaller functions

Each step of the animation loop now corresponds to a function. For example, the following code:

sofa::helper::AdvancedTimer::stepBegin("BehaviorUpdatePositionVisitor");
BehaviorUpdatePositionVisitor beh(params , dt);
gnode->execute ( beh );
sofa::helper::AdvancedTimer::stepEnd("BehaviorUpdatePositionVisitor");

is now in a function:

void DefaultAnimationLoop::behaviorUpdatePosition(const core::ExecParams* params, const SReal dt) const
{
    sofa::helper::ScopedAdvancedTimer timer("BehaviorUpdatePositionVisitor");
    BehaviorUpdatePositionVisitor beh(params, dt);
    gnode->execute(beh);
}

In the end, the pipeline is easier to read:

sofa::core::MechanicalParams mparams(*params);
mparams.setDt(dt);

behaviorUpdatePosition(params, dt);
updateInternalData(params);

resetConstraint(params);

beginIntegration(params, dt);
{
    collisionDetection(params);

    const core::ConstraintParams cparams;
    buildConstraintMatrix(cparams);
    accumulateMatrixDeriv(cparams);

    solve(params, dt);

    projectPositionAndVelocity(nextTime, mparams);
    propagateOnlyPositionAndVelocity(nextTime, mparams);
}
endIntegration(params, dt);
computeIsolatedForces(params, dt);

updateSimulationContext(params, dt, startTime);

AnimateVisitor

AnimateVisitor is no longer used. It was difficult to read its logic (the visitor called other visitors, it relies heavily on pruning which is easy to miss). Instead, I suggest to explicit all the steps from the AnimateVisitor into the DefaultAnimationLoop. This is closer to what is done in the FreeMotionAnimationLoop. Plus, we can find common steps, which makes the code more consistent.

Note also the introduction of ComputeIsolatedForceVisitor (see the comments in the code to understand its purpose).

Multithreading

Since AnimateVisitor is no longer used, SolveVisitor is used instead, providing optional multithreading, i.e. solving each ODE in parallel. Similar to what was done in the FreeMotionAnimationLoop.

Benchmark

Measured on examples/Component/SolidMechanics/FEM/TetrahedronFEMForceField.scn

Without parallelism

[INFO]    [BatchGUI] 1000 iterations done in 14.7031 s ( 68.0128 FPS).
 LEVEL   START    NUM      MIN     MAX   MEAN     DEV    TOTAL  PERCENT ID
   2       0.03    1      10.57   27.32   11.94    2.11   11.94   82.14 ..solve

With parallelism

[INFO]    [BatchGUI] 1000 iterations done in 7.13825 s ( 140.09 FPS).
 LEVEL   START    NUM      MIN     MAX   MEAN     DEV    TOTAL  PERCENT ID
   2       0.03    1       3.53    6.85    4.45    0.81    4.45   63.60 ..solve

The simulation is 2x faster. But there are 4 different objects, so we expected a speed-up of 4x. However, the speed-up is only about the solve function. Another time consuming function is the end event when computing the von Misses stresses. Still, the solve function only shows a speedup of 2.68x, instead of 4x. I cannot explain it for now...

[ci-depends-on https://github.com/sofa-framework/SofaPython3/pull/362]


By submitting this pull request, I acknowledge that
I have read, understand, and agree SOFA Developer Certificate of Origin (DCO).


Reviewers will merge this pull-request only if

alxbilger commented 11 months ago

[ci-build][with-all-tests]

fredroy commented 11 months ago

[ci-build][with-all-tests]

alxbilger commented 11 months ago

[ci-build][with-all-tests]

alxbilger commented 11 months ago

Another benchmark: examples/Demos/chainAll.scn

With parallelism

1000 iterations done in 41.8915 s ( 23.8712 FPS).

Without parallelism:

1000 iterations done in 91.9302 s ( 10.8778 FPS).
alxbilger commented 10 months ago

[ci-build][with-all-tests][force-full-build]

hugtalbot commented 10 months ago

[ci-build][with-all-tests] (check for MacOS)

fredroy commented 10 months ago

[ci-build][with-all-tests][force-full-build]

alxbilger commented 10 months ago

I don't understand why the dashboard says 2 scenes are failing. When I see the result, I see only one

hugtalbot commented 10 months ago

CI sees apparently twice an error in advancedtimer .. strange

[ERROR]   [AdvancedTimer::end] timer[Animate] does not correspond to last call to begin(cg_timer)
alxbilger commented 10 months ago

There is an error in the test because timer ids changed in this PR

sofabot commented 9 months ago

[ci-depends-on] detected during build #13.

To unlock the merge button, you must

sofabot commented 9 months ago

[ci-depends-on] detected during build #14.

To unlock the merge button, you must

alxbilger commented 9 months ago

The crash that happened on Windows also happens on the master branch on my computer. But I don't understand how it is not detected by the CI

fredroy commented 9 months ago

The crash that happened on Windows also happens on the master branch on my computer. But I don't understand how it is not detected by the CI

Maybe it is random, it does not crash on mine (but I only tried like 2, 3 times) on msvc Nevertheless, I dont think this scene is working as intended anyway.... (the particules do not interact with the static mesh)

hugtalbot commented 9 months ago

It seems strange that the factorization of the mapping propagation at the end of the time step makes the scene crashes.. Have you investigated it further @alxbilger ?

alxbilger commented 8 months ago

[ci-build][with-all-tests][force-full-build]

sofabot commented 8 months ago

[ci-depends-on] detected during build #15.

To unlock the merge button, you must

alxbilger commented 8 months ago

[ci-build][with-all-tests][force-full-build]

sofabot commented 8 months ago

[ci-depends-on] detected during build #16.

All dependencies are merged/closed and all ExternalProject pointers are up-to-date. Congrats! :+1: