Skip to content

Body states in float for the wide contact stages #95

Closed

Description

@nicolas-maman

From #90. The wide contact solver reads body states in double. Each gather_bodies converts 52 doubles (13 per body for 4 lanes), and each scatter converts back. Box3D keeps BodyState in float, padded to 64 bytes, so it gathers with four 4x4 transposes.

Tried and dropped in #90:

  • a native SSE gather that converts in C and returns the lanes through memory. It was bit-identical but 20% slower on the warm start, because of the memory round-trip.

What would likely help is having the states themselves in float for the contact stages:

  1. An f32 mirror of the awake states, refreshed per step. It needs a sync at the integrate stages, and joints read the double states.
  2. BodyState in float throughout. This touches integration, joints and every reader of velocities, and changes results. Box3D computes in float, so this would move us closer to the reference.

Either option should be measured against main on the three bench/physics_world scenes before it lands. Option 2 also needs the determinism goldens and the cross-platform trace re-checked.

Activity

  1. nicolas-maman commented on Oct 5, 2026

    @nicolas-maman
    CollaboratorAuthor

    Measured on 2026-10-05 and dropped, so it isn't tried again: a velocity-only gather for the warm start (6 of the 13 doubles per body; the warm start reads no positions). Bit-identical, and the warm stage was unchanged interleaved against main over 4 rounds (large pyramid 0.99-1.01 ms on main, 0.99-1.06 with it; the other two scenes the same). GCC already drops the unused loads once gather_bodies is inlined, so the conversion cost this issue is about is only what each stage really reads: the 6 velocities, plus the 7 delta position and rotation values in the solve, relax and restitution.

  2. nicolas-maman commented on Oct 5, 2026

    @nicolas-maman
    CollaboratorAuthor

    Also measured on 2026-10-05 and dropped: BodyState padded from 112 to 128 bytes, so each state could be two whole cache lines. The buffers are calloc-backed (16-byte aligned), so the padding alone doesn't line states up. Each scene alone, interleaved 4 rounds against #107: no consistent change (large pyramid slightly worse, joint grid and many pyramids within the spread). A 64-byte-aligned state buffer would be the honest test of this, but the probe gives no reason to expect much. The float states this issue proposes would halve the record instead (64 bytes, as the reference has it).

  3. nicolas-maman commented on Oct 5, 2026

    @nicolas-maman
    CollaboratorAuthor

    Where this stands (2026-10-05, main 3aa5d25). The four-lane contact stages are at or near Box3D's four-lane float path on the large pyramid, stage for stage:

    stage aephysics Box3D f555ee4 (four lanes)
    warm start 0.93-1.06 ms 1.17
    solve 1.86-2.00 1.76
    relax 2.29-2.38 2.24

    The double-to-float conversion this issue is about doesn't show at four lanes: the warm start is already ahead. Float states would buy a few percent on the solve and relax, at a precision cost and with new determinism goldens.

    The case changes with eight lanes (#96). Gathering eight bodies doubles the conversion work, where Box3D transposes float states. So this issue goes ahead when #96 does. Until then it's parked: worth less than its cost.

  4. added 2 commits that reference this issue on Oct 7, 2026
  5. nicolas-maman commented on Oct 7, 2026

    @nicolas-maman
    CollaboratorAuthor

    Done in #126 (a896022): BodyState is the reference's 64-byte float layout; AVX2 large pyramid 8.18-8.69 to 7.71-8.00 ms, many pyramids 19.9-20.9 to 18.8-19.7, joint grid level. Numbers in RESULTS.md, 'Body states in float'.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions