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 |
+31 -2
View File
@@ -33,13 +33,29 @@ per-inference measurements become `NA` in aggregates, not zero. With zero
completed outputs, interval, throughput, and energy per inference are unavailable;
measured average chip power can still be reported. Functional status is retained.
Floating-point correctness requires both elementwise absolute/relative tolerance
and a relative L2 limit for each nonzero reference output. The L2 limit prevents
small reference outputs from accepting all-zero results under the absolute floor.
It cannot substitute for the elementwise check. Zero references use the absolute
check; integer outputs require exact agreement. Nonfinite outputs are rejected.
Validation reports record both maximum absolute and relative L2 errors.
Report reuse includes the validation-policy identity.
Removing normalization operations can amplify floating-point sensitivity and
change the computation. Such variants must use their own native reference.
Agreement in a global norm alone does not establish elementwise correctness.
Independent reference implementations and higher-precision calculations can
help diagnose rounding sensitivity without relaxing the recorded pass criteria.
Ablation percentages require positive finite values for both the variant and
its matching baseline. Tiny positive measurements retain significant digits
instead of being rounded to zero in the comparison CSV. An extreme valid
decrease can round to `-100.00%`; that value alone is not evidence of failure.
Reciprocal output interval and throughput cannot both have that decrease.
The ablation plotter warns and displays `N/A` for such invalid paired percentages,
while leaving the CSV and functional status unchanged.
The ablation report uses each disabled feature as its comparison baseline.
Planning gain uses `no-plan`; throughput synchronization gain uses `no-sync`.
Throughput gain measures the relative increase. Latency, power, and energy gains
measure relative reductions. Both programs' functional statuses remain separate.
## Report reuse and implementation revisions
@@ -58,6 +74,12 @@ Metrics come from Pimsim's
[`Chip::getSimulationReport`](../../backend-simulators/pim/pimsim-nn/src/chip/Chip.cpp)
and [`EnergyCounter`](../../backend-simulators/pim/pimsim-nn/src/utils/EnergyCounter.cpp).
Pimsim-nn omits `vsoftmax` before instruction fetch. Reported performance and
energy exclude its work. The PIM queue estimator uses the same omission.
Functional validation executes Softmax and compares the same full model with
its native reference. This timing approximation does not establish hardware
support for Softmax or include its execution energy.
- Latency mode measures time to complete one inference.
- Throughput-mode latency is measurement duration / completed iterations,
equal to `1000 / throughput` before rounding. It is not end-to-end pipelined
@@ -67,9 +89,16 @@ and [`EnergyCounter`](../../backend-simulators/pim/pimsim-nn/src/utils/EnergyCou
mode). Plots convert pJ to mJ with `1e-9`; no pipeline-depth or batch-size
division is applied.
Existing `average_energy_pj`, `raptor_energy_pj`, and validation CSV energy
columns retain their names for compatibility. They contain energy per inference.
Fast mode measures throughput over the last two convergence windows but power
and energy over the entire run up to early stop. Energy includes startup and
work in flight, so it need not equal average power / reported throughput.
If convergence fails, comparison and ablation reports retain the simulator's
full-duration fallback throughput. This measurement includes transient execution.
It does not establish steady-state convergence. The per-case JSON records its
measurement type and convergence status. Missing or invalid measurements remain `NA`.
Use `--no-fast` for full-duration measurements. Consult the
[correctness notes](../../validation/tools/pim/pimcomp/correctness/README.md) before interpreting failed rows
as performance comparisons.
+7 -4
View File
@@ -43,10 +43,13 @@ shows why a fusion label is not proof of numeric equivalence.
Pimsim accepts ISA instructions rather than ONNX operators. Its
[instruction decoder](../../backend-simulators/pim/pimsim-nn/src/isa/Instruction.cpp)
rejects `vsoftmax` (opcode 21) and unknown opcodes; unsupported operations must
not be approximated in the oracle. This is why the dedicated GoogLeNet artifact
removes LRN/Softmax and the YOLO artifact removes Softmax. YOLO retains its other
operations, including MatMul/Transpose and detection decoding, for Raptor.
omits `vsoftmax` (binary opcode 21) before fetch and warns once per process
because it has no timing model. Other unknown opcodes remain errors.
Reported timing and energy exclude Softmax work. Functional validation still
executes Softmax. The comparison uses full YOLO and GoogLeNet with only its two
LRN nodes bypassed. VGG8 and both ResNet graphs retain all operators.
The historical `*-pimsim-nn.onnx` files retain the earlier Softmax-free graphs
for result reproduction; they are no longer the suite's selected inputs.
## Standalone frontend/backend reproduction