even better more structured throughput scheduling
Validate Operations / validate-operations (push) Has been cancelled

plot adjustments
validation adjustments
This commit is contained in:
NiccoloN
2026-10-27 17:46:46 +01:00
parent 49d6fb42cf
commit a77edafcbf
46 changed files with 3265 additions and 1043 deletions
+1 -1
View File
@@ -24,7 +24,7 @@ Boolean switches default to off unless stated otherwise.
| `--pim-conv-stream-chunk-positions=N` | Output positions per streamed chunk; default: 1024. |
| `--pim-report-conv-lowering=true\|false` | Bounded lowering report; default: true. |
| `--pim-disable-spatial-planning` | Choose each plan's first dense alternative; ONNX rewrites and graph merging remain enabled. |
| `--pim-disable-synchronization` | Omit wait/sync for ablation; removes correctness guarantees for buffer reuse and restart. |
| `--pim-disable-synchronization` | Keep the normal selected schedule and omit wait/sync during code generation. Report a separate zero-cost synchronization estimate for ablation. Removes correctness guarantees for buffer reuse and restart. |
| `--pim-detect-communication-deadlock` | Check expanded blocking send/receive ordering. |
| `--pim-verify-bufferization-copy-freedom` | Run the expensive pre-bufferization copy-freedom proof. |
+5 -7
View File
@@ -136,12 +136,10 @@ remain approximations, not extra inferred memory traffic.
[`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,
it by chunk lanes. Initialization uses nominal priorities; transposes count as
bulk moves there. One joint prefix/resource DP constructs the initial partition.
Bounded beam refinement changes partitions and their core allocations together.
Queue-aware Spatial evaluation scores every admitted physical placement. PEFT,
final schedule evaluation, and reported per-core demand use physical estimates.
These quantities must not be substituted for measured simulator periods.
@@ -220,7 +218,7 @@ Consumed prefixes, capacities, and compaction indices cannot affect future timin
An idle controller's past completion cannot delay future arrivals.
These normalizations require causal, monotonic transitions, which the proof checks.
Proof construction uses at most 256 generations and 16 MiB of snapshot storage.
Proof construction uses at most 1024 generations and 64 MiB of snapshot storage.
Each checkpoint scans events, dependencies, and remaining tokens, then orders a copy of the pending frontier.
Exact comparisons use bounded history; hashes only filter comparisons.
Unproved recurrence remains explicit and cannot guide multi-candidate selection.
+89 -27
View File
@@ -2,7 +2,7 @@
`prepareSpatialSchedules` constructs the shared `ComputeGraph`. Latency mode
uses PEFT. For `--pipeline > 1`, the PIM compiler selects among bounded pipeline
candidates with static queue-aware instruction analysis. Pipeline mode does not run PEFT.
candidates with static queue-aware Spatial execution analysis. Pipeline mode does not run PEFT.
See [implementation notes](scheduling-implementation.md) for fragment-view eligibility,
receive forwarding, transfer rounding, cost-model boundaries, and recovery limits.
@@ -15,7 +15,7 @@ receive forwarding, transfer rounding, cost-model boundaries, and recovery limit
| Target resources and physical link costs | Compiler target adapter via `SchedulingTarget` |
| Latency priorities, reservations, placement, per-core order | `PeftScheduler` |
| Capacity-driven workload splitting | `PipelineWorkloadPreparation` |
| Groups, stage partitioning, core budgets | `buildPipelineGroups`, `partitionPipelineGroups`, `assignPipelineStages` |
| Groups, stage partitioning, core budgets | `buildPipelineGroups`, `initialPipelinePartition`, `optimizePipelineSchedule` |
| Topology clustering and stage-local packing | `PipelineCoreLayout`, `packPipelineStages`, `IndexedResidentWeights` |
| Timing evaluation and publication equivalence | `evaluateSchedule`, `populateScheduleEquivalenceClasses` |
| Selected execution order and homogeneous runs | Scheduled compute planning/materialization |
@@ -58,14 +58,61 @@ paths exclude core-order constraints; completion includes them. Stage spans
exclude cross-stage routing, restart/host synchronization, and contention.
Simulator latency and measured throughput remain the performance gates.
Pipeline candidate generation retains the original ordered-packing/dependency-tail
heuristic and the memory-aware and sharing-aware searches. The partition DP
keeps at most eight compute/memory trade-offs per state. Four final alternatives
and the initial partition undergo core allocation, topology placement, and
capacity verification. The previous compute/memory guards identify candidate
zero, the original fallback. They do not reject legal alternatives before queue
analysis. All candidates preserve candidate zero's non-empty pipeline stages.
PEFT is unchanged.
Throughput scheduling uses one bounded joint optimizer. Initialization groups all
lanes of an operation and computes one ordered partition with a prefix DP.
The DP jointly assigns operation prefixes and at most sixteen units of spare
core capacity. Each configured stage reserves one physical core. Quantization
limits initialization only; refinement uses geometric core transfers, including one core.
Quantization can miss a feasible allocation. Initialization failure reports a
bounded-search limitation, not proved hardware infeasibility.
The seed minimizes maximum stage packing/dependency priority over the legal
active-stage counts within the configured depth. These priorities provide
a starting point, not a timing guarantee. Refinement can remove stage boundaries.
No empty stage is inserted between dependent operations.
Every proposed partition receives a minimax core budget for its changed stages.
Unchanged stages retain their budgets. The allocator builds
constructive ordered-packing curves and uses reuse-first resident-weight packing
when order alone cannot realize a capacity bound. A feasible packing remains
feasible with idle extra cores. All placements pass the existing topology-aware
physical packing, operation-group, adjacency and capacity checks.
Refinement uses a beam of two schedules ranked by the larger queue estimate.
Its ordered neighborhood moves operation groups across adjacent stage boundaries,
inserts a boundary, or removes consecutive boundaries.
Refinement preserves contiguous groups in the initialization's topological order.
Coalescing compacts later stages. Each changed block redistributes its core pool.
Core coordinates also transfer powers of two between stages, including one core.
These moves cross packing plateaus within a bounded number of evaluations.
The configured pipeline depth and total physical resources remain fixed.
A cheap proxy ranks the neighborhood before physical packing and queue analysis.
It uses ordered-packing curves, dependency spans and aggregate shared-memory demand.
Refinement uses the target's existing per-operation execution costs, rather than
redistributing aggregate processor work across operations.
Processor service and critical recurrence contributions guide ties toward affected bottlenecks.
The PIM adapter supplies target-neutral processor guidance from the shared periodic
graph. PIM timing semantics remain outside Spatial.
The optimizer evaluates at most thirty-two complete Spatial queue costs and attempts
at most 128 constructive allocations and physical packings.
Each round evaluates at most two new placements.
Each retained parent receives one queue-evaluation opportunity per round.
The first round can evaluate two neighbors of its single parent.
The two best evaluated schedules form the next beam.
All evaluated schedules remain available for final comparison.
Search stops at the evaluation or
packing budget, or when the beam's legal unvisited neighborhood is exhausted.
Canonical stage/budget vectors, physical core order and evaluation index break
ties deterministically. Actual physical placements, including inactive-core
stage identities, are deduplicated. The final 2.1% near-equivalence policy compares
the retained queue estimates. There are no independent legacy, sharing-aware,
allocator-only or boundary-shift candidate-generation policies.
Unavailable timing, unsupported static forms or unproved recurrence explicitly
stop a costed search. They are not silently discarded. One operation group or
one distinct neighborhood schedule skips optional queue comparison and lowers
once. Final backend resource retries remain restricted to already costed schedules.
`ComputeGraph` retains physical publication and consumer identities separately
from aggregated dependency edges. Cross-stage demands charge one store per
@@ -247,27 +294,28 @@ pending tokens. The event heap contains at most one event per node. FIFO token
storage retains pending generations, rather than instruction-stream copies.
The diagnostic limits each event to 64 generations and processed events to
`16(V + E)`. It reports `unavailable` if either bound prevents convergence.
The two tie-order runs reuse the same graph. Production uses this queue execution directly and omits maximum-cycle-ratio analysis.
The two tie-order runs reuse the same graph. Production uses queue execution for costs and maximum-cycle-ratio analysis for bounded search guidance.
The standalone frontend retains the recurrence witness. Neither analysis changes latency PEFT.
## Default throughput selection
Full PIM code generation uses Spatial-only queue-aware selection for `--pipeline > 1`.
Latency PEFT and `--pim-only-codegen` retain their existing behavior.
Intermediate emission retains the original schedule and stops at its requested stage.
Intermediate emission retains the initialized schedule and stops at its requested stage.
Its schedule can differ from the final program.
The compiler performs these steps:
1. Run the frontend, layout planning, and graph preparation once.
2. Generate at most eleven legal schedules from the existing searches.
3. Remove duplicate physical placements, including stage identities and core order.
4. Realize each candidate in an independent clone of the prepared checkpoint.
2. Construct one legal initial partition, allocate cores, and place its work.
3. Rank legal joint partition/allocation moves with inexpensive resource proxies.
4. Realize each admitted schedule in an independent clone of the prepared checkpoint.
5. Query the target adapter over realized Spatial IR, then release the clone.
6. Require supported static forms, available costs, and proved modeled recurrence for every candidate.
7. Select a candidate with the existing 2.1% selection margin.
8. Realize the selected schedule again from the unchanged checkpoint.
9. Lower, allocate, verify, and emit only the selected program.
6. Require supported static forms, available costs, and proved modeled recurrence.
7. Refine a two-schedule beam within thirty-two total queue evaluations.
8. Apply the existing 2.1% near-equivalence rule to the evaluated schedules.
9. Realize the selected schedule again from the unchanged checkpoint.
10. Lower, allocate, verify, and emit only the selected program.
A single candidate skips event extraction, queue analysis, recurrence proof, and comparison.
It is realized and lowered once, even when optional timing is unavailable.
@@ -283,14 +331,17 @@ The target supplies model evidence. Spatial applies the 2.1% selection policy ma
Selection does not read JSON diagnostics. Reports serialize the typed results.
Spatial owns candidate generation, legality, placement, and target-neutral comparison.
The PIM adapter owns execution-event extraction, instruction timing, and resource contention.
Pimsim-nn omits `vsoftmax` before fetch, so the PIM queue model assigns it no timed work.
Input materialization, surrounding instructions, transfers, and synchronization retain their costs.
Functional simulation still executes Softmax. Estimated timing and energy exclude Softmax work.
The shared queue engine models controller arrival arbitration and cross-generation dependencies.
The compiler does not execute candidate programs or invoke a simulator.
Both arbitration policies must establish complete-state recurrence within bounded analysis budgets.
Their estimates are sensitivity checks, not formal bounds.
The candidate with the lowest larger estimate must separate from the original schedule.
The candidate with the lowest larger estimate must separate from the initialized schedule.
Comparison uses `[min(ties)/1.021, max(ties)/0.979]`.
Close alternatives retain candidate zero. The 2.1% margin is a policy heuristic.
Close alternatives retain the initialized schedule. The 2.1% margin is a policy heuristic.
Spatial timing predictions have no formal accuracy bound.
The search finds the best distinguishable candidate in its bounded set, without global optimality.
@@ -310,7 +361,7 @@ Code-generation failures also stop compilation when recovery cannot be justified
If every candidate fails, one diagnostic lists all attempted candidates and causes.
`reports/pipeline_selection.json` records Spatial costs, eligibility, selection, and backend attempts.
It also records candidate generation, realization, extraction, expansion, queue, lowering, and finalization times.
It also records search parents, compact task-stage runs, core budgets, recurrence contributions, termination, attempts, queue budget, and phase times.
`--enable-timing` adds per-pass lowering times and IR operation/value counts.
Final instruction generation uses the normal compiler timing report.
Explicit Spatial exports and IR dumps reconstruct pre-lowering artifacts for the selected schedule.
@@ -328,8 +379,19 @@ Optional diagnostics expose resource work, recurrence, and ordered-request finge
Offline Pimsim fast-mode runs validate predictions and emitted programs.
Simulator measurements never enter production selection.
For `C <= 11` candidates, scheduling metadata uses `O(C(T+P))` storage for `T` compute instances and `P` cores.
Placement deduplication costs `O(C²T)` time.
For `C <= 32` candidates, scheduling metadata uses `O(C(T+P))` storage for `T` compute instances and `P` cores.
Placement deduplication costs `O(C²(T+P))` time. The beam retains at most two schedules.
A round streams legal boundary and core moves into a shortlist of at most `2C`.
Each parent builds stage resource and dependency summaries in `O(T+E+P)` time and storage.
Unchanged-stage packing costs use an `O(SP)` cache. Changed task lists are not cached.
Each parent proposes `O(G + S² log P)` group, cut, and core moves.
For `M` proposed assignments, cheap allocation and scoring cost
`O(M (T log T + S P + E + F + S Kpack))`, plus bounded shortlist comparisons,
where `Kpack` is one existing ordered-packing query's cost.
Constructive allocation builds at most `S P` ordered-packing queries per admitted
partition. The graph and weight indices are reused. Search performs at most
128 physical packings; queue costs remain capped at thirty-two.
Recurrence guidance uses the shared bounded maximum-cycle-ratio solver.
Candidate realization and extraction are sequential; complete candidate modules are not retained.
Normal successful compilation performs one candidate-specific backend lowering.
Recovery performs at most `C` lowerings. Retry selection costs `O(C²)` time and `O(C)` metadata.
@@ -354,7 +416,7 @@ proved hardware infeasibility.
Let `T` be tasks, `E` dependencies, `P` cores, `G` groups, `S` stages,
`R` weight references, `W` distinct weights, `C` modeled work, `F` physical
fragment/consumer demands, and bounded frontier size `K = 8`.
fragment/consumer demands, and resource quantization `Q <= 16`.
| Analysis | Time / storage |
|---|---|
@@ -362,8 +424,8 @@ fragment/consumer demands, and bounded frontier size `K = 8`.
| Weight indexing | Up to `O(R W)` equality comparisons |
| Weight lower bounds | `O(R + W)` / `O(W)` bits |
| Constructive best fit | `O(T log T + P R + P W)` / `O(P W)` bits plus `O(T + P)`; bounded retries only on failure |
| Partition DP | Up to `O(S G² ((T + R) log C + W + K³))` plus dependency traversal / `O(S G² + S G K)`; at most five additional physical placements per memory objective |
| Cut memory service | Expected `O(F + G)` time / `O(F + G)` scratch and retained demands |
| Joint initialization DP | `O(G² Q Kpack + S G² Q²)` time / `O(G² Q + S G Q)` storage; `Kpack` is one ordered-pack cost query |
| Neighborhood memory service | Expected `O(T + F)` per partition / `O(T + F)` scratch |
| Topology clustering / cached PEFT distances | `O(P²)` time |
| Concat cost extraction | `O(A D)` for `A` inputs of rank `D`; constant auxiliary space |
| Cached pipeline priorities | `O(T + D)` time / `O(T + G)` space for `D` template-body operations |