You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
[CPU EP] MatMulNBits (accuracy_level=4) produces wrong results on x86-64 AVX2 when loaded from session.save_external_prepacked_constant_initializers output (1.31.1) #33677
We save an optimized model with prepacked constant initializers and load that saved model later
(the documented "save prepacked weights" flow) to memory-map the packed weights. On x86-64 with AVX2
(no AVX-512) and onnxruntime 1.31.1, graphs containing MatMulNBits (int4, block-wise, accuracy_level=4)
compute wrong values after reload. In our autoregressive TTS model the stop token is never emitted, so
generation runs to the 250-frame cap on every input.
Observations (same model, same inputs, Linux x86-64 GitHub runner, CPU flags avx avx2 f16c fma):
Variant
Frames generated (seed 1 / 2)
Expected
fp32 reference
27 / 32
stops
int4 MatMulNBits acc4, loaded from prepacked save
250 / 250
does not stop
same int4 graphs, not prepacked (ORT packs in memory)
23 / 27
stops
same int4 graphs with accuracy_level=0, prepacked
26 / 26
stops
int8 MatMulInteger graphs only, prepacked
30 / 31
stops
onnxruntime 1.23.2 (does not write int4 prepacked blobs)
26 / 28
stops
Same on windows-latest x86-64 (AMD Family 25, onnxruntime 1.31.1).
arm64 (macOS, Linux aarch64) with the same flow is correct; audio is bit-identical to the unpacked model.
Under Rosetta (no AVX exposed) onnxruntime 1.31.1 does not write int4 prepacked blobs and the issue does not appear.
A single-node probe (one MatMulNBits node, M=1) compares equal between prepacked and unpacked loads, so the
mismatch seems to need M>1 or appear only after graph fusions.
To reproduce
Save step (Python):
so=ort.SessionOptions()
so.graph_optimization_level=ort.GraphOptimizationLevel.ORT_ENABLE_ALLso.intra_op_num_threads=1so.add_session_config_entry("session.save_external_prepacked_constant_initializers", "1")
so.add_session_config_entry("session.optimized_model_external_initializers_file_name", "model.packed.data")
so.add_session_config_entry("session.optimized_model_external_initializers_min_size_in_bytes", "1024")
so.optimized_model_filepath="model.packed.onnx"ort.InferenceSession("model.onnx", so, providers=["CPUExecutionProvider"])
Then load model.packed.onnx in a new session and compare its outputs with model.onnx. A self-contained
model is not attached yet (see note above); the failing graphs are a text encoder and an autoregressive
prefix step quantized with MatMulNBits (bits=4, block_size=32, symmetric, accuracy_level=4).
Urgency
Workaround in place: we skip prepacking for graphs with MatMulNBits on x86-64, at the cost of about
100 MB more private memory per process.
Platform / versions
Linux (ubuntu-latest) and Windows (windows-latest), x86-64 AVX2; onnxruntime 1.31.1 from PyPI, Python 3.12, CPUExecutionProvider.
Activity