UB in to_float callback for I2_S (missing scale param) + 3 more bugs on ARM Ampere Altra
Nessuno ha ancora preso questa issue.
Valutazione
- Difficoltà
- 5/5
- Tempo stimato
- Più di una settimana
- Idoneità per principianti
- 20/100
- Tipo di issue
- Bug
- Chiarezza
- Da chiarire
- Stato di attività
- Ferma
- Stack tecnologico
- cmake, cpp
- Ambito
- build-system, machine-learning, performance
Direzione di ricerca
Inizia riproducendo i risultati ARM con i comandi e i build flags indicati nell’issue, quindi esamina 3rdparty/llama.cpp/ggml/src/ggml.c, CMakeLists.txt e il percorso ARM di ggml-bitnet-mad.cpp. Confronta il percorso gemv di -b 1 con il percorso gemm di -b 32, incluso il callback I2_S e la configurazione dotprod. Il lavoro è completato quando vengono identificati e corretti i problemi di correttezza ARM rimanenti e viene confermato un output coerente.
Scritto dal modello di indicizzazione a partire dal testo della issue.
Descrizione
Environment
- Platform: Oracle Cloud Compute A1 Flex (Ampere Altra, armv8.2-a,
asimddppresent in/proc/cpuinfo) - OS: Ubuntu 22.04 LTS
- Compiler: clang 14.0
- Commit: main branch, March 2026
- Build flags:
-DBITNET_ARM_TL1=ON -DCMAKE_C_COMPILER=clang -DCMAKE_CXX_COMPILER=clang++ -DCMAKE_C_FLAGS="-march=armv8.2-a+fp16+dotprod" - Model:
microsoft/BitNet-b1.58-2B-4T-gguf(ggml-model-i2_s.gguf, 1.2GB) - Python: 3.12 (venv)
System info (from llama-cli output)
NEON = 1 | ARM_FMA = 1 | SVE = 0 | MATMUL_INT8 = 0 | (all x86 = 0)
Problem
With -b 1 (gemv path): model produces real words but completely incoherent output.
With -b 32+ (gemm path for prompt): model produces GGGG garbage for all generated tokens.
# gemv path (-b 1, default in run_inference.py)
$ python run_inference.py -m models/BitNet-b1.58-2B-4T-gguf/ggml-model-i2_s.gguf \
-p "The capital of France is" -n 30 -t 4
The capital of France is offline officially.ai happy collective lower sl ruled m unit proven-for...
# gemm path (-b 32)
$ ./build/bin/llama-cli -m models/BitNet-b1.58-2B-4T-gguf/ggml-model-i2_s.gguf \
-p "Hello, my name is" -n 50 -t 4 -b 32
Hello, my name isGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGG
Speed is correct (~18 tok/s on 4 ARM cores), model loads without errors.
Bug 1: to_float callback — type mismatch (confirmed, patched)
In 3rdparty/llama.cpp/ggml/src/ggml.c, the type table for GGML_TYPE_I2_S registers dequantize_row_i2_s as a ggml_to_float_t callback, but the signatures do not match:
// Typedef (3 params):
typedef void (*ggml_to_float_t)(const void * x, float * y, int64_t n);
// Actual function (4 params — 4th is the i2 scale):
void dequantize_row_i2_s(const uint8_t * x, float * y, int64_t n, const float i2_scale);
// Bug in type table (ggml.c ~line 1185):
.to_float = (ggml_to_float_t) dequantize_row_i2_s, // scale never passed → UB
The cast silences the compiler but causes undefined behavior — on ARM, the 4th argument register is garbage → i2_scale is random → dequantized weights are garbage.
Applied fix — wrapper in the same translation unit:
// At top of ggml.c:
static void dequantize_row_i2_s_wrapper(const void * vx, float * y, int64_t n) {
const uint8_t * x = (const uint8_t *) vx;
const float i2_scale = ((const float *)(x + (n / 4)))[0];
dequantize_row_i2_s(x, y, n, i2_scale);
}
// In type table:
.to_float = dequantize_row_i2_s_wrapper,
Effect: without this fix → GGGG for all configs. With fix → real words with -b 1 (but still incoherent, see Bug 3).
Bug 2: +dotprod not enabled in CMakeLists for ARM (build issue)
The build system generates -march=armv8.2-a without +dotprod. On ARM Ampere Altra:
- CPU has
asimddp(dotprod SDOT/UDOT) in/proc/cpuinfo - Without
+dotprod,__ARM_FEATURE_DOTPRODis not defined by clang ggml-bitnet-mad.cppfalls to the#elsepath usingvmlal_s8(int16 accumulator)- For vectors of 2560+ elements, int16 accumulator overflows → incorrect results (related to #411)
Verification:
clang -march=armv8.2-a+fp16+dotprod -dM -E - < /dev/null | grep DOTPROD
# → #define __ARM_FEATURE_DOTPROD 1
clang -march=armv8.2-a+fp16 -dM -E - < /dev/null | grep DOTPROD
# → (nothing)
Suggested fix: add +dotprod to CMakeLists.txt for AArch64 targets when CPU supports it, or document it as a required flag.
Bug 3: gemm path (ne11 > 3) produces GGGG on ARM — root cause unknown
When the batch has more than 3 tokens (prompt evaluation with -b 32), the code takes the ggml_gemm_i2_i8_s path instead of ggml_gemv_i2_i8_s. On ARM, this path produces completely wrong output:
# Relevant code path in ggml.c (~line 13268):
if (gemm && (ne11 > 3)) {
if (src0->type == GGML_TYPE_I2_S) {
// gemm path — produces GGGG on ARM
const float * scale = (float *)((uint8_t*)(src0->data) + (ne00 * ne01 / 4));
gemm(...);
for (...) {
tmp[...] = (tmp[...] - act_sums[col]) / (act_scales[col]) * (*scale);
}
}
}
Since prompt tokens are processed via gemm and corrupt the KV cache, all subsequent generated tokens are also garbage.
Workaround: use -b 1 to force all computation through the gemv path (avoids the bug but is slower and still produces incoherent text).
Bug 4: incoherent output even with gemv path (remaining issue)
Even with -b 1 + Bug 1 fix + dotprod enabled, output is semantically incoherent. The model generates real vocabulary tokens but with no semantic coherence:
"The capital of France is offline officially.ai happy collective..."
"Hello, my name is Freedom reduce Dispatch linear Dahl tent corps..."
This persists even with temperature=0 (greedy decoding), suggesting the issue is in the logit distribution rather than sampling. Possible causes:
act_sums(activation zero-point correction) computed incorrectly for ARM- Scale offset wrong for GQA tensors (K/V: [2560, 640] with 5 KV heads vs Q: [2560, 2560])
- Activation quantization (
quantize_row_i8_s) producing incorrect scale values
Steps to reproduce
# 1. Clone and build (Ubuntu 22.04, ARM Ampere)
git clone https://github.com/microsoft/BitNet.git && cd BitNet
git submodule update --init --depth=1
python3 -m venv .venv && source .venv/bin/activate && pip install -r requirements.txt
# 2. Build (add +dotprod — not in default CMakeLists)
cmake -S . -B build \
-DBITNET_ARM_TL1=ON \
-DCMAKE_C_COMPILER=clang \
-DCMAKE_CXX_COMPILER=clang++ \
-DCMAKE_C_FLAGS="-march=armv8.2-a+fp16+dotprod" \
-DCMAKE_CXX_FLAGS="-march=armv8.2-a+fp16+dotprod" \
-DCMAKE_BUILD_TYPE=Release
make -C build -j4
# 3. Download model
huggingface-cli download microsoft/BitNet-b1.58-2B-4T-gguf \
--local-dir models/BitNet-b1.58-2B-4T-gguf
# 4. Test (without Bug 1 fix — GGGG for all batch sizes)
python run_inference.py -m models/BitNet-b1.58-2B-4T-gguf/ggml-model-i2_s.gguf \
-p "The capital of France is" -n 30
# 5. Apply Bug 1 fix to 3rdparty/llama.cpp/ggml/src/ggml.c (see above)
# Rebuild and test — now produces words with -b 1 but still incoherent
Related issues
- #411 — int16 overflow in NEON 1x1 kernel (same root area, different manifestation)
- #195 — ARM inference issues (similar platform)
Hardware confirmation
Tested exclusively on Oracle Cloud Compute A1 Flex (ARM Ampere Altra).
Reports from Reddit/r/LocalLLaMA indicate M1/M2/M3 Mac users achieve coherent output — suggesting the issue may be ARM Ampere-specific or related to the dotprod/vmlal path difference.
- Lingua principale
- C++
- Stelle
- 40.3k
- Fork
- 3.7k
- Metriche di merge delle PR
- Nessuna PR unita negli ultimi 30g
Preparare l'ambiente
Questo progetto non fornisce container di sviluppo, Dockerfile né guida per i contributori, quindi l'ambiente è a tuo carico: parti dal suo README e consulta la nostra guida al primo contributo per i passaggi generali.
Come iniziare
- Leggi tutta la issue e poi la guida ai contributi del progetto.
- Commenta sulla issue per dire che te ne occupi tu — evita che due persone facciano lo stesso lavoro.
- Fai un fork del repository e lavora su un branch.
- Apri una pull request che faccia riferimento al numero della issue.
Altre issue di microsoft/BitNet
-
Difficoltà 2/5 1-3 ore Idoneità per principianti 86/100
-
i2_s SIGSEGVs at n_ubatch >= 32: BLAS backend dequantises by a row stride 4x the real packed rowAperta
Difficoltà 2/5 1-3 ore Idoneità per principianti 76/100
-
Difficoltà 2/5 1-3 ore Idoneità per principianti 86/100
-
Difficoltà 1/5 Meno di un'ora Idoneità per principianti 92/100
-
Difficoltà 2/5 1-3 ore Idoneità per principianti 76/100
Tutte le issue di microsoft/BitNet
Issue simili
-
Unconfirmed bug
Difficoltà 1/5 Meno di un'ora Idoneità per principianti 88/100
luanti-org/luanti#17605 · 1 commento ·
I maintainer di solito rispondono entro 2 giorni
-
area: config area: firmware priority: P2 - medium size: S type: bug
Difficoltà 2/5 1-3 ore Idoneità per principianti 76/100
Mizithra/ActiveTerrain#16 ·
-
Difficoltà 2/5 1-3 ore Idoneità per principianti 84/100
grumpycoders/pcsx-redux#2171 ·
I maintainer di solito rispondono entro 1 giorno
-
Difficoltà 2/5 1-3 ore Idoneità per principianti 70/100
I maintainer di solito rispondono entro 1 giorno
-
Difficoltà 2/5 1-3 ore Idoneità per principianti 88/100
bytedance/trae-agent#524 · 1 commento ·
I maintainer di solito rispondono entro 1 giorno