🐬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。
notion image
notion image
notion image

代码注释

对应代码实际计算流程:
notion image

参数设置:

对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
notion image
💡
由于 都是多头共享的,因此 也是多头共享的

矩阵吸收?

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

  吸收前后对比

notion image
基于上述公式,逻辑上可以把中间两个参数矩阵的乘法放到离线去做,但是仔细研究下会发现,这样既不会省显存,也不会省计算。 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 

  1. 一个linear算出所有专家的分数
  1. 将专家分成8组,对于组内,将最高的两个份数相加,得到这个组的份数
  1. 选出最高的4个组
  1. 对这4个组内的所有专家分数,做sigmoid
  1. 选出最高的8个专家

参数矩阵大小

weight: 256 * 7168 bias: 256

Moe

  1. 用Gate选出8个专家(最多分布在4个节点),如果其中有在本机的,就是进行计算。
  1. 进行all_reducea,源码中,永远都是所有的机器都会参与,无论上面是否有被激活的专家。
  1. 最后加上共享专家的输出

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...