Skip to content

GatherBlockQuantized default zero_point differs between CPU and CUDA #31692

Description

GatherBlockQuantized default zero_point differs between CPU and CUDA

Describe the issue

com.microsoft::GatherBlockQuantized produces different values on CPU and CUDA when the optional zero_points input is omitted.

For GGUF Q4_0 data the correct dequantization convention is (q - 8) * scale. ORT CPU appears to use an implicit zero point of 8, while ORT CUDA appears to use an implicit zero point of 0. This silently corrupts quantized embedding rows on CUDA whenever a converter relies on the default.

A downstream mobius conversion bug exposed this on large Q4_0 LLMs: every token embedding was offset by 8 * scale on CUDA. Adding an explicit packed zero point initializer of 0x88 fixed CUDA output without changing anything else.

Minimal reproducer shape

A single-node graph is enough:

  • op: com.microsoft::GatherBlockQuantized
  • inputs: qweight, indices, scales
  • omit optional zero_points
  • attrs: bits=4, block_size=32, gather_axis=0, quantize_axis=1
  • qweight: rows filled with nibble value 10 (0xAA bytes)
  • scales: e.g. [[0.5], [0.25]]
  • indices: [0, 1]

Expected under Q4_0-style dequantization with default zp 8:

  • row 0: (10 - 8) * 0.5 = 1.0
  • row 1: (10 - 8) * 0.25 = 0.5

Observed behavior from the downstream investigation:

  • CPU matches (q - 8) * scale
  • CUDA matches q * scale

Why this matters

The CPU/CUDA default mismatch makes model correctness depend on execution provider. In the downstream model, ORT CPU generated correct text, while ORT CUDA and native CUDA generated deterministic garbage until explicit zero points were added.

MatMulNBits was tested separately with the same model weights and CPU/CUDA agreed to fp16 rounding, so this report is specifically about GatherBlockQuantized's omitted zero_points default.

Downstream references

Request

Please make the GatherBlockQuantized default zero point consistent across CPU and CUDA, or document that converters must always provide zero_points because the default is not portable.

Metadata

Metadata

Labels

No labels
No labels

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions