Skip to content

Engine benchmark and an allocation-free update()/differentiate() #233

Open

Description

@petlenz

Part of #237.

Why

The FFT homogenization host evaluates one material point per voxel per iteration, millions of times per load step. The engine has gained iteration groups, systems, derivative plans and checkpoints since #173, and nobody has measured it since. The review found per-call allocations:

There is no benchmark in the repo (tests/, examples/ and tools/ have none).

Design

  • benchmarks/engine_bench.cpp, a plain std::chrono harness with no new dependency, built when NUMSIM_MATERIALS_BUILD_BENCHMARKS=ON and always at -O3 -DNDEBUG. It runs these cases, each per point update after warm-up, as median of N runs:
    1. linear elasticity: update();
    2. the same with derivative(stress, strain);
    3. J2 on system with the implicit-function-theorem tangent;
    4. the damage chain with accumulated derivative;
    5. the nonlinear mean-field composite (iteration group);
    6. checkpoint() + restore().
  • Allocation counter. A replaced global operator new in the benchmark executable counts allocations. Each case asserts zero allocations per update after the first call, and a test target runs the same assertion as a gtest, so CI catches a regression.
  • Fixes:
    • J, B and dx/dp become members of the derivative plan, sized once;
    • Eigen solves into preallocated storage (PartialPivLU member, compute + solve into a member);
    • checkpoint() writes into a reusable std::vector<std::byte> buffer through the existing serialize() hooks, or a binary path if serialize needs a stream;
    • anything else the counter finds.
  • Baseline. Run the same cases on main, before Epic: property engine 2 — inspectable graph, in-engine iteration, residual systems and derivative edges #221, where the API exists (cases 1, 2 via the hand-written tangent, and 4). Report the table in the PR.

Tests

  • A gtest EngineHotPath.UpdateAndDifferentiateDoNotAllocate with the counting operator new, for the cases above (red first on the current code).
  • The benchmark builds in CI. It only runs there, without timing assertions, because CI timing is noisy.

Depends on

#232 (the fixes land in the split units).

Out of scope

  • SIMD or batching several points per call; that belongs to the FFT host design.
  • Threading.

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