Skip to content

feat(analysis): settle what peak-footprint claims, and make the claim true #146

Description

@zhen8838

Why

analyze reports # peak-footprint=<level>:<bytes> and refuses a program whose
peak exceeds the capacity a target states (src/tilefoundry/analysis/memory.py:391-395).
The name says "peak", but what is computed is the sum of the bytes live at the worst
point of the program (memory.py:363-380) — a lower bound on what an allocator
would need, because it accounts for neither placement nor fragmentation.

Nothing in this repository allocates buffers: grep -rn 'lifetime\|liveness\|reuse\|binpack' src/tilefoundry/codegen/
returns nothing, and codegen/cuda/tir/memory/alloc_tensor.py emits a declaration.
So the number is a self-standing estimate that no later stage is obliged to meet.

That is sound in one direction and silent in the other:

  • A refusal is trustworthy. If even the optimistic sum exceeds capacity, the program
    cannot fit, whatever the allocator does. No false refusals come from fragmentation.
  • An acceptance is not. A program that fits only under a packing nobody performs is
    accepted, and a program whose fragmentation pushes it over capacity is accepted too.

What

Decide what peak-footprint claims, and make the claim true.

Either:

  • Keep the lower bound and say so. Rename the reported quantity and the refusal
    so a reader knows it is a necessary, not a sufficient, condition, and state in
    docs/spec/cli.md that acceptance means "not provably too large".
  • Make it the allocated peak. Assign every buffer a lifetime, solve the packing
    (a CP-SAT bin-pack, as buffer schedulers such as nncase's do), and report the
    peak that solution reaches. This is only meaningful if codegen then allocates
    under the same policy: an allocated peak that codegen does not follow is a second
    account of the same quantity, and the two will disagree.

Contract

docs/spec/cli.md currently states neither what the number means nor which of the
two readings the refusal carries. Whichever way this is settled, that section is the
place it gets written down.

Risk

The second option is the larger one and it does not stand alone: it needs a codegen
allocation contract to be worth reporting. Filing this separately from the
lifetime-accounting fix below, which is a bug under the current reading and is being
fixed on its own.

Related: the lifetimes feeding today's number are built on a flattened value list
(memory.py:250-276, fed by memory.py:307) that carries no loop nesting, so a
loop-carried value's residency is under-counted. That is a defect under either
reading and is being fixed separately.

Activity

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