Skip to content

WIP: Add experimental DSA memory-planner adapter - #2052

Draft
tonibohnlein wants to merge 47 commits into
hw-native-sys:mainfrom
tonibohnlein:dsa-memory-planning-solver
Draft

WIP: Add experimental DSA memory-planner adapter#2052
tonibohnlein wants to merge 47 commits into
hw-native-sys:mainfrom
tonibohnlein:dsa-memory-planning-solver

Conversation

@tonibohnlein

@tonibohnlein tonibohnlein commented Jul 14, 2026

Copy link
Copy Markdown
Contributor

Summary

  • add an optional MemoryPlanner.DSA path that exports unmerged physical
    allocations, invokes a standalone C++ DSA solver, independently validates
    the placement, and writes offsets back to PyPTO MemRefs
  • solve standard buffer-level DSA geometry: lifetime conflicts and explicit
    separations are address-disjoint; lifetime-disjoint buffers may reuse and
    subdivide freed regions
  • preserve mandatory aliases, pools, capacities, reservations, alignment,
    target/no-alias constraints, and pipeline-stage separations
  • add schema-v1 corpus export, capability checks, PassContext/system-test
    planner selection, and focused adapter tests

Status

This is a draft/WIP implementation for RFC #1980 and #1908. It does not yet
close either issue.

The external tonibohnlein/dsa-solver
dependency is temporary research scaffolding. PyPTO pins
0af3c08
(package version 0.8.0). Once a production heuristic is selected and validated,
it should be ported into PyPTO and the external dependency removed.

Architecture

InitMemRef
  -> MaterializeSemanticAliases
  -> collect unmerged physical allocations
  -> standalone DSA solver
  -> independent validation
  -> write offsets back to MemRefs

The DSA path skips opportunistic MemoryReuse coalescing but reuses its
phi/loop-aware lifetime and constraint analysis. Each physical allocation is
exported with one conservative lifetime hull; unproven gaps between SSA aliases
are not exposed as reusable memory.

Standard DSA geometry

The former global whole-slot restriction is disabled. A freed region may be
subdivided among smaller co-live buffers, which is the geometry required by
#1908.

PyPTO contributes constraints and provenance:

  • fixed pools, capacities, reservations, and alignment
  • mandatory alias classes
  • target and semantic no-alias separations
  • hard separation of pipeline stages that must coexist

The uncalibrated pipeline_serialization cost proxy is research-only and is not
used by the production first-fit path.

Validation

Current exact pins:

  • PyPTO: 27ceb9f6
  • dsa-solver: 0af3c08a
  • PyPTO-Lib: 6e897cd9

Host and CI gates:

Current device blocker: partial-overlap dependency

The blocking 910B2 gather gate fails deterministically under DSA on four
devices while PyPTO passes:

test_gather.py::TestGatherIndex::test_gather_tile_input_source_unchanged[a2a3]

The standard DSA placement reuses part of an expired 4 KiB allocation:

assemble_src       [4096, 8192)  last read by pto.tmov
gather_idx_row     [4608, 4640)  later written by pto.tload

The placement is valid against the exported sequential lifetimes. However,
PTOAS v0.48 does not emit the required cross-pipe WAR synchronization for this
partial overlap. The later 32-byte load can overwrite data still being consumed
by the move, producing exactly eight corrupted FP32 elements. Equal-base reuse
is handled, but arbitrary range overlap is not currently represented safely
through the PyPTO fixed-address path.

This is not the earlier multi-interval-hole defect and not a standalone-solver
feasibility bug. The remaining design work is to preserve standard DSA
subdivision while making partial-overlap reuse dependency-safe, either through
range-aware downstream dependency handling or a narrowly grounded PyPTO
constraint/repair. Reintroducing the former global whole-slot rule would hide
the defect but would also remove the #1908 subdivision capability.

Until this blocker is fixed and rerun, this PR makes no end-to-end correctness
or performance claim for standard partial-overlap placement.

Remaining WIP

Corpus and research

The standalone repository contains 452 unique checked-in PyPTO/PyPTO-Lib
instances
after structural deduplication, plus the MiniMalloc benchmark
family. Benchmark reports keep standard DSA peak/runtime separate from
PyPTO-specific research objectives.

Related

@coderabbitai

coderabbitai Bot commented Jul 14, 2026

Copy link
Copy Markdown

Important

Review skipped

Draft detected.

Please check the settings in the CodeRabbit UI or the .coderabbit.yaml file in this repository. To trigger a single review, invoke the @coderabbitai review command.

⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro Plus

Run ID: 8763d6ad-87fb-498e-b2a1-b048f60b48d0

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Use the checkbox below for a quick retry:

  • 🔍 Trigger review

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@gemini-code-assist gemini-code-assist Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review

