🐬DeepSeek-v3 模型笔记
type
status
date
slug
summary
tags
category
icon
password
AI summary
参数量总揽
671B_config.json
一个MLA:187105280
一个layer的moe experts: 44040192 * (256+1) = 11318329344
一个router: 7168 * 256 = 1835008
一个dense layer MLP: 7168 * 18432 * 3 = 396361728
一个moe layer = mla + router + moe = 11507269632
一个dense layer = mla + mlp = 583467008
Embedding: 926679040
outpu linear: vocab_size * hidden_size = 129280 * 7168 = 926679040
total = moe_layer * 58 + dense_layer * 3 + embeeding + output_linear = 671,025,397,760
总mla: mla * 61 = 11413422080 (1.7%)
总moe: moe * 58 = 656463101952 (97.8%)
可见experts的参数占据量整个模型的量绝大多数。
MLA
相关MLA建议阅读文章
简述
先通过一个下投影矩阵将输入下投影到一个维度更小的latent向量,并加到cache, 然后每个head各自再用两个上投影矩阵,把latent向量分别上投影为k,v向量。 所有头共享一个laten向量,但是有独自的k,v向量,因此总共有1个下投影矩阵,n_heads*2个上投影矩阵。
q也做了一样的操作,先下投影,再上投影。
为解决rope不兼容,额外为q/k,添加一部分维度(64),这部分与传统做法一致,先投影到q/k,然后添加rope信息。最后将带rope和不带rope的q/k进行concat,作为最终的q/k。



代码注释
对应代码实际计算流程:

参数设置:
对deepseek v3中MLA的详细分析(对比MHA的计算量、缓存量、参数量)
用config_671B.json的配置:
dim: 7168,
n_layers: 61,
n_heads: 128,
q_lora_rank: 1536,
kv_lora_rank: 512,
qk_nope_head_dim: 128,
qk_rope_head_dim: 64,
v_head_dim: 128,
参数矩阵大小:
以671B为例。
w_dq = dim * q_lora_rank = 7168 * 1536 = 11,010,048
w_uq = q_lora_rank * n_heads * qk_nope_head_dim = 1536 * 128 * 128 = 25,165,824
w_qr = q_lora_rank * n_heads * qk_rope_head_dim = 1536 * 128 * 64 = 12,582,912
w_dkv = dim * kv_lora_rank = 7168 * 512 = 3,670,016
w_uk = kv_lora_rank * n_heads * v_head_dim = 512 * 128 * 128 = 8,388,608
w_kr = dim * qk_rope_head_dim = 7168 * 64 = 458,752
w_uv = kv_lora_rank * n_heads * v_head_dim = 512 * 128 * 128 = 8,388,608
w_o = n_heads * v_head_dim * dim = 128 * 128 * 7168 = 117,440,512
total = 187,105,280

由于 都是多头共享的,因此 和 也是多头共享的
矩阵吸收?

论文中说,可以把 吸收成一个矩阵,把 吸收成一个矩阵,就不需要把cache的 重计算为k,v了。

由于矩阵乘法的结合律,可以先计算 。
但是从上面的代码可以发现,实际并没有做这样的吸收。而是按照上面的两个式子,从左至右依次计算,倒是也没有将k,v显式地compute出来。
实际上,如果按照论文的思路,先进行吸收的化,无论新矩阵的大小,还是吸收后需要的计算量,都是增加了的,可能这也是章老师实验测试发现性能反而下降的原因。
吸收前后对比

基于上述公式,逻辑上可以把中间两个参数矩阵的乘法放到离线去做,但是仔细研究下会发现,这样既不会省显存,也不会省计算。
deepseek v3代码采用的是,online从左至右依次计算
下面是如果将两个参数矩阵进行融合,前后对比。
参数量
融合前:
w_uq + w_kr = 25,165,824 + 8,388,608 = 33,554,432
融合后:
w_absorbed = q_lora_rank * kv_lora_rank * n_heads = 1536 * 512 * 128 = 100,663,296
融合后,大约大了三倍
单token计算量
融合前:
c_before = w_uq + w_uk + qk_nope_head_dim * n_heads = 33,619,968
融合后:
c_after = w_absorbed + kv_lora_rank * n_heads = 100,728,832
计算量也大了三倍
MOE
Gate
- 一个linear算出所有专家的分数
- 将专家分成8组,对于组内,将最高的两个份数相加,得到这个组的份数
- 选出最高的4个组
- 对这4个组内的所有专家分数,做sigmoid
- 选出最高的8个专家
参数矩阵大小
weight: 256 * 7168
bias: 256
Moe
- 用Gate选出8个专家(最多分布在4个节点),如果其中有在本机的,就是进行计算。
- 进行all_reducea,源码中,永远都是所有的机器都会参与,无论上面是否有被激活的专家。
- 最后加上共享专家的输出
MLP(Expert)
参数矩阵大小
单个expert
w1: 7168 * 2408 = 14680064
w3: 7168 * 2408 = 14680064
w3: 2408 * 7168 = 14680064
total : 14680064 * 3 = 44040192
Prev
DeepSeek-v3 Infra笔记
Next
体系结构 ETH 2024笔记
Loading...