48e9fb3795
Validate Operations / validate-operations (push) Failing after 3h13m5s
update results_comparison.csv
121 lines
7.3 KiB
Markdown
121 lines
7.3 KiB
Markdown
# Scheduling implementation notes
|
|
|
|
The [scheduling overview](scheduling.md) maps ownership and summarizes costs/complexity.
|
|
Normative graph, pipeline, synchronization, and target contracts are linked
|
|
there; the details below describe current implementation choices.
|
|
|
|
## Publication, order, and local materialization
|
|
|
|
Deferred transfer planning allocates one host slot for repeated full-fragment
|
|
requirements with the same physical producer, payload type, and source slot.
|
|
One immutable producer result identifies one logical inference generation.
|
|
Scalar source projections retain separate publications until their exact
|
|
geometry has a common representation in both analyses.
|
|
|
|
Boundary planning moves a shared publication's notifications to its earliest
|
|
existing send boundary. The first notification stores the payload before READY;
|
|
later notifications emit READY only. Each reader retains its load and READY
|
|
count. FREE planning includes every physical reader before the first overwrite
|
|
of the shared slot. Existing unique writer-reader releases, register allocation,
|
|
capacity-driven FREE-group merging, and restart barriers remain in force.
|
|
|
|
Host-slot allocation and shared-boundary planning take expected linear time
|
|
and space in the number of physical consumer transfers. Structured send runs
|
|
retain compact per-lane store flags. They do not duplicate payload shaping
|
|
for notification-only readers.
|
|
|
|
[`materializeScheduledCompute`](../../src/PIM/Dialect/Spatial/Passes/Transforms/MergeComputeNodes/ScheduledComputeMaterialization.cpp) records
|
|
graph IDs for publication identity, not execution order. Class lanes retain
|
|
graph encounter order independently of physical core IDs, preserving regular
|
|
source-lane mappings. Within each core, instances sort by verified scheduler
|
|
slots. Only consecutive compatible instances form homogeneous runs; class-lane
|
|
ordering must not reorder a core's work.
|
|
|
|
`insertLocalFragment` replaces a complete singleton insertion with a leading
|
|
unit-dimension reshape view only when:
|
|
|
|
- source and destination have static shapes;
|
|
- destination rank is source rank + 1, with leading dimension 1 and remaining
|
|
dimensions exactly equal to the source shape;
|
|
- element type and encoding match;
|
|
- offset/size/stride lists all match destination rank; and
|
|
- every offset is statically zero, every size is the full corresponding
|
|
destination dimension, and every stride is statically one.
|
|
|
|
This includes scalar sources. Other insertions retain `tensor.insert_slice`
|
|
semantics rather than being converted into views.
|
|
|
|
Receive forwarding belongs to
|
|
[`PimBufferizationPass.cpp`](../../src/PIM/Dialect/Pim/Passes/Transforms/Bufferization/PimBufferizationPass.cpp),
|
|
after copy lowering and contiguity normalization. It requires a private
|
|
allocation and single-use receive/copy chain in the same block, zero source and
|
|
receive offsets, and equal sizes. The receive can sink to the copy target past
|
|
memory-effect-free operations and `memref.load` (including lane lookup loads).
|
|
Writes, synchronization, and other effectful operations are barriers. Forwarding
|
|
does not establish synchronization policy.
|
|
|
|
## Transfer accounting and transpose costs
|
|
|
|
[`ComputeGraph.cpp`](../../src/PIM/Dialect/Spatial/Passes/Transforms/MergeComputeNodes/Scheduling/ComputeGraph.cpp) uses the same cached publication map for
|
|
dependency extraction and projected transfer volume. Physical slots map back
|
|
to graph lanes; graph-range overlap is not a byte estimate. Blueprint edges
|
|
belong to this shared graph for both scheduling strategies.
|
|
|
|
Exact projections charge selected physical fragments individually, including
|
|
each fragment's byte, endpoint-memory, and packet rounding. Conservative batch
|
|
dependencies charge a producer chunk as one aggregate: scale element count by
|
|
chunk lanes, multiply by effective bitwidth, then round to bytes once before
|
|
memory-access/flit rounding. Dividing an already rounded whole-result byte
|
|
count would lose sub-byte payloads. These two granularities are deliberate.
|
|
Spatial can analyze sub-byte storage; PIM communication lowering requires
|
|
byte-sized elements. Blueprint assembly charges per fragment. A full fragment
|
|
receive directly into assembly storage omits duplicate endpoint-memory edge
|
|
cost; later copy elimination can leave this estimate conservative.
|
|
|
|
Execution transpose costs share `getTransposeRun` with lowering: round memory
|
|
reads/writes per run and add vector execution when source stride is not one.
|
|
The [Pimsim vector unit](../../backend-simulators/pim/pimsim-nn/src/core/component/VectorUnit.cpp)
|
|
charges vector payload bytes, not the full strided address footprint. The
|
|
compiler model follows that accounting; instruction setup/issue and contention
|
|
remain approximations, not extra inferred memory traffic.
|
|
|
|
## Priorities, placement, and recovery limits
|
|
|
|
[`PipelineScheduling.cpp`](../../src/PIM/Dialect/Spatial/Passes/Transforms/MergeComputeNodes/Scheduling/PipelineScheduling.cpp) caches a per-template
|
|
adjustment between physical execution cost and nominal volume priority, scaling
|
|
it by chunk lanes. The original partitioning and packing candidate uses nominal
|
|
priorities; transposes count as bulk moves there. The memory-aware candidate
|
|
uses execution estimates for partitioning, retaining the existing core-budget
|
|
and packing heuristics. Final
|
|
selection evaluates bounded alternatives after physical placement, retaining
|
|
the original candidate when the combined resource estimates worsen. PEFT,
|
|
final schedule evaluation, and reported per-core demand use physical estimates.
|
|
These quantities must not be substituted for measured simulator periods.
|
|
|
|
Placement compares maximum per-core serial compute plus incident same-stage
|
|
transfer demand, then completion/span and compute load. Each participating core
|
|
is charged incident transfer demand as a placement proxy; those charges are not
|
|
summed twice into elapsed time. Within 1% demand difference, span breaks the tie.
|
|
Ordered packing plus dependency-tail priority biases cuts away from long
|
|
dependent groups; it is not a throughput prediction. Measured simulator periods
|
|
remain authoritative, including when a proxy improves.
|
|
|
|
Core budgets come from stage allocation and bounded capacity recovery. Failed
|
|
packing budgets are not lower bounds. [PEFT reservations](../../src/PIM/Dialect/Spatial/Passes/Transforms/MergeComputeNodes/Scheduling/PeftScheduler.cpp)
|
|
prefer weight reuse when distinct weights exceed half the fleet's one-copy
|
|
resident capacity; otherwise they favor communication/load. The reuse-first
|
|
constructor supplies feasibility recovery without replacing a successful
|
|
reservation, and can concentrate work. No exact combinatorial solver proves
|
|
infeasibility after heuristic failure.
|
|
|
|
[`ResidentWeightPacking.hpp`](../../src/PIM/Dialect/Spatial/Passes/Transforms/MergeComputeNodes/Scheduling/ResidentWeightPacking.hpp) adds at most 17
|
|
constructions after initial failure: one reverse traversal, then up to 16
|
|
single-choice replays sharing 65,536 candidate checks. Scratch buffers are reused;
|
|
an extra `O(T)` failed-assignment snapshot is created only after both initial
|
|
orders fail. Weight indexing still has `O(R W)` worst-case equality work; partition
|
|
DP and latency insertion-gap searches remain superlinear as listed in the
|
|
scheduling overview. Cached PEFT center distances avoid a topology scan per task/candidate;
|
|
projection and priority analyses share/cache work rather than revisiting every
|
|
template body per chunk. Ready-transfer signature searches remain another
|
|
potential compile-time hotspot.
|