This pull request introduces a pluggable standalone DSA (Dynamic Storage Allocation) memory-planning solver and its adapter to PyPTO, adding the MemoryPlanner.DSA option to allow joint lifetime reuse and offset selection. When active, the pipeline skips opportunistic MemoryReuse and uses AllocateMemoryAddr to export a deterministic schema-v1 JSON problem, solve it using the standalone solver, validate the placement, and write back physical addresses. Feedback on the changes highlights two key issues: first, the PYPTO_ENABLE_DSA_SOLVER preprocessor definition must be defined globally in CMakeLists.txt so that conditional compilation blocks in the core C++ sources are correctly compiled; second, the adapter should generate dense, sequential BufferIds instead of casting the raw interval index, as sparse IDs can violate solver assumptions and lead to out-of-bounds indexing.

Important

The consumer version of Gemini Code Assist on GitHub is being sunset. Starting June 18, 2026, new organization installations will be blocked, and all code review activity will officially cease on July 17, 2026.
For more details on the timeline and next steps, please review the Help Documentation.

Comment thread CMakeLists.txt
Comment thread src/ir/transforms/dsa/memref_dsa_adapter.cpp Outdated
…w-native-sys#1980)

Phase 1: IR-free DsaSolver interface + FirstFitByLifetimeSolver (per-pool,
colocation super-buffers, separation adjacency, decreasing-size skyline) +
independent Validate + passes.dsa binding + 11 unit tests.

Phase 2: ComputeAllocationLifetimes shared entry point (LifetimeInterval moved
to utils/lifetime_analysis.h); BuildDsaProblem adapter; MaybeConsultDsaSolver
runs the solver on real IR behind PYPTO_DSA_SOLVER=1 and logs DSA-peak vs
bump-peak per space, bump stays authoritative. 2159 transform tests pass.
…#1980)

ComputeAllocationPlan now returns intervals + separations (index pairs that must
stay apart). Pipeline double-buffer clones (same group, different stage via
PipelineMembershipsConflict) are emitted as DsaProblem separations so the solver
keeps ping-pong operands in distinct buffers instead of collapsing them.

Adds dsa::GetSolverMode (PYPTO_DSA_SOLVER: consult/1 vs plan vs off); MemoryReuse
skips its pipeline_membership strip when the solver is engaged so pass 31's
adapter can see the tags (codegen already tolerates the surviving attr — it does
under memory_planner=PTOAS where the strip is skipped anyway).

Verified: expert_routed L0A/Left consult goes 4096 -> 8192 (double-buffer kept
apart). 2159 transform tests pass.
…ive-sys#1980)

ComputeAllocationPlan now also emits the Ascend910B load+tpop_from_aic in-place
hazard (backend-gated) and op-semantic forbid-alias (e.g. tile.sel mask/tmp vs
output) as separations — the same constraints MemoryReuse honors — so the solver
never forms those unsafe aliases. Takes FunctionPtr now (for the hazard guard).
Forbid operands resolve to allocations via base_ identity (no reuse chain pre-solve).

2159 transform tests pass; expert_routed consult clean (no validator warnings).
…tive-sys#1980)

Adds ApplyDsaSolution (solution offsets -> MemRef byte_offsets, mirroring the
bump's slot-base + relative fold) and MaybePlanWithDsaSolver. In 'plan' mode the
solver's addresses replace the bump's, but only through a hard gate: feasible
AND every space's peak <= the bump's AND validator clean; otherwise it falls back
to the bump (never worse). 'consult'/'1' still just logs.

Tests use AIV (InCore) kernels — a plain @pl.function is non-InCore so the pass
no-ops. plan mode reuses tile_c into tile_a's slot (peak 49152 -> 32768); consult
mode leaves the bump untouched. Verified on expert_routed: all 6 kernels apply
the plan (gate passed), compile succeeds. 2160 transform tests pass.
…hw-native-sys#1980)

Pipeline-clone separations are now capacity-gated (hw-native-sys#1949 core): keep only
F_g = max(1, min(depth, floor(cap/slot))) residues apart, so lifetime-disjoint
same-residue clones reuse instead of the full-depth spread that overflowed tight
L0B kernels.

Deferred (surfaced blocker): skipping MemoryReuse's opportunistic merge under
=plan (the prerequisite for the hw-native-sys#1908 sub-region fix) is not safe yet — the
optimistic F_g cannot replicate MemoryReuse's full mutable shed loop + exact
SpaceFootprint refit, so expert_routed's matmuls overflow L0B (3 co-live 32KB
Right buffers = 96KB > 64KB) and the gate falls back to an already-overflowing
un-merged bump. =plan therefore runs on MERGED groups for now (safe, gate-bounded,
all expert_routed kernels apply + compile passes); hw-native-sys#1908 not yet fixed by =plan.

2160 transform tests pass.
Attach deterministic SSA dependency paths to pre-promotion reuse candidates. Add function-keyed PTOAS summary comparison and candidate inspection tools with regression tests and synchronized documentation.
@tonibohnlein
tonibohnlein force-pushed the dsa-memory-planning-solver branch from 1b95c88 to bcac01f Compare July 28, 2026 15:12
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

Status: No status

Development

Successfully merging this pull request may close these issues.

1 participant