根本问题确认: ✅ 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 ⭐⭐⭐⭐⭐
This commit is contained in:
@@ -0,0 +1,146 @@
|
||||
# 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实现
|
||||
Reference in New Issue
Block a user