[IE] UnrollGroupQuantize: make unrolled slice locations unique per consumer#302
Conversation
…nsumer
GenericUnrollBase::splitValue named each unrolled slice after the value being
split (appendLoc(val.getLoc(), "slice_{idx}")). When one value feeds more than
one unrolled consumer -- e.g. a grouped-INT4 per-group scale that is the
dequantization scale of both the weight and the activation DynamicDequantize --
the low-index slices of that shared value get byte-identical locations across
consumers, and StopLocationVerifierPass aborts with "Found N duplicated names
after full verification".
Derive each slice's location from the consuming op plus an operand tag and chunk
index (takeOpLoc(consumerOp, "{operandTag}_slice_{idx}")) so slices of a shared
value stay unique. The per-chunk reduced FakeQuantize/DynamicDequantize ops keep
their consumer-rooted "slice_{idx}" locations (already unique by construction).
Adds a LIT regression test (unroll_group_quantize_shared_param_locations.mlir)
covering a shared scale feeding two DynamicDequantize consumers.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
|
Follow-up: I filed #303 documenting the next VPUX compiler blocker the same model (Qwen3-0.6B, asymmetric per-group INT4) hits once this PR is applied — a sub-byte (u4) per-group zero-point SEGMENTED slice that |
|
Note: I've closed #303 — it surfaces on per-group asymmetric INT4, which the dev team flagged as unsupported on NPU (openvinotoolkit/openvino#34450). This PR is narrower: it fixes a |
Details:
Problem.
UnrollGroupQuantize(via the sharedGenericUnrollBase::splitValue) names each unrolled slice after the value being split —appendLoc(val.getLoc(), "slice_{idx}"). When a single value feeds more than one unrolled consumer — e.g. a grouped-INT4 per-group scale that is the dequantization scale of both the weightDynamicDequantizeand the activation/matmulDynamicDequantize— the low-index slices of that shared value get byte-identical locations across the two consumers.StopLocationVerifierPassthen aborts compilation:Found N duplicated names after full verification(N = 40 on a Qwen3-0.6B grouped-INT4 attention projection).This is the root cause behind the zero-dim
as_convolutionsymptom previously guarded in #265 / #266: on currentdevelopthe zero-dim shape no longer appears; the failure surfaces here, in a pass emitting non-unique locations — i.e. the "fix it where it appears" case.Fix. Derive each slice's location from the consuming op plus an operand tag and chunk index —
takeOpLoc(consumerOp, "{operandTag}_slice_{idx}")— instead of from the shared value. Slices of a shared value now stay unique because they are rooted at the (distinct) consumers. The per-chunk reduced ops (FakeQuantize / DynamicDequantize) keep their consumer-rootedslice_{idx}locations, already unique by construction. AllsplitValuecall sites are updated to pass the consumer + operand tag.Test. New LIT test
tests/lit/NPU/dialect/IE/passes/unroll_group_quantize_shared_param_locations.mlir: a shared scale feeding twoDynamicDequantizeconsumers; asserts each consumer's slices resolve to a fused location rooted at that consumer + operand tag (so the two consumers'scale_slice_0/input_slice_0are distinct). Pre-fix the slices alias and the test fails.Verification.
vpux-opt --unroll-group-quantize --mlir-print-debuginfo | FileCheckpasses on the new test.StopLocationVerifierPass(Found 40 duplicated names); with it, the compile proceeds past that pass and continues through the pipeline. Confirms the fix resolves a genuine compile blocker on the supported INT4 path, not just the isolated LIT case.Tickets:
AI Assistance:
splitValuerefactor, and the LIT regression test.vpux-opt/FileCheckand an end-to-end NPU compile on an Intel Core Ultra 7 258V (NPU 4000) from a from-source build.