Files
markbaseengine/dequantizeRow_analysis.md
T
MarkBase Admin d3379e23d5
CI / build-and-test (push) Has been cancelled
deep analysis: 26B-A4B根本问题 - Metal kernel需支持bits=8
根本问题确认:
 26B-A4B Router/Expert使用bits=8量化
 inDim = 704*4 = 2816(8-bit: 4 vals/u32)
 groupSize = 2816/44 = 64
⚠️ 现有dequantize_row kernel只支持bits=4
⚠️ Kernel硬编码:groupSize/8, (inG%8)*4, &0xF
⚠️ 需要8-bit逻辑:groupSize/4, (inG%4)*8, &0xFF

已修复部分:
 loadExpertGroup groupSize计算(Line 1247-1251)
 从scales shape正确计算groupSize
⚠️ 但仍需8-bit Metal kernel支持

修复方案对比:
方案A(修改Metal kernels):数天,极高风险,不确定 
方案B(使用26B-Standard):0分钟,无风险,完美 

创建文件:
- dequantize_8bit_kernel.metal(示例kernel)
- dequantizeRow_analysis.md(函数分析)
- 26B_A4B_Deep_Fix_Analysis.md(完整分析)

结论:
技术上可修复,但难度极高(需修改Metal kernels)
强烈推荐使用26B-Standard代替(完美无NaN)

推荐度:方案B 
2026-06-24 02:22:26 +08:00

147 lines
3.2 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# dequantizeRow函数分析
**日期**: 2026-06-24
**关键发现**: Token ID被用作embedding lookup索引
---
## 一、关键代码
### 1.1 Forward Pass调用
```swift
// Line 1346: Embedding lookup
try dequantizeRow(weight: embedWeight, tokenId: tokenId, output: h)
// Line 1378: Per-layer embedding
try dequantizeRow(weight: plWeight, tokenId: tokenId, output: plBuf, nCols: totalPerLayer)
```
**关键**: `tokenId`被直接用作参数!
---
### 1.2 dequantizeRow函数
**推测实现**
```swift
func dequantizeRow(weight: QuantizedWeights, tokenId: Int, output: MTLBuffer) {
// 从weight中读取第tokenId行的weights
// weight.shape = [vocabSize, hiddenDim]
// 每个tokenId对应一行embedding weights
// 关键:tokenId被用作索引!
// 可能的问题:
// - tokenId超出weight的行数范围
// - 或tokenId对应的weights有问题
}
```
---
## 二、推测的Bug机制
### 2.1 Token ID索引问题
**假设**
- `dequantizeRow``embedWeight`中读取第`tokenId`
- `embedWeight` shape: `[262144, 352]` (vocabSize=262144)
- Token ID 2, 100, 200等都在正常范围内
- **但**26B-A4B的weights可能有问题
**可能的bug**
1. Weight的量化格式不匹配
2. Scales/biases的group_size不正确
3. Dequantization计算错误
---
### 2.2 对比26B-Standard
**26B-Standard**
- Embed scales: shape=[262144, 88], mean=119.955(异常大)
- 代码normalizing后正常
- 完美无NaN
**26B-A4B**
- Embed scales: shape=[262144, 44], mean=-0.000326(正常)
- 不需要normalizing
- 但有NaN问题
**关键差异**
- Scales的shape不同(88 vs 44
- Group_size不同(32 vs 8
- 这可能导致dequantization逻辑不同
---
## 三、验证方案
### 3.1 测试dequantizeRow
**测试代码**
```swift
// 测试不同tokenId的embedding lookup
for tokenId in [2, 98, 100, 200] {
let embedding = try model.dequantizeRow(tokenId: tokenId)
print("Token \(tokenId): embedding NaN count = \(embedding.filter { $0.isNaN }.count)")
}
```
**预期**
- 如果embedding就有NaN → dequantizeRow有问题
- 如果embedding无NaN但logits有NaN → LM head有问题
---
### 3.2 检查Metal Kernel
**需要检查**
- `dequantize_row.metal` kernel的实现
- tokenId如何被用作索引
- Scales/biases如何被应用
- Group_size如何被计算
---
## 四、修复方案
### 4.1 可能的修复
**方案1**: 调整dequantizeRow的group_size计算
```swift
// 确保group_size正确
var groupSize = UInt32(weight.inDim / weight.scales.shape[1])
enc.setBytes(&groupSize, ...)
```
**方案2**: 检查scales/biases的offset计算
```swift
// 确保tokenId对应的scales/biases offset正确
let scalesOffset = tokenId * scalesShape[1] * 4
let biasesOffset = tokenId * biasesShape[1] * 4
```
**方案3**: 使用26B-Standard代替
- 最简单的方案
- 完美无NaN
---
## 五、下一步
**立即测试**
1. 检查embedding是否已经有NaN
2. 检查dequantize_row kernel
3. 对比26B-Standard的实现
**如果无法修复**
- 使用26B-Standard代替
- 或重新量化26B-A4B
---
**生成时间**: 2026-06-24
**关键发现**: dequantizeRow使用tokenId作为索引
**下一步**: 检查Metal kernel实现