add plot generation scripts adjust validation tools add up-to-date results
This commit is contained in:
@@ -0,0 +1,98 @@
|
||||
# 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
|
||||
|
||||
[`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. Partitioning and packing use the nominal priorities;
|
||||
transposes count as bulk moves there. PEFT, final schedule evaluation, and
|
||||
reported per-core demand use physical estimates. These quantities must not be
|
||||
substituted for one another when interpreting results.
|
||||
|
||||
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.
|
||||
Reference in New Issue
Block a user