LLM 大语言模型显存消耗估计与计算
1. LLM 大语言模型开发流程
在大模型(如 LLaMA-7B、GPT-3 等)的开发、训练、微调、推理和部署过程中,各个阶段的流程都涉及多个复杂的步骤。以下是详细的流程描述,涵盖训练和微调的区别,以及训练、推理和部署的具体过程。
1.1 预训练(Pre-training)
目标:使用大规模的数据集训练模型,使其能够理解和生成自然语言。
流程:
-
数据准备:
- 收集大规模文本数据(如维基百科、新闻、书籍等)。
- 数据清洗和预处理,包括分词、去除停用词等。
-
模型定义:
- 选择模型架构(如 Transformer)。
- 定义模型的层数、隐藏单元数、注意力头数等超参数。
-
训练过程:
- 初始化:随机初始化模型权重。
- 前向传播:计算每个输入的输出。
- 计算损失:使用目标数据计算模型的损失(如交叉熵损失)。
- 反向传播:计算梯度并更新模型权重。
- 优化:使用优化器(如 Adam、AdamW)调整学习率和其他超参数。
-
评估:
- 使用验证集评估模型的性能(如准确率、损失值)。
-
保存模型:
- 保存训练后的模型权重和配置,以便后续使用或微调。
1.2 微调(Fine-tuning)
目标:在特定任务或数据集上对预训练模型进行调整,以提高任务性能。
流程:
-
准备特定任务的数据集:
- 收集并处理特定任务的数据集(如文本分类、问答等)。
-
加载预训练模型:
- 从预训练模型中加载权重。
-
任务适配:
- 修改模型架构(如添加分类层)以适应特定任务。
-
微调过程:
- 前向传播:在特定任务数据上计算输出。
- 计算损失:使用特定任务的标签计算损失。
- 反向传播:计算梯度并更新模型权重。
- 优化:调整学习率和其他超参数。
-
评估:
- 在验证集上评估模型的性能。
-
保存微调后的模型:
- 保存微调后的模型权重和配置,以便部署或进一步优化。
1.3 推理(Inference)
目标:使用训练好的模型进行实际应用(如文本生成、翻译等)。
流程:
-
加载模型:
- 从磁盘加载预训练或微调后的模型权重。
-
预处理输入:
- 对输入数据进行预处理(如分词、编码)。
-
前向传播:
- 使用模型计算输入数据的输出。
-
后处理:
- 对模型输出进行解码和后处理(如将生成的文本转换为可读的形式)。
-
输出结果:
- 返回或展示模型的输出结果。
1.4 部署(Deployment)
目标:将模型部署到生产环境中,使其能够为用户提供服务。
流程:
-
环境准备:
- 配置运行环境(如服务器、云平台)。
- 安装必要的软件和库。
-
模型导出:
- 导出模型为适合部署的格式(如 ONNX、TensorFlow SavedModel)。
-
创建服务:
- 构建 API 或用户接口来与模型进行交互(如 REST API、gRPC)。
-
集成:
- 将模型集成到应用程序或服务中。
-
监控和维护:
- 监控模型的性能和响应时间。
- 定期维护和更新模型,处理任何出现的问题。
-
优化:
- 进行模型压缩(如量化、剪枝)以减少部署成本。
- 使用缓存和负载均衡来提高服务的可扩展性。
2. 模型GPU显存占用(accelerate 工具)
2.1 开发环境
- Transformers 4.38.1
- Accelerate 0.27.2
2.2 使用方法
这个工具 accelerate estimate-memory 是 huggingface 的 accelerate 开发库中提供的一个工具。使用这个工具,并不会真正的下载或者加载模型到内存中,它只是根据meta数据来对大模型所需要的内存进行模拟计算。所以,运行此工具并不需要您有GPU机器。
2.2.1 网页在线访问
截止 2024/7/23 (无法打开)
https://huggingface.co/spaces/hf-accelerate/model-memory-usage
2.2.2 本地运行
- 安装 accelerate, transformers
pip install accelerate
pip install transformers
- 使用方法举例
# 基本使用方法
accelerate estimate-memory mistralai/Mistral-7B-v0.1
accelerate estimate-memory meta-llama/Llama-2-13b-hf# 只显示指定的数据类型
accelerate estimate-memory mistralai/Mistral-7B-v0.1 --dtypes float16# 指定开发库(针对本地模型,Hub上存储的模型不需要指定)
accelerate estimate-memory mistralai/Mistral-7B-v0.1 --dtypes float32 float16 --library_name transformers# 设置 trust_remote_code=True
accelerate estimate-memory Qwen/Qwen1.5-7B #正常
accelerate estimate-memory Qwen/Qwen-7B #报错
accelerate estimate-memory Qwen/Qwen-7B --trust_remote_code #可以运行# 其他模型
accelerate estimate-memory google/gemma-7b
accelerate estimate-memory baichuan-inc/Baichuan2-7B-Base --trust_remote_code
2.3 实验结果
2.3.1 meta-llama/Llama-2-7b-hf
accelerate estimate-memory meta-llama/Llama-2-7b-hf
┌──────────────────────────────────────────────────────────┐
│ Memory Usage for loading `meta-llama/Llama-2-7b-hf` │
├───────┬─────────────┬──────────┬─────────────────────────┤
│ dtype │Largest Layer│Total Size│ Training using Adam │
├───────┼─────────────┼──────────┼─────────────────────────┤
│float32│ 776.03 MB │ 24.74 GB │ 98.96 GB │
│float16│ 388.02 MB │ 12.37 GB │ 49.48 GB │
│ int8 │ 194.01 MB │ 6.18 GB │ N/A │
│ int4 │ 97.0 MB │ 3.09 GB │ N/A │
└───────┴─────────────┴──────────┴─────────────────────────┘
2.3.2 手动测试代码
测试使用的代码:
代码使用mistralai/Mistral-7B-Instruct-v0.2模型,原教程直接复制过来,未修改,如需需要自己修改
from transformers import AutoModelForCausalLM, AutoTokenizer
import torch, pdbmodel = AutoModelForCausalLM.from_pretrained("mistralai/Mistral-7B-Instruct-v0.2", torch_dtype=torch.float32, device_map="auto")
#model = AutoModelForCausalLM.from_pretrained("mistralai/Mistral-7B-Instruct-v0.2", torch_dtype=torch.float16, device_map="auto")
#model = AutoModelForCausalLM.from_pretrained("mistralai/Mistral-7B-Instruct-v0.2", load_in_8bit=True, device_map="auto")
#model = AutoModelForCausalLM.from_pretrained("mistralai/Mistral-7B-Instruct-v0.2", load_in_4bit=True, device_map="auto")tokenizer = AutoTokenizer.from_pretrained("mistralai/Mistral-7B-Instruct-v0.2")
#pdb.set_trace()input_text = "Write me a poem about Machine Learning."
input_ids = tokenizer(input_text, return_tensors="pt").to("cuda")outputs = model.generate(**input_ids, max_new_tokens=1000)
print(tokenizer.decode(outputs[0]))
2.4 总结
这个工具的计算的结果,针对代码加入到Transformers中的模型,计算结果有参考价值。
针对本地模型,计算可能会不准确。
作为总结,可以试着回答下面的问题:
- 这个工具可以做什么? 如何使用?
- 此工具如何设置
trust_remote_code=True
? 什么情况下需要设置?
处理来自第三方的自定义配置 - Timm是什么?: https://huggingface.co/timm
是huggingface的开发库,主要面向图像处理模型 - 此工具的计算值与实际运行时的差异有多大? 造成差异的原因有那些?
3. 模型GPU显存占用(手动计算—推理过程)
前提条件: 模型参数量为 $ \Phi$
推理过程
推理过程包括模型的一次前向传播,显存主要存储模型的参数。当模型通过 Float 16 数据类型存储时,每个元素占据 2 个 bytes,因此显存占用量为 2 Φ 2\Phi 2Φ。当模型通过 Float 32 数据类型存储时,每个元素占据 4 个 bytes,因此显存占用量为 4 Φ 4\Phi 4Φ。
例子
以 ChatGLM-6B 为例,FP16 存储时 (6*2=12G):
量化等级 | 最低 GPU 显存(推理) |
---|---|
FP16(无量化) | 13 GB |
INT8 | 8 GB |
INT4 | 6 GB |
总结
推理过程中,模型参数的存储占据显存的主要部分。不同的数据类型(FP16、INT8、INT4)对显存的需求不同,选择适当的量化等级可以有效地减少显存占用。
4. 模型GPU显存占用(手动计算—训练过程)
模型训练过程中,显存占用主要包括下面四个部分:
- 模型参数
- 模型梯度
- 优化器状态
- 中间激活值
4.1 基础知识
- 1GB = 1024 MB
- 1MB = 1024KB
- 1KB = 1024B
- 1B = 8bit
- FP32 32bit 单精度 4B
- FP16 16bit 半精度 2B
4.2 模型参数
4.2.1 前置说明:
符号说明
-
n layer n_{\text{layer}} nlayer: 模型层数;
-
d model d_{\text{model}} dmodel: 模型残差输出维度大小;
-
d ff d_{\text{ff}} dff: 前馈神经网络输出维度大小;
-
d attn d_{\text{attn}} dattn: 注意力网络输出维度大小;
-
n heads n_{\text{heads}} nheads: 每一层的多头注意力的数量;
-
n ctx n_{\text{ctx}} nctx: 输入的上下文长度大小;
前置知识
-
参数量定义:
参数量是指神经网络或机器学习模型中可以进行学习和调整的参数的数量。包括权重(weights)和偏量(biases),它们在训练过程中不断地更新以优化模型的性能。 -
FLOPS定义:
FLOPS(floating point operations)表示浮点数运算次数,衡量计算量的大小。 -
如何计算矩阵乘法的FLOPs:
- 对于 A ∈ R l × n , B ∈ R n × k A \in \mathbb{R}^{l \times n}, B \in \mathbb{R}^{n \times k} A∈Rl×n,B∈Rn×k,计算 A B AB AB需要进行 n n n次乘法运算和 n n n次加法运算,共计 2 n k 2nk 2nk次浮点数运算,需 2 n k 2nk 2nk次FLOPs。
- 对于 A ∈ R m × n , B ∈ R n × p A \in \mathbb{R}^{m \times n}, B \in \mathbb{R}^{n \times p} A∈Rm×n,B∈Rn×p,计算 A B AB AB需要的浮点数运算次数为 2 m n p 2mnp 2mnp。
4.2.2 Transformer各层参数及计算量如下表所示
Operation | Parameters | FLOPs per Token |
---|---|---|
Embed | ( n vocab + n ctx ) d model (n_{\text{vocab}} + n_{\text{ctx}}) d_{\text{model}} (nvocab+nctx)dmodel | 4 d model 4d_{\text{model}} 4dmodel |
Attention: QKV | n layer d model 3 d attn n_{\text{layer}} d_{\text{model}} 3d_{\text{attn}} nlayerdmodel3dattn | 2 n layer d model 3 d attn 2n_{\text{layer}} d_{\text{model}} 3d_{\text{attn}} 2nlayerdmodel3dattn |
Attention: Mask | - | 2 n layer n ctx d attn 2n_{\text{layer}} n_{\text{ctx}} d_{\text{attn}} 2nlayernctxdattn |
Attention: Project | n layer d attn d model n_{\text{layer}} d_{\text{attn}} d_{\text{model}} nlayerdattndmodel | 2 n layer d attn d embd 2n_{\text{layer}} d_{\text{attn}} d_{\text{embd}} 2nlayerdattndembd |
Feedforward | n layer 2 d model d ff n_{\text{layer}} 2d_{\text{model}} d_{\text{ff}} nlayer2dmodeldff | 2 n layer 2 d model d ff 2n_{\text{layer}} 2d_{\text{model}} d_{\text{ff}} 2nlayer2dmodeldff |
De-embed | - | 2 d model n vocab 2d_{\text{model}} n_{\text{vocab}} 2dmodelnvocab |
Total (Non-Embedding) | N = 2 d model n layer ( 2 d attn + d ff ) N = 2d_{\text{model}} n_{\text{layer}} (2d_{\text{attn}} + d_{\text{ff}}) N=2dmodelnlayer(2dattn+dff) | C forward = 2 N + 2 n layer n ctx d attn C_{\text{forward}} = 2N + 2n_{\text{layer}} n_{\text{ctx}} d_{\text{attn}} Cforward=2N+2nlayernctxdattn |
4.2.3 Embedding层
-
功能:
Embedding层完成输入ID到向量的映射,将词表大小的ID映射到 d model d_{\text{model}} dmodel维度的向量。 -
计算转换:
[ batch , n ctx ] × [ vocab , d model ] → [ batch , n ctx , d model ] [ \text{batch}, n_{\text{ctx}} ] \times [ \text{vocab}, d_{\text{model}} ] \rightarrow [ \text{batch}, n_{\text{ctx}}, d_{\text{model}} ] [batch,nctx]×[vocab,dmodel]→[batch,nctx,dmodel] -
操作:
这里的“ × \times ×”代表lookup操作。 -
参数量:
- 词嵌入矩阵参数量大小为: n vocab × d model n_{\text{vocab}} \times d_{\text{model}} nvocab×dmodel
- 上下文输入向量大小为: n ctx × d model n_{\text{ctx}} \times d_{\text{model}} nctx×dmodel
4.2.4 Attention QKV 层
功能:
Attention QKV层完成输入向量到注意力层的映射,将隐层大小 d model d_{\text{model}} dmodel映射到多头注意力 3 d attn 3d_{\text{attn}} 3dattn维度的向量。
计算转换:
[ batch , n ctx , d model ] × [ d model , 3 d attn ] [\text{batch}, n_{\text{ctx}}, d_{\text{model}}] \times [d_{\text{model}}, 3d_{\text{attn}}] [batch,nctx,dmodel]×[dmodel,3dattn]
参数量:
每一层的变换如上所示,Attention QKV层参数量大小为: n layer d model 3 d attn n_{\text{layer}} d_{\text{model}} 3d_{\text{attn}} nlayerdmodel3dattn
计算量:
计算量包括矩阵的乘法运算和加法运算两个操作,每个Token计算量大小为:
2 × batch × n ctx × n layer d model 3 d attn / ( batch × n ctx ) = 2 n layer d model 3 d attn 2 \times \text{batch} \times n_{\text{ctx}} \times n_{\text{layer}} d_{\text{model}} 3d_{\text{attn}} / (\text{batch} \times n_{\text{ctx}}) = 2n_{\text{layer}} d_{\text{model}} 3d_{\text{attn}} 2×batch×nctx×nlayerdmodel3dattn/(batch×nctx)=2nlayerdmodel3dattn
4.2.5 Attention Mask层
功能:
Attention Mask层完成以下计算操作:
Softmax ( Q K T d model ) V \text{Softmax}\left( \frac{QK^T}{\sqrt{d_{\text{model}}}} \right) V Softmax(dmodelQKT)V
计算维度转换:
[ batch , n ctx , d attn ] × [ batch , d attn , n ctx ] → [ batch , n ctx , n ctx ] [\text{batch}, n_{\text{ctx}}, d_{\text{attn}}] \times [\text{batch}, d_{\text{attn}}, n_{\text{ctx}}] \rightarrow [\text{batch}, n_{\text{ctx}}, n_{\text{ctx}}] [batch,nctx,dattn]×[batch,dattn,nctx]→[batch,nctx,nctx]
[ batch , n ctx , n ctx ] × [ batch , n ctx , d attn ] → [ batch , n ctx , d attn ] [\text{batch}, n_{\text{ctx}}, n_{\text{ctx}}] \times [\text{batch}, n_{\text{ctx}}, d_{\text{attn}}] \rightarrow [\text{batch}, n_{\text{ctx}}, d_{\text{attn}}] [batch,nctx,nctx]×[batch,nctx,dattn]→[batch,nctx,dattn]
未引入新的变量,因为无参数量。
计算量:
Attention Mask层计算量包括矩阵的乘法运算和加法运算两个操作,每个Token计算量大小为:
2 × n layer × ( batch × n ctx × d attn × n ctx + batch × n ctx × n ctx × d attn ) / ( batch × n ctx ) = 2 n layer n ctx d attn 2 \times n_{\text{layer}} \times (\text{batch} \times n_{\text{ctx}} \times d_{\text{attn}} \times n_{\text{ctx}} + \text{batch} \times n_{\text{ctx}} \times n_{\text{ctx}} \times d_{\text{attn}}) / (\text{batch} \times n_{\text{ctx}}) = 2n_{\text{layer}} n_{\text{ctx}} d_{\text{attn}} 2×nlayer×(batch×nctx×dattn×nctx+batch×nctx×nctx×dattn)/(batch×nctx)=2nlayernctxdattn
4.2.6 Attention Project层总结
功能:
Attention Project层完成从Attention输出维度 d attn d_{\text{attn}} dattn到隐层大小 d model d_{\text{model}} dmodel的映射。
计算维度转换:
[ batch , n ctx , d attn ] × [ d attn , d model ] → [ batch , n ctx , d model ] [\text{batch}, n_{\text{ctx}}, d_{\text{attn}}] \times [d_{\text{attn}}, d_{\text{model}}] \rightarrow [\text{batch}, n_{\text{ctx}}, d_{\text{model}}] [batch,nctx,dattn]×[dattn,dmodel]→[batch,nctx,dmodel]
参数量:
每一层的变化均如上所示,Attention Project层参数量大小为: n layer d attn d model n_{\text{layer}} d_{\text{attn}} d_{\text{model}} nlayerdattndmodel
计算量:
Attention Project层计算量包括矩阵的乘法运算和加法运算两个操作,每个Token计算量大小为:
2 × n layer × batch × n ctx × d attn × d model / ( batch × n ctx ) = 2 n layer d attn d model 2 \times n_{\text{layer}} \times \text{batch} \times n_{\text{ctx}} \times d_{\text{attn}} \times d_{\text{model}} / (\text{batch} \times n_{\text{ctx}}) = 2n_{\text{layer}} d_{\text{attn}} d_{\text{model}} 2×nlayer×batch×nctx×dattn×dmodel/(batch×nctx)=2nlayerdattndmodel
4.2.7 Feedforward层总结
功能:
Feedforward层完成从隐层大小 d model d_{\text{model}} dmodel到前馈隐层大小 d ff d_{\text{ff}} dff再到隐层大小 d model d_{\text{model}} dmodel的映射。
计算维度转换:
[ batch , n ctx , d model ] × [ d model , d ff ] → [ batch , n ctx , d ff ] [\text{batch}, n_{\text{ctx}}, d_{\text{model}}] \times [d_{\text{model}}, d_{\text{ff}}] \rightarrow [\text{batch}, n_{\text{ctx}}, d_{\text{ff}}] [batch,nctx,dmodel]×[dmodel,dff]→[batch,nctx,dff]
[ batch , n ctx , d ff ] × [ d ff , d model ] → [ batch , n ctx , d model ] [\text{batch}, n_{\text{ctx}}, d_{\text{ff}}] \times [d_{\text{ff}}, d_{\text{model}}] \rightarrow [\text{batch}, n_{\text{ctx}}, d_{\text{model}}] [batch,nctx,dff]×[dff,dmodel]→[batch,nctx,dmodel]
参数量:
每一层的变化均如上所示,Feedforward层参数量大小为: n layer 2 d model d ff n_{\text{layer}} 2d_{\text{model}} d_{\text{ff}} nlayer2dmodeldff
计算量:
Feedforward层计算量包括矩阵的乘法运算和加法运算两个操作,每个Token计算量大小为:
2 × n layer × ( batch × n ctx × d model × d ff + batch × n ctx × d ff × d model ) / ( batch × n ctx ) = 2 n layer 2 d model d ff 2 \times n_{\text{layer}} \times (\text{batch} \times n_{\text{ctx}} \times d_{\text{model}} \times d_{\text{ff}} + \text{batch} \times n_{\text{ctx}} \times d_{\text{ff}} \times d_{\text{model}}) / (\text{batch} \times n_{\text{ctx}}) = 2n_{\text{layer}} 2d_{\text{model}} d_{\text{ff}} 2×nlayer×(batch×nctx×dmodel×dff+batch×nctx×dff×dmodel)/(batch×nctx)=2nlayer2dmodeldff
4.2.8 De-emb层总结
功能:
De-emb层完成从隐层大小 d model d_{\text{model}} dmodel到输出 n vocab n_{\text{vocab}} nvocab的映射。
计算维度转换:
[ batch , n ctx , d model ] × [ d model , n vocab ] → [ batch , n ctx , n vocab ] [\text{batch}, n_{\text{ctx}}, d_{\text{model}}] \times [d_{\text{model}}, n_{\text{vocab}}] \rightarrow [\text{batch}, n_{\text{ctx}}, n_{\text{vocab}}] [batch,nctx,dmodel]×[dmodel,nvocab]→[batch,nctx,nvocab]
操作方式:
De-embedding层通常使用与输入嵌入层(Embedding层)相同的权重矩阵来进行线性转换。这种权重共享的策略有助于减少模型参数量,从而降低过拟合的风险。因此,不需要为De-embedding层单独分配参数量。
计算量:
计算量包括矩阵的乘法运算和加法运算两个操作,每个Token计算量大小为:
2 × batch × n ctx × d model × n vocab / ( batch × n ctx ) = 2 d model n vocab 2 \times \text{batch} \times n_{\text{ctx}} \times d_{\text{model}} \times n_{\text{vocab}} / (\text{batch} \times n_{\text{ctx}}) = 2d_{\text{model}} n_{\text{vocab}} 2×batch×nctx×dmodel×nvocab/(batch×nctx)=2dmodelnvocab
4.2.9 总结
模型总参数量(不包括Embedding参数):
N = n layer ( d model 3 d attn + d attn d model + 2 d model d ff ) = 2 d model n layer ( 2 d attn + d ff ) N = n_{\text{layer}} (d_{\text{model}} 3d_{\text{attn}} + d_{\text{attn}} d_{\text{model}} + 2d_{\text{model}} d_{\text{ff}}) = 2d_{\text{model}} n_{\text{layer}} (2d_{\text{attn}} + d_{\text{ff}}) N=nlayer(dmodel3dattn+dattndmodel+2dmodeldff)=2dmodelnlayer(2dattn+dff)
每个Token计算量:
C forward = 2 n layer ( d model 3 d attn + n ctx d model + d attn d model + 2 d model d ff ) C_{\text{forward}} = 2n_{\text{layer}} (d_{\text{model}} 3d_{\text{attn}} + n_{\text{ctx}} d_{\text{model}} + d_{\text{attn}} d_{\text{model}} + 2d_{\text{model}} d_{\text{ff}}) Cforward=2nlayer(dmodel3dattn+nctxdmodel+dattndmodel+2dmodeldff)
= 4 d model n layer ( 2 d attn + d ff ) + 2 n layer n ctx d attn = 4d_{\text{model}} n_{\text{layer}} (2d_{\text{attn}} + d_{\text{ff}}) + 2n_{\text{layer}} n_{\text{ctx}} d_{\text{attn}} =4dmodelnlayer(2dattn+dff)+2nlayernctxdattn
= 2 N + 2 n layer n ctx d attn = 2N + 2n_{\text{layer}} n_{\text{ctx}} d_{\text{attn}} =2N+2nlayernctxdattn
4.2.10 实例分析
以下是两个具体实例的分析及总结:
ChatGLM-6B
-
参数:
- 层数:28层
- 隐藏层大小:4096
- 中间隐藏层大小:16384
- 注意力头数:32
- 词表大小:130528
- 上下文长度:2048
-
参数量计算:
N = 2 × 4096 × 28 × ( 2 × 4096 + 16386 ) + ( 130528 + 2048 ) × 4096 = 6 , 180 , 634 , 624 N = 2 \times 4096 \times 28 \times (2 \times 4096 + 16386) + (130528 + 2048) \times 4096 = 6,180,634,624 N=2×4096×28×(2×4096+16386)+(130528+2048)×4096=6,180,634,624
LLAMA-7B
-
参数:
- 层数:32层
- 隐藏层大小:4096
- 中间隐藏层大小:11008
- 注意力头数:32
- 词表大小:32000
- 上下文长度:2048
-
参数量计算:
N = 2 × 4096 × 32 × ( 2 × 4096 + 11008 ) + ( 32000 + 2048 ) × 4096 = 5 , 172 , 625 , 408 N = 2 \times 4096 \times 32 \times (2 \times 4096 + 11008) + (32000 + 2048) \times 4096 = 5,172,625,408 N=2×4096×32×(2×4096+11008)+(32000+2048)×4096=5,172,625,408
计算结果与模型参数不符原因
发现上述计算结果与实际模型参数不符的原因在于LLAMA的前馈神经网络层采用了SwiGLU激活函数,使得FFN层的计算方式发生变化:
F F N SwiGLU ( x , W , V , W 2 ) = ( Swish ( x W ) ∘ x V ) W 2 FFN_{\text{SwiGLU}}(x, W, V, W_2) = (\text{Swish}(xW) \circ xV) W_2 FFNSwiGLU(x,W,V,W2)=(Swish(xW)∘xV)W2
因此,FFN相比原计算方式参数矩阵从2个变成了3个。
修正后的LLAMA-7B计算
- 修正参数量计算:
N = 2 × 4096 × 32 × ( 2 × 4096 + 11008 × 3 / 2 ) + ( 32000 + 2048 ) × 4096 = 6 , 615 , 465 , 984 N = 2 \times 4096 \times 32 \times (2 \times 4096 + 11008 \times 3 / 2) + (32000 + 2048) \times 4096 = 6,615,465,984 N=2×4096×32×(2×4096+11008×3/2)+(32000+2048)×4096=6,615,465,984
LLAMA-13B
-
参数:
- 层数:40层
- 隐藏层大小:5120
- 中间隐藏层大小:13824
- 注意力头数:40
- 词表大小:32000
- 上下文长度:2048
-
参数量计算:
N = 2 × 5120 × 40 × ( 2 × 5120 + 13824 × 3 / 2 ) + ( 32000 + 2048 ) × 5120 = 12 , 862 , 095 , 360 N = 2 \times 5120 \times 40 \times (2 \times 5120 + 13824 \times 3 / 2) + (32000 + 2048) \times 5120 = 12,862,095,360 N=2×5120×40×(2×5120+13824×3/2)+(32000+2048)×5120=12,862,095,360
4.3 优化器
4.3.1 Adam优化器的显存计算公式
-
模型参数显存:
模型参数显存 = 参数数量 × 每个参数的字节数 \text{模型参数显存} = \text{参数数量} \times \text{每个参数的字节数} 模型参数显存=参数数量×每个参数的字节数 -
动量(m)显存 (梯度指数平滑值):
动量显存 = 参数数量 × 每个动量变量的字节数 \text{动量显存} = \text{参数数量} \times \text{每个动量变量的字节数} 动量显存=参数数量×每个动量变量的字节数 -
平方梯度(v)显存 (梯度平方指数平滑值):
平方梯度显存 = 参数数量 × 每个平方梯度变量的字节数 \text{平方梯度显存} = \text{参数数量} \times \text{每个平方梯度变量的字节数} 平方梯度显存=参数数量×每个平方梯度变量的字节数 -
Adam优化器总显存:
Adam优化器总显存 = 动量显存 + 平方梯度显存 \text{Adam优化器总显存} = \text{动量显存} + \text{平方梯度显存} Adam优化器总显存=动量显存+平方梯度显存
LLama13B 有130亿(13B)个参数,每个参数为32位浮点数(4字节)(因为梯度值很小,需要用FP32保存,以避免精度损失)
4.3.2 LLama 13B Adam优化器的显存计算实例
-
模型参数显存:
模型参数显存 = 13 × 1 0 9 × 4 字节 = 52 GB \text{模型参数显存} = 13 \times 10^9 \times 4 \text{字节} = 52 \text{GB} 模型参数显存=13×109×4字节=52GB
-
动量显存:
动量显存 = 13 × 1 0 9 × 4 字节 = 52 GB \text{动量显存} = 13 \times 10^9 \times 4 \text{字节} = 52 \text{GB} 动量显存=13×109×4字节=52GB -
平方梯度显存:
平方梯度显存 = 13 × 1 0 9 × 4 字节 = 52 GB \text{平方梯度显存} = 13 \times 10^9 \times 4 \text{字节} = 52 \text{GB} 平方梯度显存=13×109×4字节=52GB -
Adam优化器总显存:
Adam优化器总显存 = 2 × 动量显存 = 2 × 52 GB = 104 GB \text{Adam优化器总显存} = 2 \times \text{动量显存} = 2 \times 52 \text{GB} = 104 \text{GB} Adam优化器总显存=2×动量显存=2×52GB=104GB -
总计 : 156GB
4.4 激活值
对于激活值的估计,采用了Reducing Activation Recomputation in Large Transformer Models 这篇论文的激活值估算方法。
激活内存需求的计算分为三部分:注意力块、MLP块和层规范化(Layer Norm)。每个部分的内存需求如下:
- s:序列长度(Sequence Length),表示输入序列的长度。例如,在自然语言处理中,s表示输入句子的单词数。
- b:微批次大小(Microbatch Size),表示一次计算中处理的样本数量。这个值通常是一个较小的批次大小,以便在计算资源受限时更高效地进行训练。
- h:隐藏层维度(Hidden Dimension Size),表示Transformer模型中每一层的隐藏状态的维度。h通常是一个较大的值,以提供足够的表示能力。
-
注意力块(Attention Block)
- 线性投影输入激活值:2sbh
- 注意力dropout所需的掩码:sbh
- 自注意力(Self-Attention)
- Q, K, V矩阵乘法的输入激活值:2sbh
- QKT矩阵乘法:4sbh
- Softmax输出:2as^2b
- Softmax dropout的掩码:as^2b
- 注意力值(Values)和其dropout输出:2as^2b + 2sbh
- 总计:11sbh + 5as^2b
-
MLP块
- 两个线性层的输入激活值:2sbh和8sbh
- GeLU非线性激活:8sbh
- Dropout的掩码:sbh
- 总计:19sbh
-
层规范化(Layer Norm)
- 每个层规范化的输入激活值:2sbh
- 总计:4sbh
综合以上计算,一个Transformer层的激活内存需求为:
Activations memory per layer = s b h ( 34 + 5 a s h ) \text{Activations memory per layer} = sbh \left(34 + \frac{5as}{h}\right) Activations memory per layer=sbh(34+h5as)
4.4.1 总激活内存需求
对于包含L层的Transformer网络,总激活内存需求为:
Total activations memory = s b h L ( 34 + 5 a s h ) \text{Total activations memory} = sbhL \left(34 + \frac{5as}{h}\right) Total activations memory=sbhL(34+h5as)
这种公式计算方法考虑了主要的激活内存贡献者,忽略了较小的缓冲区,提供了一个较为准确的激活内存需求估算。
4.4.2 LLama 13B 激活内存计算实例
激活值的内存消耗计算公式为:
Memory (GB) = s × b × h × ( 34 + 5 × a × s h ) × L 1024 × 1024 × 1024 \text{Memory (GB)} = \frac{s \times b \times h \times (34 + 5 \times a \times \frac{s}{h}) \times L}{1024 \times 1024 \times 1024} Memory (GB)=1024×1024×1024s×b×h×(34+5×a×hs)×L
LLama 13B
- s 序列长度:1024
- b batch size:1
- h 隐藏层大小:5120
- a Attention 头:40
- L 层数 :40
FP16:
s * b * h * (34 + 5 * a * s/h ) * L /1024 /1024/1024 GB = 14.5GB
4.5 梯度值
与推理相比,我们只需要在传递给下一层之前存储单个层的激活,微调需要存储前向传播过程中创建的所有激活。这对于计算梯度是必要的,然后用于反向传播误差并更新模型的权重。
为了估计计算梯度所需的内存,我们可以使用用于推理的相同公式,然后将结果乘以层数。
在反向传播过程中,需要存储每一层的梯度,这些梯度包括参数的梯度和激活值的梯度。
一个Transformer层的梯度内存需求为:
Gradients memory per layer = s b h ( 34 + 5 a s h ) \text{Gradients memory per layer} = sbh \left(34 + \frac{5as}{h}\right) Gradients memory per layer=sbh(34+h5as)
如果L是层数,那么计算梯度所消耗的内存为
Total memory per layer = s b h L ( 34 + 5 a s h ) \text{Total memory per layer} = sbhL \left(34 + \frac{5as}{h}\right) Total memory per layer=sbhL(34+h5as)
FP16:
s * b * h * (34 + 5 * a * s/h ) * L /1024 /1024/1024 GB = 14.5GB
4.6 总计
Batch Size = 1 , Seq_Len = 1024, FP16
- 模型参数:26GB
- 优化器:156GB
- 激活值:14.5GB
- 梯度值:26GB
- 合计:222.5GB
5. 模型GPU显存占用(实验代码计算)
5.1 简介
本文使用Wanda方法,已在Github上开源
论文:A Simple and Effective Pruning Approach for Large Language Models
**源码:**https://github.com/locuslab/wanda
环境配置
- 操作系统:Windows11
- GPU :Nvidia RTX 3090
- Python : 3.9
- pytorch==1.10.1
- cudatoolkit==11.3
- transformers==4.28.0
- datasets==2.11.0
- accelerate==0.18.0
详细环境配置以及使用手册请查看 Github 中的 README 文件
5.2定义显存监控函数
定义一个显存监控函数 print_memory_usage
,以便在代码中调用:
import torchdef print_memory_usage(stage=''):"""打印当前显存使用情况"""allocated = torch.cuda.memory_allocated() / 1024**3 # 转换为GBreserved = torch.cuda.memory_reserved() / 1024**3 # 转换为GBprint(f"{stage} - Allocated memory: {allocated:.2f} GB")print(f"{stage} - Reserved memory: {reserved:.2f} GB")
5.3 Magnitude 方法实例
5.3.1 代码实例
在 prune.py
中prune_magnitude
函数中添加print_memory_usage
查看显存函数
def prune_magnitude(args, model, tokenizer, device=torch.device("cuda:0"), prune_n=0, prune_m=0):layers = model.model.layers# 在开始修剪之前,打印当前显存使用情况。这样可以了解开始修剪之前的显存状态。print_memory_usage("剪枝之前")for i in range(len(layers)):layer = layers[i]subset = find_layers(layer)# 在处理每一层之前打印显存使用情况。这有助于监控每一层处理对显存的影响。print_memory_usage(f"处理第 {i} 层之前")for name in subset:W = subset[name].weight.dataW_metric = torch.abs(W)if prune_n != 0:W_mask = (torch.zeros_like(W)==1)for ii in range(W_metric.shape[1]):if ii % prune_m == 0:tmp = W_metric[:,ii:(ii+prune_m)].float()W_mask.scatter_(1,ii+torch.topk(tmp, prune_n,dim=1, largest=False)[1], True)else:thresh = torch.sort(W_metric.flatten().cuda())[0][int(W.numel()*args.sparsity_ratio)].cpu()W_mask = (W_metric<=thresh)W[W_mask] = 0# 在每一层的权重修剪之后打印显存使用情况。这样可以了解修剪操作对显存的影响。print_memory_usage(f"剪枝第 {i} 的权重 {name} 之后")# 在所有层修剪完成之后打印显存使用情况,获取整体的显存使用情况print_memory_usage("剪枝所有层之后")
5.3.2 实验运行
python main.py --model meta-llama/Llama-2-7b-hf --prune_method magnitude --sparsity_ratio 0.5 --sparsity_type unstructured --save out/llama2_7b/unstructured/magnitude/
详细解释:
- 加载
meta-llama/Llama-2-7b-hf
模型。 - 使用
magnitude
剪枝方法对模型进行剪枝。 - 剪枝的稀疏率设为50%,即模型的50%参数会被剪掉。
- 剪枝类型是不结构化的稀疏(unstructured),参数可以任意位置剪枝。
- 最后,将剪枝后的模型保存到指定的目录
out/llama2_7b/unstructured/magnitude/
5.3.3 实验结果
use device cuda:0
pruning starts
剪枝之前 - 分配内存: 12.68 GB
剪枝之前 - 保留内存: 12.69 GB
处理第 0 层之前 - 分配内存: 12.68 GB
处理第 0 层之前 - 保留内存: 12.69 GB
剪枝第 0 的权重 self_attn.q_proj 之后 - 分配内存: 12.72 GB
剪枝第 0 的权重 self_attn.q_proj 之后 - 保留内存: 13.35 GB
剪枝第 0 的权重 self_attn.k_proj 之后 - 分配内存: 12.72 GB
剪枝第 0 的权重 self_attn.k_proj 之后 - 保留内存: 13.35 GB
剪枝第 0 的权重 self_attn.v_proj 之后 - 分配内存: 12.72 GB
剪枝第 0 的权重 self_attn.v_proj 之后 - 保留内存: 13.35 GB
剪枝第 0 的权重 self_attn.o_proj 之后 - 分配内存: 12.72 GB
剪枝第 0 的权重 self_attn.o_proj 之后 - 保留内存: 13.35 GB
剪枝第 0 的权重 mlp.gate_proj 之后 - 分配内存: 12.80 GB
剪枝第 0 的权重 mlp.gate_proj 之后 - 保留内存: 14.95 GB
剪枝第 0 的权重 mlp.down_proj 之后 - 分配内存: 12.80 GB
剪枝第 0 的权重 mlp.down_proj 之后 - 保留内存: 14.95 GB
剪枝第 0 的权重 mlp.up_proj 之后 - 分配内存: 12.80 GB
剪枝第 0 的权重 mlp.up_proj 之后 - 保留内存: 14.95 GB
处理第 1 层之前 - 分配内存: 12.80 GB
处理第 1 层之前 - 保留内存: 14.95 GB
剪枝第 1 的权重 self_attn.q_proj 之后 - 分配内存: 12.72 GB
剪枝第 1 的权重 self_attn.q_proj 之后 - 保留内存: 14.95 GB
剪枝第 1 的权重 self_attn.k_proj 之后 - 分配内存: 12.72 GB
剪枝第 1 的权重 self_attn.k_proj 之后 - 保留内存: 14.95 GB
剪枝第 1 的权重 self_attn.v_proj 之后 - 分配内存: 12.72 GB
剪枝第 1 的权重 self_attn.v_proj 之后 - 保留内存: 14.95 GB
剪枝第 1 的权重 self_attn.o_proj 之后 - 分配内存: 12.72 GB
剪枝第 1 的权重 self_attn.o_proj 之后 - 保留内存: 14.95 GB
剪枝第 1 的权重 mlp.gate_proj 之后 - 分配内存: 12.80 GB
剪枝第 1 的权重 mlp.gate_proj 之后 - 保留内存: 14.95 GB
剪枝第 1 的权重 mlp.down_proj 之后 - 分配内存: 12.80 GB
剪枝第 1 的权重 mlp.down_proj 之后 - 保留内存: 14.95 GB
剪枝第 1 的权重 mlp.up_proj 之后 - 分配内存: 12.80 GB
剪枝第 1 的权重 mlp.up_proj 之后 - 保留内存: 14.95 GB
处理第 2 层之前 - 分配内存: 12.80 GB
处理第 2 层之前 - 保留内存: 14.95 GB
剪枝第 2 的权重 self_attn.q_proj 之后 - 分配内存: 12.72 GB
剪枝第 2 的权重 self_attn.q_proj 之后 - 保留内存: 14.95 GB
剪枝第 2 的权重 self_attn.k_proj 之后 - 分配内存: 12.72 GB
剪枝第 2 的权重 self_attn.k_proj 之后 - 保留内存: 14.95 GB
剪枝第 2 的权重 self_attn.v_proj 之后 - 分配内存: 12.72 GB
剪枝第 2 的权重 self_attn.v_proj 之后 - 保留内存: 14.95 GB
剪枝第 2 的权重 self_attn.o_proj 之后 - 分配内存: 12.72 GB
剪枝第 2 的权重 self_attn.o_proj 之后 - 保留内存: 14.95 GB
剪枝第 2 的权重 mlp.gate_proj 之后 - 分配内存: 12.80 GB
剪枝第 2 的权重 mlp.gate_proj 之后 - 保留内存: 14.95 GB
剪枝第 2 的权重 mlp.down_proj 之后 - 分配内存: 12.80 GB
剪枝第 2 的权重 mlp.down_proj 之后 - 保留内存: 14.95 GB
剪枝第 2 的权重 mlp.up_proj 之后 - 分配内存: 12.80 GB
剪枝第 2 的权重 mlp.up_proj 之后 - 保留内存: 14.95 GB
处理第 3 层之前 - 分配内存: 12.80 GB
处理第 3 层之前 - 保留内存: 14.95 GB
剪枝第 3 的权重 self_attn.q_proj 之后 - 分配内存: 12.72 GB
剪枝第 3 的权重 self_attn.q_proj 之后 - 保留内存: 14.95 GB
剪枝第 3 的权重 self_attn.k_proj 之后 - 分配内存: 12.72 GB
剪枝第 3 的权重 self_attn.k_proj 之后 - 保留内存: 14.95 GB
剪枝第 3 的权重 self_attn.v_proj 之后 - 分配内存: 12.72 GB
剪枝第 3 的权重 self_attn.v_proj 之后 - 保留内存: 14.95 GB
剪枝第 3 的权重 self_attn.o_proj 之后 - 分配内存: 12.72 GB
剪枝第 3 的权重 self_attn.o_proj 之后 - 保留内存: 14.95 GB
剪枝第 3 的权重 mlp.gate_proj 之后 - 分配内存: 12.80 GB
剪枝第 3 的权重 mlp.gate_proj 之后 - 保留内存: 14.95 GB
剪枝第 3 的权重 mlp.down_proj 之后 - 分配内存: 12.80 GB
剪枝第 3 的权重 mlp.down_proj 之后 - 保留内存: 14.95 GB
剪枝第 3 的权重 mlp.up_proj 之后 - 分配内存: 12.80 GB
剪枝第 3 的权重 mlp.up_proj 之后 - 保留内存: 14.95 GB
处理第 4 层之前 - 分配内存: 12.80 GB
处理第 4 层之前 - 保留内存: 14.95 GB
剪枝第 4 的权重 self_attn.q_proj 之后 - 分配内存: 12.72 GB
剪枝第 4 的权重 self_attn.q_proj 之后 - 保留内存: 14.95 GB
剪枝第 4 的权重 self_attn.k_proj 之后 - 分配内存: 12.72 GB
剪枝第 4 的权重 self_attn.k_proj 之后 - 保留内存: 14.95 GB
剪枝第 4 的权重 self_attn.v_proj 之后 - 分配内存: 12.72 GB
剪枝第 4 的权重 self_attn.v_proj 之后 - 保留内存: 14.95 GB
剪枝第 4 的权重 self_attn.o_proj 之后 - 分配内存: 12.72 GB
剪枝第 4 的权重 self_attn.o_proj 之后 - 保留内存: 14.95 GB
剪枝第 4 的权重 mlp.gate_proj 之后 - 分配内存: 12.80 GB
剪枝第 4 的权重 mlp.gate_proj 之后 - 保留内存: 14.95 GB
剪枝第 4 的权重 mlp.down_proj 之后 - 分配内存: 12.80 GB
剪枝第 4 的权重 mlp.down_proj 之后 - 保留内存: 14.95 GB
剪枝第 4 的权重 mlp.up_proj 之后 - 分配内存: 12.80 GB
剪枝第 4 的权重 mlp.up_proj 之后 - 保留内存: 14.95 GB
处理第 5 层之前 - 分配内存: 12.80 GB
处理第 5 层之前 - 保留内存: 14.95 GB
剪枝第 5 的权重 self_attn.q_proj 之后 - 分配内存: 12.72 GB
剪枝第 5 的权重 self_attn.q_proj 之后 - 保留内存: 14.95 GB
剪枝第 5 的权重 self_attn.k_proj 之后 - 分配内存: 12.72 GB
剪枝第 5 的权重 self_attn.k_proj 之后 - 保留内存: 14.95 GB
剪枝第 5 的权重 self_attn.v_proj 之后 - 分配内存: 12.72 GB
剪枝第 5 的权重 self_attn.v_proj 之后 - 保留内存: 14.95 GB
剪枝第 5 的权重 self_attn.o_proj 之后 - 分配内存: 12.72 GB
剪枝第 5 的权重 self_attn.o_proj 之后 - 保留内存: 14.95 GB
剪枝第 5 的权重 mlp.gate_proj 之后 - 分配内存: 12.80 GB
剪枝第 5 的权重 mlp.gate_proj 之后 - 保留内存: 14.95 GB
剪枝第 5 的权重 mlp.down_proj 之后 - 分配内存: 12.80 GB
剪枝第 5 的权重 mlp.down_proj 之后 - 保留内存: 14.95 GB
剪枝第 5 的权重 mlp.up_proj 之后 - 分配内存: 12.80 GB
剪枝第 5 的权重 mlp.up_proj 之后 - 保留内存: 14.95 GB
处理第 6 层之前 - 分配内存: 12.80 GB
处理第 6 层之前 - 保留内存: 14.95 GB
剪枝第 6 的权重 self_attn.q_proj 之后 - 分配内存: 12.72 GB
剪枝第 6 的权重 self_attn.q_proj 之后 - 保留内存: 14.95 GB
剪枝第 6 的权重 self_attn.k_proj 之后 - 分配内存: 12.72 GB
剪枝第 6 的权重 self_attn.k_proj 之后 - 保留内存: 14.95 GB
剪枝第 6 的权重 self_attn.v_proj 之后 - 分配内存: 12.72 GB
剪枝第 6 的权重 self_attn.v_proj 之后 - 保留内存: 14.95 GB
剪枝第 6 的权重 self_attn.o_proj 之后 - 分配内存: 12.72 GB
剪枝第 6 的权重 self_attn.o_proj 之后 - 保留内存: 14.95 GB
剪枝第 6 的权重 mlp.gate_proj 之后 - 分配内存: 12.80 GB
剪枝第 6 的权重 mlp.gate_proj 之后 - 保留内存: 14.95 GB
剪枝第 6 的权重 mlp.down_proj 之后 - 分配内存: 12.80 GB
剪枝第 6 的权重 mlp.down_proj 之后 - 保留内存: 14.95 GB
剪枝第 6 的权重 mlp.up_proj 之后 - 分配内存: 12.80 GB
剪枝第 6 的权重 mlp.up_proj 之后 - 保留内存: 14.95 GB
处理第 7 层之前 - 分配内存: 12.80 GB
处理第 7 层之前 - 保留内存: 14.95 GB
剪枝第 7 的权重 self_attn.q_proj 之后 - 分配内存: 12.72 GB
剪枝第 7 的权重 self_attn.q_proj 之后 - 保留内存: 14.95 GB
剪枝第 7 的权重 self_attn.k_proj 之后 - 分配内存: 12.72 GB
剪枝第 7 的权重 self_attn.k_proj 之后 - 保留内存: 14.95 GB
剪枝第 7 的权重 self_attn.v_proj 之后 - 分配内存: 12.72 GB
剪枝第 7 的权重 self_attn.v_proj 之后 - 保留内存: 14.95 GB
剪枝第 7 的权重 self_attn.o_proj 之后 - 分配内存: 12.72 GB
剪枝第 7 的权重 self_attn.o_proj 之后 - 保留内存: 14.95 GB
剪枝第 7 的权重 mlp.gate_proj 之后 - 分配内存: 12.80 GB
剪枝第 7 的权重 mlp.gate_proj 之后 - 保留内存: 14.95 GB
剪枝第 7 的权重 mlp.down_proj 之后 - 分配内存: 12.80 GB
剪枝第 7 的权重 mlp.down_proj 之后 - 保留内存: 14.95 GB
剪枝第 7 的权重 mlp.up_proj 之后 - 分配内存: 12.80 GB
剪枝第 7 的权重 mlp.up_proj 之后 - 保留内存: 14.95 GB
处理第 8 层之前 - 分配内存: 12.80 GB
处理第 8 层之前 - 保留内存: 14.95 GB
剪枝第 8 的权重 self_attn.q_proj 之后 - 分配内存: 12.72 GB
剪枝第 8 的权重 self_attn.q_proj 之后 - 保留内存: 14.95 GB
剪枝第 8 的权重 self_attn.k_proj 之后 - 分配内存: 12.72 GB
剪枝第 8 的权重 self_attn.k_proj 之后 - 保留内存: 14.95 GB
剪枝第 8 的权重 self_attn.v_proj 之后 - 分配内存: 12.72 GB
剪枝第 8 的权重 self_attn.v_proj 之后 - 保留内存: 14.95 GB
剪枝第 8 的权重 self_attn.o_proj 之后 - 分配内存: 12.72 GB
剪枝第 8 的权重 self_attn.o_proj 之后 - 保留内存: 14.95 GB
剪枝第 8 的权重 mlp.gate_proj 之后 - 分配内存: 12.80 GB
剪枝第 8 的权重 mlp.gate_proj 之后 - 保留内存: 14.95 GB
剪枝第 8 的权重 mlp.down_proj 之后 - 分配内存: 12.80 GB
剪枝第 8 的权重 mlp.down_proj 之后 - 保留内存: 14.95 GB
剪枝第 8 的权重 mlp.up_proj 之后 - 分配内存: 12.80 GB
剪枝第 8 的权重 mlp.up_proj 之后 - 保留内存: 14.95 GB
处理第 9 层之前 - 分配内存: 12.80 GB
处理第 9 层之前 - 保留内存: 14.95 GB
剪枝第 9 的权重 self_attn.q_proj 之后 - 分配内存: 12.72 GB
剪枝第 9 的权重 self_attn.q_proj 之后 - 保留内存: 14.95 GB
剪枝第 9 的权重 self_attn.k_proj 之后 - 分配内存: 12.72 GB
剪枝第 9 的权重 self_attn.k_proj 之后 - 保留内存: 14.95 GB
剪枝第 9 的权重 self_attn.v_proj 之后 - 分配内存: 12.72 GB
剪枝第 9 的权重 self_attn.v_proj 之后 - 保留内存: 14.95 GB
剪枝第 9 的权重 self_attn.o_proj 之后 - 分配内存: 12.72 GB
剪枝第 9 的权重 self_attn.o_proj 之后 - 保留内存: 14.95 GB
剪枝第 9 的权重 mlp.gate_proj 之后 - 分配内存: 12.80 GB
剪枝第 9 的权重 mlp.gate_proj 之后 - 保留内存: 14.95 GB
剪枝第 9 的权重 mlp.down_proj 之后 - 分配内存: 12.80 GB
剪枝第 9 的权重 mlp.down_proj 之后 - 保留内存: 14.95 GB
剪枝第 9 的权重 mlp.up_proj 之后 - 分配内存: 12.80 GB
剪枝第 9 的权重 mlp.up_proj 之后 - 保留内存: 14.95 GB
处理第 10 层之前 - 分配内存: 12.80 GB
处理第 10 层之前 - 保留内存: 14.95 GB
剪枝第 10 的权重 self_attn.q_proj 之后 - 分配内存: 12.72 GB
剪枝第 10 的权重 self_attn.q_proj 之后 - 保留内存: 14.95 GB
剪枝第 10 的权重 self_attn.k_proj 之后 - 分配内存: 12.72 GB
剪枝第 10 的权重 self_attn.k_proj 之后 - 保留内存: 14.95 GB
剪枝第 10 的权重 self_attn.v_proj 之后 - 分配内存: 12.72 GB
剪枝第 10 的权重 self_attn.v_proj 之后 - 保留内存: 14.95 GB
剪枝第 10 的权重 self_attn.o_proj 之后 - 分配内存: 12.72 GB
剪枝第 10 的权重 self_attn.o_proj 之后 - 保留内存: 14.95 GB
剪枝第 10 的权重 mlp.gate_proj 之后 - 分配内存: 12.80 GB
剪枝第 10 的权重 mlp.gate_proj 之后 - 保留内存: 14.95 GB
剪枝第 10 的权重 mlp.down_proj 之后 - 分配内存: 12.80 GB
剪枝第 10 的权重 mlp.down_proj 之后 - 保留内存: 14.95 GB
剪枝第 10 的权重 mlp.up_proj 之后 - 分配内存: 12.80 GB
剪枝第 10 的权重 mlp.up_proj 之后 - 保留内存: 14.95 GB
处理第 11 层之前 - 分配内存: 12.80 GB
处理第 11 层之前 - 保留内存: 14.95 GB
剪枝第 11 的权重 self_attn.q_proj 之后 - 分配内存: 12.72 GB
剪枝第 11 的权重 self_attn.q_proj 之后 - 保留内存: 14.95 GB
剪枝第 11 的权重 self_attn.k_proj 之后 - 分配内存: 12.72 GB
剪枝第 11 的权重 self_attn.k_proj 之后 - 保留内存: 14.95 GB
剪枝第 11 的权重 self_attn.v_proj 之后 - 分配内存: 12.72 GB
剪枝第 11 的权重 self_attn.v_proj 之后 - 保留内存: 14.95 GB
剪枝第 11 的权重 self_attn.o_proj 之后 - 分配内存: 12.72 GB
剪枝第 11 的权重 self_attn.o_proj 之后 - 保留内存: 14.95 GB
剪枝第 11 的权重 mlp.gate_proj 之后 - 分配内存: 12.80 GB
剪枝第 11 的权重 mlp.gate_proj 之后 - 保留内存: 14.95 GB
剪枝第 11 的权重 mlp.down_proj 之后 - 分配内存: 12.80 GB
剪枝第 11 的权重 mlp.down_proj 之后 - 保留内存: 14.95 GB
剪枝第 11 的权重 mlp.up_proj 之后 - 分配内存: 12.80 GB
剪枝第 11 的权重 mlp.up_proj 之后 - 保留内存: 14.95 GB
处理第 12 层之前 - 分配内存: 12.80 GB
处理第 12 层之前 - 保留内存: 14.95 GB
剪枝第 12 的权重 self_attn.q_proj 之后 - 分配内存: 12.72 GB
剪枝第 12 的权重 self_attn.q_proj 之后 - 保留内存: 14.95 GB
剪枝第 12 的权重 self_attn.k_proj 之后 - 分配内存: 12.72 GB
剪枝第 12 的权重 self_attn.k_proj 之后 - 保留内存: 14.95 GB
剪枝第 12 的权重 self_attn.v_proj 之后 - 分配内存: 12.72 GB
剪枝第 12 的权重 self_attn.v_proj 之后 - 保留内存: 14.95 GB
剪枝第 12 的权重 self_attn.o_proj 之后 - 分配内存: 12.72 GB
剪枝第 12 的权重 self_attn.o_proj 之后 - 保留内存: 14.95 GB
剪枝第 12 的权重 mlp.gate_proj 之后 - 分配内存: 12.80 GB
剪枝第 12 的权重 mlp.gate_proj 之后 - 保留内存: 14.95 GB
剪枝第 12 的权重 mlp.down_proj 之后 - 分配内存: 12.80 GB
剪枝第 12 的权重 mlp.down_proj 之后 - 保留内存: 14.95 GB
剪枝第 12 的权重 mlp.up_proj 之后 - 分配内存: 12.80 GB
剪枝第 12 的权重 mlp.up_proj 之后 - 保留内存: 14.95 GB
处理第 13 层之前 - 分配内存: 12.80 GB
处理第 13 层之前 - 保留内存: 14.95 GB
剪枝第 13 的权重 self_attn.q_proj 之后 - 分配内存: 12.72 GB
剪枝第 13 的权重 self_attn.q_proj 之后 - 保留内存: 14.95 GB
剪枝第 13 的权重 self_attn.k_proj 之后 - 分配内存: 12.72 GB
剪枝第 13 的权重 self_attn.k_proj 之后 - 保留内存: 14.95 GB
剪枝第 13 的权重 self_attn.v_proj 之后 - 分配内存: 12.72 GB
剪枝第 13 的权重 self_attn.v_proj 之后 - 保留内存: 14.95 GB
剪枝第 13 的权重 self_attn.o_proj 之后 - 分配内存: 12.72 GB
剪枝第 13 的权重 self_attn.o_proj 之后 - 保留内存: 14.95 GB
剪枝第 13 的权重 mlp.gate_proj 之后 - 分配内存: 12.80 GB
剪枝第 13 的权重 mlp.gate_proj 之后 - 保留内存: 14.95 GB
剪枝第 13 的权重 mlp.down_proj 之后 - 分配内存: 12.80 GB
剪枝第 13 的权重 mlp.down_proj 之后 - 保留内存: 14.95 GB
剪枝第 13 的权重 mlp.up_proj 之后 - 分配内存: 12.80 GB
剪枝第 13 的权重 mlp.up_proj 之后 - 保留内存: 14.95 GB
处理第 14 层之前 - 分配内存: 12.80 GB
处理第 14 层之前 - 保留内存: 14.95 GB
剪枝第 14 的权重 self_attn.q_proj 之后 - 分配内存: 12.72 GB
剪枝第 14 的权重 self_attn.q_proj 之后 - 保留内存: 14.95 GB
剪枝第 14 的权重 self_attn.k_proj 之后 - 分配内存: 12.72 GB
剪枝第 14 的权重 self_attn.k_proj 之后 - 保留内存: 14.95 GB
剪枝第 14 的权重 self_attn.v_proj 之后 - 分配内存: 12.72 GB
剪枝第 14 的权重 self_attn.v_proj 之后 - 保留内存: 14.95 GB
剪枝第 14 的权重 self_attn.o_proj 之后 - 分配内存: 12.72 GB
剪枝第 14 的权重 self_attn.o_proj 之后 - 保留内存: 14.95 GB
剪枝第 14 的权重 mlp.gate_proj 之后 - 分配内存: 12.80 GB
剪枝第 14 的权重 mlp.gate_proj 之后 - 保留内存: 14.95 GB
剪枝第 14 的权重 mlp.down_proj 之后 - 分配内存: 12.80 GB
剪枝第 14 的权重 mlp.down_proj 之后 - 保留内存: 14.95 GB
剪枝第 14 的权重 mlp.up_proj 之后 - 分配内存: 12.80 GB
剪枝第 14 的权重 mlp.up_proj 之后 - 保留内存: 14.95 GB
处理第 15 层之前 - 分配内存: 12.80 GB
处理第 15 层之前 - 保留内存: 14.95 GB
剪枝第 15 的权重 self_attn.q_proj 之后 - 分配内存: 12.72 GB
剪枝第 15 的权重 self_attn.q_proj 之后 - 保留内存: 14.95 GB
剪枝第 15 的权重 self_attn.k_proj 之后 - 分配内存: 12.72 GB
剪枝第 15 的权重 self_attn.k_proj 之后 - 保留内存: 14.95 GB
剪枝第 15 的权重 self_attn.v_proj 之后 - 分配内存: 12.72 GB
剪枝第 15 的权重 self_attn.v_proj 之后 - 保留内存: 14.95 GB
剪枝第 15 的权重 self_attn.o_proj 之后 - 分配内存: 12.72 GB
剪枝第 15 的权重 self_attn.o_proj 之后 - 保留内存: 14.95 GB
剪枝第 15 的权重 mlp.gate_proj 之后 - 分配内存: 12.80 GB
剪枝第 15 的权重 mlp.gate_proj 之后 - 保留内存: 14.95 GB
剪枝第 15 的权重 mlp.down_proj 之后 - 分配内存: 12.80 GB
剪枝第 15 的权重 mlp.down_proj 之后 - 保留内存: 14.95 GB
剪枝第 15 的权重 mlp.up_proj 之后 - 分配内存: 12.80 GB
剪枝第 15 的权重 mlp.up_proj 之后 - 保留内存: 14.95 GB
处理第 16 层之前 - 分配内存: 12.80 GB
处理第 16 层之前 - 保留内存: 14.95 GB
剪枝第 16 的权重 self_attn.q_proj 之后 - 分配内存: 12.72 GB
剪枝第 16 的权重 self_attn.q_proj 之后 - 保留内存: 14.95 GB
剪枝第 16 的权重 self_attn.k_proj 之后 - 分配内存: 12.72 GB
剪枝第 16 的权重 self_attn.k_proj 之后 - 保留内存: 14.95 GB
剪枝第 16 的权重 self_attn.v_proj 之后 - 分配内存: 12.72 GB
剪枝第 16 的权重 self_attn.v_proj 之后 - 保留内存: 14.95 GB
剪枝第 16 的权重 self_attn.o_proj 之后 - 分配内存: 12.72 GB
剪枝第 16 的权重 self_attn.o_proj 之后 - 保留内存: 14.95 GB
剪枝第 16 的权重 mlp.gate_proj 之后 - 分配内存: 12.80 GB
剪枝第 16 的权重 mlp.gate_proj 之后 - 保留内存: 14.95 GB
剪枝第 16 的权重 mlp.down_proj 之后 - 分配内存: 12.80 GB
剪枝第 16 的权重 mlp.down_proj 之后 - 保留内存: 14.95 GB
剪枝第 16 的权重 mlp.up_proj 之后 - 分配内存: 12.80 GB
剪枝第 16 的权重 mlp.up_proj 之后 - 保留内存: 14.95 GB
处理第 17 层之前 - 分配内存: 12.80 GB
处理第 17 层之前 - 保留内存: 14.95 GB
剪枝第 17 的权重 self_attn.q_proj 之后 - 分配内存: 12.72 GB
剪枝第 17 的权重 self_attn.q_proj 之后 - 保留内存: 14.95 GB
剪枝第 17 的权重 self_attn.k_proj 之后 - 分配内存: 12.72 GB
剪枝第 17 的权重 self_attn.k_proj 之后 - 保留内存: 14.95 GB
剪枝第 17 的权重 self_attn.v_proj 之后 - 分配内存: 12.72 GB
剪枝第 17 的权重 self_attn.v_proj 之后 - 保留内存: 14.95 GB
剪枝第 17 的权重 self_attn.o_proj 之后 - 分配内存: 12.72 GB
剪枝第 17 的权重 self_attn.o_proj 之后 - 保留内存: 14.95 GB
剪枝第 17 的权重 mlp.gate_proj 之后 - 分配内存: 12.80 GB
剪枝第 17 的权重 mlp.gate_proj 之后 - 保留内存: 14.95 GB
剪枝第 17 的权重 mlp.down_proj 之后 - 分配内存: 12.80 GB
剪枝第 17 的权重 mlp.down_proj 之后 - 保留内存: 14.95 GB
剪枝第 17 的权重 mlp.up_proj 之后 - 分配内存: 12.80 GB
剪枝第 17 的权重 mlp.up_proj 之后 - 保留内存: 14.95 GB
处理第 18 层之前 - 分配内存: 12.80 GB
处理第 18 层之前 - 保留内存: 14.95 GB
剪枝第 18 的权重 self_attn.q_proj 之后 - 分配内存: 12.72 GB
剪枝第 18 的权重 self_attn.q_proj 之后 - 保留内存: 14.95 GB
剪枝第 18 的权重 self_attn.k_proj 之后 - 分配内存: 12.72 GB
剪枝第 18 的权重 self_attn.k_proj 之后 - 保留内存: 14.95 GB
剪枝第 18 的权重 self_attn.v_proj 之后 - 分配内存: 12.72 GB
剪枝第 18 的权重 self_attn.v_proj 之后 - 保留内存: 14.95 GB
剪枝第 18 的权重 self_attn.o_proj 之后 - 分配内存: 12.72 GB
剪枝第 18 的权重 self_attn.o_proj 之后 - 保留内存: 14.95 GB
剪枝第 18 的权重 mlp.gate_proj 之后 - 分配内存: 12.80 GB
剪枝第 18 的权重 mlp.gate_proj 之后 - 保留内存: 14.95 GB
剪枝第 18 的权重 mlp.down_proj 之后 - 分配内存: 12.80 GB
剪枝第 18 的权重 mlp.down_proj 之后 - 保留内存: 14.95 GB
剪枝第 18 的权重 mlp.up_proj 之后 - 分配内存: 12.80 GB
剪枝第 18 的权重 mlp.up_proj 之后 - 保留内存: 14.95 GB
处理第 19 层之前 - 分配内存: 12.80 GB
处理第 19 层之前 - 保留内存: 14.95 GB
剪枝第 19 的权重 self_attn.q_proj 之后 - 分配内存: 12.72 GB
剪枝第 19 的权重 self_attn.q_proj 之后 - 保留内存: 14.95 GB
剪枝第 19 的权重 self_attn.k_proj 之后 - 分配内存: 12.72 GB
剪枝第 19 的权重 self_attn.k_proj 之后 - 保留内存: 14.95 GB
剪枝第 19 的权重 self_attn.v_proj 之后 - 分配内存: 12.72 GB
剪枝第 19 的权重 self_attn.v_proj 之后 - 保留内存: 14.95 GB
剪枝第 19 的权重 self_attn.o_proj 之后 - 分配内存: 12.72 GB
剪枝第 19 的权重 self_attn.o_proj 之后 - 保留内存: 14.95 GB
剪枝第 19 的权重 mlp.gate_proj 之后 - 分配内存: 12.80 GB
剪枝第 19 的权重 mlp.gate_proj 之后 - 保留内存: 14.95 GB
剪枝第 19 的权重 mlp.down_proj 之后 - 分配内存: 12.80 GB
剪枝第 19 的权重 mlp.down_proj 之后 - 保留内存: 14.95 GB
剪枝第 19 的权重 mlp.up_proj 之后 - 分配内存: 12.80 GB
剪枝第 19 的权重 mlp.up_proj 之后 - 保留内存: 14.95 GB
处理第 20 层之前 - 分配内存: 12.80 GB
处理第 20 层之前 - 保留内存: 14.95 GB
剪枝第 20 的权重 self_attn.q_proj 之后 - 分配内存: 12.72 GB
剪枝第 20 的权重 self_attn.q_proj 之后 - 保留内存: 14.95 GB
剪枝第 20 的权重 self_attn.k_proj 之后 - 分配内存: 12.72 GB
剪枝第 20 的权重 self_attn.k_proj 之后 - 保留内存: 14.95 GB
剪枝第 20 的权重 self_attn.v_proj 之后 - 分配内存: 12.72 GB
剪枝第 20 的权重 self_attn.v_proj 之后 - 保留内存: 14.95 GB
剪枝第 20 的权重 self_attn.o_proj 之后 - 分配内存: 12.72 GB
剪枝第 20 的权重 self_attn.o_proj 之后 - 保留内存: 14.95 GB
剪枝第 20 的权重 mlp.gate_proj 之后 - 分配内存: 12.80 GB
剪枝第 20 的权重 mlp.gate_proj 之后 - 保留内存: 14.95 GB
剪枝第 20 的权重 mlp.down_proj 之后 - 分配内存: 12.80 GB
剪枝第 20 的权重 mlp.down_proj 之后 - 保留内存: 14.95 GB
剪枝第 20 的权重 mlp.up_proj 之后 - 分配内存: 12.80 GB
剪枝第 20 的权重 mlp.up_proj 之后 - 保留内存: 14.95 GB
处理第 21 层之前 - 分配内存: 12.80 GB
处理第 21 层之前 - 保留内存: 14.95 GB
剪枝第 21 的权重 self_attn.q_proj 之后 - 分配内存: 12.72 GB
剪枝第 21 的权重 self_attn.q_proj 之后 - 保留内存: 14.95 GB
剪枝第 21 的权重 self_attn.k_proj 之后 - 分配内存: 12.72 GB
剪枝第 21 的权重 self_attn.k_proj 之后 - 保留内存: 14.95 GB
剪枝第 21 的权重 self_attn.v_proj 之后 - 分配内存: 12.72 GB
剪枝第 21 的权重 self_attn.v_proj 之后 - 保留内存: 14.95 GB
剪枝第 21 的权重 self_attn.o_proj 之后 - 分配内存: 12.72 GB
剪枝第 21 的权重 self_attn.o_proj 之后 - 保留内存: 14.95 GB
剪枝第 21 的权重 mlp.gate_proj 之后 - 分配内存: 12.80 GB
剪枝第 21 的权重 mlp.gate_proj 之后 - 保留内存: 14.95 GB
剪枝第 21 的权重 mlp.down_proj 之后 - 分配内存: 12.80 GB
剪枝第 21 的权重 mlp.down_proj 之后 - 保留内存: 14.95 GB
剪枝第 21 的权重 mlp.up_proj 之后 - 分配内存: 12.80 GB
剪枝第 21 的权重 mlp.up_proj 之后 - 保留内存: 14.95 GB
处理第 22 层之前 - 分配内存: 12.80 GB
处理第 22 层之前 - 保留内存: 14.95 GB
剪枝第 22 的权重 self_attn.q_proj 之后 - 分配内存: 12.72 GB
剪枝第 22 的权重 self_attn.q_proj 之后 - 保留内存: 14.95 GB
剪枝第 22 的权重 self_attn.k_proj 之后 - 分配内存: 12.72 GB
剪枝第 22 的权重 self_attn.k_proj 之后 - 保留内存: 14.95 GB
剪枝第 22 的权重 self_attn.v_proj 之后 - 分配内存: 12.72 GB
剪枝第 22 的权重 self_attn.v_proj 之后 - 保留内存: 14.95 GB
剪枝第 22 的权重 self_attn.o_proj 之后 - 分配内存: 12.72 GB
剪枝第 22 的权重 self_attn.o_proj 之后 - 保留内存: 14.95 GB
剪枝第 22 的权重 mlp.gate_proj 之后 - 分配内存: 12.80 GB
剪枝第 22 的权重 mlp.gate_proj 之后 - 保留内存: 14.95 GB
剪枝第 22 的权重 mlp.down_proj 之后 - 分配内存: 12.80 GB
剪枝第 22 的权重 mlp.down_proj 之后 - 保留内存: 14.95 GB
剪枝第 22 的权重 mlp.up_proj 之后 - 分配内存: 12.80 GB
剪枝第 22 的权重 mlp.up_proj 之后 - 保留内存: 14.95 GB
处理第 23 层之前 - 分配内存: 12.80 GB
处理第 23 层之前 - 保留内存: 14.95 GB
剪枝第 23 的权重 self_attn.q_proj 之后 - 分配内存: 12.72 GB
剪枝第 23 的权重 self_attn.q_proj 之后 - 保留内存: 14.95 GB
剪枝第 23 的权重 self_attn.k_proj 之后 - 分配内存: 12.72 GB
剪枝第 23 的权重 self_attn.k_proj 之后 - 保留内存: 14.95 GB
剪枝第 23 的权重 self_attn.v_proj 之后 - 分配内存: 12.72 GB
剪枝第 23 的权重 self_attn.v_proj 之后 - 保留内存: 14.95 GB
剪枝第 23 的权重 self_attn.o_proj 之后 - 分配内存: 12.72 GB
剪枝第 23 的权重 self_attn.o_proj 之后 - 保留内存: 14.95 GB
剪枝第 23 的权重 mlp.gate_proj 之后 - 分配内存: 12.80 GB
剪枝第 23 的权重 mlp.gate_proj 之后 - 保留内存: 14.95 GB
剪枝第 23 的权重 mlp.down_proj 之后 - 分配内存: 12.80 GB
剪枝第 23 的权重 mlp.down_proj 之后 - 保留内存: 14.95 GB
剪枝第 23 的权重 mlp.up_proj 之后 - 分配内存: 12.80 GB
剪枝第 23 的权重 mlp.up_proj 之后 - 保留内存: 14.95 GB
处理第 24 层之前 - 分配内存: 12.80 GB
处理第 24 层之前 - 保留内存: 14.95 GB
剪枝第 24 的权重 self_attn.q_proj 之后 - 分配内存: 12.72 GB
剪枝第 24 的权重 self_attn.q_proj 之后 - 保留内存: 14.95 GB
剪枝第 24 的权重 self_attn.k_proj 之后 - 分配内存: 12.72 GB
剪枝第 24 的权重 self_attn.k_proj 之后 - 保留内存: 14.95 GB
剪枝第 24 的权重 self_attn.v_proj 之后 - 分配内存: 12.72 GB
剪枝第 24 的权重 self_attn.v_proj 之后 - 保留内存: 14.95 GB
剪枝第 24 的权重 self_attn.o_proj 之后 - 分配内存: 12.72 GB
剪枝第 24 的权重 self_attn.o_proj 之后 - 保留内存: 14.95 GB
剪枝第 24 的权重 mlp.gate_proj 之后 - 分配内存: 12.80 GB
剪枝第 24 的权重 mlp.gate_proj 之后 - 保留内存: 14.95 GB
剪枝第 24 的权重 mlp.down_proj 之后 - 分配内存: 12.80 GB
剪枝第 24 的权重 mlp.down_proj 之后 - 保留内存: 14.95 GB
剪枝第 24 的权重 mlp.up_proj 之后 - 分配内存: 12.80 GB
剪枝第 24 的权重 mlp.up_proj 之后 - 保留内存: 14.95 GB
处理第 25 层之前 - 分配内存: 12.80 GB
处理第 25 层之前 - 保留内存: 14.95 GB
剪枝第 25 的权重 self_attn.q_proj 之后 - 分配内存: 12.72 GB
剪枝第 25 的权重 self_attn.q_proj 之后 - 保留内存: 14.95 GB
剪枝第 25 的权重 self_attn.k_proj 之后 - 分配内存: 12.72 GB
剪枝第 25 的权重 self_attn.k_proj 之后 - 保留内存: 14.95 GB
剪枝第 25 的权重 self_attn.v_proj 之后 - 分配内存: 12.72 GB
剪枝第 25 的权重 self_attn.v_proj 之后 - 保留内存: 14.95 GB
剪枝第 25 的权重 self_attn.o_proj 之后 - 分配内存: 12.72 GB
剪枝第 25 的权重 self_attn.o_proj 之后 - 保留内存: 14.95 GB
剪枝第 25 的权重 mlp.gate_proj 之后 - 分配内存: 12.80 GB
剪枝第 25 的权重 mlp.gate_proj 之后 - 保留内存: 14.95 GB
剪枝第 25 的权重 mlp.down_proj 之后 - 分配内存: 12.80 GB
剪枝第 25 的权重 mlp.down_proj 之后 - 保留内存: 14.95 GB
剪枝第 25 的权重 mlp.up_proj 之后 - 分配内存: 12.80 GB
剪枝第 25 的权重 mlp.up_proj 之后 - 保留内存: 14.95 GB
处理第 26 层之前 - 分配内存: 12.80 GB
处理第 26 层之前 - 保留内存: 14.95 GB
剪枝第 26 的权重 self_attn.q_proj 之后 - 分配内存: 12.72 GB
剪枝第 26 的权重 self_attn.q_proj 之后 - 保留内存: 14.95 GB
剪枝第 26 的权重 self_attn.k_proj 之后 - 分配内存: 12.72 GB
剪枝第 26 的权重 self_attn.k_proj 之后 - 保留内存: 14.95 GB
剪枝第 26 的权重 self_attn.v_proj 之后 - 分配内存: 12.72 GB
剪枝第 26 的权重 self_attn.v_proj 之后 - 保留内存: 14.95 GB
剪枝第 26 的权重 self_attn.o_proj 之后 - 分配内存: 12.72 GB
剪枝第 26 的权重 self_attn.o_proj 之后 - 保留内存: 14.95 GB
剪枝第 26 的权重 mlp.gate_proj 之后 - 分配内存: 12.80 GB
剪枝第 26 的权重 mlp.gate_proj 之后 - 保留内存: 14.95 GB
剪枝第 26 的权重 mlp.down_proj 之后 - 分配内存: 12.80 GB
剪枝第 26 的权重 mlp.down_proj 之后 - 保留内存: 14.95 GB
剪枝第 26 的权重 mlp.up_proj 之后 - 分配内存: 12.80 GB
剪枝第 26 的权重 mlp.up_proj 之后 - 保留内存: 14.95 GB
处理第 27 层之前 - 分配内存: 12.80 GB
处理第 27 层之前 - 保留内存: 14.95 GB
剪枝第 27 的权重 self_attn.q_proj 之后 - 分配内存: 12.72 GB
剪枝第 27 的权重 self_attn.q_proj 之后 - 保留内存: 14.95 GB
剪枝第 27 的权重 self_attn.k_proj 之后 - 分配内存: 12.72 GB
剪枝第 27 的权重 self_attn.k_proj 之后 - 保留内存: 14.95 GB
剪枝第 27 的权重 self_attn.v_proj 之后 - 分配内存: 12.72 GB
剪枝第 27 的权重 self_attn.v_proj 之后 - 保留内存: 14.95 GB
剪枝第 27 的权重 self_attn.o_proj 之后 - 分配内存: 12.72 GB
剪枝第 27 的权重 self_attn.o_proj 之后 - 保留内存: 14.95 GB
剪枝第 27 的权重 mlp.gate_proj 之后 - 分配内存: 12.80 GB
剪枝第 27 的权重 mlp.gate_proj 之后 - 保留内存: 14.95 GB
剪枝第 27 的权重 mlp.down_proj 之后 - 分配内存: 12.80 GB
剪枝第 27 的权重 mlp.down_proj 之后 - 保留内存: 14.95 GB
剪枝第 27 的权重 mlp.up_proj 之后 - 分配内存: 12.80 GB
剪枝第 27 的权重 mlp.up_proj 之后 - 保留内存: 14.95 GB
处理第 28 层之前 - 分配内存: 12.80 GB
处理第 28 层之前 - 保留内存: 14.95 GB
剪枝第 28 的权重 self_attn.q_proj 之后 - 分配内存: 12.72 GB
剪枝第 28 的权重 self_attn.q_proj 之后 - 保留内存: 14.95 GB
剪枝第 28 的权重 self_attn.k_proj 之后 - 分配内存: 12.72 GB
剪枝第 28 的权重 self_attn.k_proj 之后 - 保留内存: 14.95 GB
剪枝第 28 的权重 self_attn.v_proj 之后 - 分配内存: 12.72 GB
剪枝第 28 的权重 self_attn.v_proj 之后 - 保留内存: 14.95 GB
剪枝第 28 的权重 self_attn.o_proj 之后 - 分配内存: 12.72 GB
剪枝第 28 的权重 self_attn.o_proj 之后 - 保留内存: 14.95 GB
剪枝第 28 的权重 mlp.gate_proj 之后 - 分配内存: 12.80 GB
剪枝第 28 的权重 mlp.gate_proj 之后 - 保留内存: 14.95 GB
剪枝第 28 的权重 mlp.down_proj 之后 - 分配内存: 12.80 GB
剪枝第 28 的权重 mlp.down_proj 之后 - 保留内存: 14.95 GB
剪枝第 28 的权重 mlp.up_proj 之后 - 分配内存: 12.80 GB
剪枝第 28 的权重 mlp.up_proj 之后 - 保留内存: 14.95 GB
处理第 29 层之前 - 分配内存: 12.80 GB
处理第 29 层之前 - 保留内存: 14.95 GB
剪枝第 29 的权重 self_attn.q_proj 之后 - 分配内存: 12.72 GB
剪枝第 29 的权重 self_attn.q_proj 之后 - 保留内存: 14.95 GB
剪枝第 29 的权重 self_attn.k_proj 之后 - 分配内存: 12.72 GB
剪枝第 29 的权重 self_attn.k_proj 之后 - 保留内存: 14.95 GB
剪枝第 29 的权重 self_attn.v_proj 之后 - 分配内存: 12.72 GB
剪枝第 29 的权重 self_attn.v_proj 之后 - 保留内存: 14.95 GB
剪枝第 29 的权重 self_attn.o_proj 之后 - 分配内存: 12.72 GB
剪枝第 29 的权重 self_attn.o_proj 之后 - 保留内存: 14.95 GB
剪枝第 29 的权重 mlp.gate_proj 之后 - 分配内存: 12.80 GB
剪枝第 29 的权重 mlp.gate_proj 之后 - 保留内存: 14.95 GB
剪枝第 29 的权重 mlp.down_proj 之后 - 分配内存: 12.80 GB
剪枝第 29 的权重 mlp.down_proj 之后 - 保留内存: 14.95 GB
剪枝第 29 的权重 mlp.up_proj 之后 - 分配内存: 12.80 GB
剪枝第 29 的权重 mlp.up_proj 之后 - 保留内存: 14.95 GB
处理第 30 层之前 - 分配内存: 12.80 GB
处理第 30 层之前 - 保留内存: 14.95 GB
剪枝第 30 的权重 self_attn.q_proj 之后 - 分配内存: 12.72 GB
剪枝第 30 的权重 self_attn.q_proj 之后 - 保留内存: 14.95 GB
剪枝第 30 的权重 self_attn.k_proj 之后 - 分配内存: 12.72 GB
剪枝第 30 的权重 self_attn.k_proj 之后 - 保留内存: 14.95 GB
剪枝第 30 的权重 self_attn.v_proj 之后 - 分配内存: 12.72 GB
剪枝第 30 的权重 self_attn.v_proj 之后 - 保留内存: 14.95 GB
剪枝第 30 的权重 self_attn.o_proj 之后 - 分配内存: 12.72 GB
剪枝第 30 的权重 self_attn.o_proj 之后 - 保留内存: 14.95 GB
剪枝第 30 的权重 mlp.gate_proj 之后 - 分配内存: 12.80 GB
剪枝第 30 的权重 mlp.gate_proj 之后 - 保留内存: 14.95 GB
剪枝第 30 的权重 mlp.down_proj 之后 - 分配内存: 12.80 GB
剪枝第 30 的权重 mlp.down_proj 之后 - 保留内存: 14.95 GB
剪枝第 30 的权重 mlp.up_proj 之后 - 分配内存: 12.80 GB
剪枝第 30 的权重 mlp.up_proj 之后 - 保留内存: 14.95 GB
处理第 31 层之前 - 分配内存: 12.80 GB
处理第 31 层之前 - 保留内存: 14.95 GB
剪枝第 31 的权重 self_attn.q_proj 之后 - 分配内存: 12.72 GB
剪枝第 31 的权重 self_attn.q_proj 之后 - 保留内存: 14.95 GB
剪枝第 31 的权重 self_attn.k_proj 之后 - 分配内存: 12.72 GB
剪枝第 31 的权重 self_attn.k_proj 之后 - 保留内存: 14.95 GB
剪枝第 31 的权重 self_attn.v_proj 之后 - 分配内存: 12.72 GB
剪枝第 31 的权重 self_attn.v_proj 之后 - 保留内存: 14.95 GB
剪枝第 31 的权重 self_attn.o_proj 之后 - 分配内存: 12.72 GB
剪枝第 31 的权重 self_attn.o_proj 之后 - 保留内存: 14.95 GB
剪枝第 31 的权重 mlp.gate_proj 之后 - 分配内存: 12.80 GB
剪枝第 31 的权重 mlp.gate_proj 之后 - 保留内存: 14.95 GB
剪枝第 31 的权重 mlp.down_proj 之后 - 分配内存: 12.80 GB
剪枝第 31 的权重 mlp.down_proj 之后 - 保留内存: 14.95 GB
剪枝第 31 的权重 mlp.up_proj 之后 - 分配内存: 12.80 GB
剪枝第 31 的权重 mlp.up_proj 之后 - 保留内存: 14.95 GB
剪枝所有层之后 - 分配内存: 12.80 GB
剪枝所有层之后 - 保留内存: 14.95 GB
******************************
layer 0 sparsity 0.500654
layer 1 sparsity 0.500707
layer 2 sparsity 0.500744
layer 3 sparsity 0.501227
layer 4 sparsity 0.501123
layer 5 sparsity 0.501560
layer 6 sparsity 0.500812
layer 7 sparsity 0.501593
layer 8 sparsity 0.500865
layer 9 sparsity 0.501034
layer 10 sparsity 0.500843
layer 11 sparsity 0.501353
layer 12 sparsity 0.501236
layer 13 sparsity 0.501154
layer 14 sparsity 0.501012
layer 15 sparsity 0.501432
layer 16 sparsity 0.501073
layer 17 sparsity 0.500963
layer 18 sparsity 0.501161
layer 19 sparsity 0.500545
layer 20 sparsity 0.500673
layer 21 sparsity 0.501270
layer 22 sparsity 0.500906
layer 23 sparsity 0.500999
layer 24 sparsity 0.500991
layer 25 sparsity 0.501228
layer 26 sparsity 0.500776
layer 27 sparsity 0.500648
layer 28 sparsity 0.501165
layer 29 sparsity 0.501206
layer 30 sparsity 0.501136
layer 31 sparsity 0.500962
sparsity sanity check 0.5010
******************************
evaluating on wikitext2
nsamples 83
sample 0
sample 50
wikitext perplexity 14.89717960357666
5.3.4 输出文件结果
method actual_sparsity ppl_test
magnitude 0.5010 14.8972
5.4 Wanda 方法实例
5.4.1 代码实例
在 prune.py
中prune_wanda
函数中添加print_memory_usage
查看显存函数
def prune_wanda(args, model, tokenizer, device=torch.device("cuda:0"), prune_n=0, prune_m=0):use_cache = model.config.use_cache # 保存模型的use_cache配置model.config.use_cache = False # 关闭缓存以节省显存print("loading calibration data")print_memory_usage("加载数据前的显存使用情况") # 打印加载数据前的显存使用情况dataloader, _ = get_loaders("c4", nsamples=args.nsamples, seed=args.seed, seqlen=model.seqlen,tokenizer=tokenizer) # 获取数据加载器print_memory_usage("加载数据后的显存使用情况") # 打印加载数据后的显存使用情况with torch.no_grad(): # 禁用梯度计算print_memory_usage("准备校准输入前的显存使用情况") # 打印准备校准输入前的显存使用情况inps, outs, attention_mask, position_ids = prepare_calibration_input(model, dataloader, device) # 准备校准数据print_memory_usage("准备校准输入后的显存使用情况") # 打印准备校准输入后的显存使用情况layers = model.model.layers # 获取模型的所有层for i in range(len(layers)): # 遍历所有层layer = layers[i] # 获取第i层subset = find_layers(layer) # 获取该层的子层if f"model.layers.{i}" in model.hf_device_map: # 如果层i在设备映射中dev = model.hf_device_map[f"model.layers.{i}"] # 获取该层所在设备print(f"layer {i} device {dev}")inps, outs, attention_mask, position_ids = inps.to(dev), outs.to(dev), attention_mask.to(dev), position_ids.to(dev) # 将数据移动到正确的设备wrapped_layers = {} # 创建一个空字典来存储包装的层for name in subset: # 遍历每个子层wrapped_layers[name] = WrappedGPT(subset[name]) # 包装子层def add_batch(name):def tmp(_, inp, out):wrapped_layers[name].add_batch(inp[0].data, out.data) # 收集数据return tmphandles = []for name in wrapped_layers: # 为每个包装的层注册前向钩子handles.append(subset[name].register_forward_hook(add_batch(name)))print_memory_usage(f"第 {i} 层前向传播前") # 打印前向传播前的显存使用情况for j in range(args.nsamples): # 对每个样本执行前向传播with torch.no_grad(): # 禁用梯度计算outs[j] = layer(inps[j].unsqueeze(0), attention_mask=attention_mask, position_ids=position_ids)[0]print_memory_usage(f"第 {i} 层前向传播后") # 打印前向传播后的显存使用情况for h in handles: # 移除前向钩子h.remove()for name in subset: # 对每个子层进行剪枝print(f"pruning layer {i} name {name}")W_metric = torch.abs(subset[name].weight.data) * torch.sqrt(wrapped_layers[name].scaler_row.reshape((1, -1))) # 计算权重度量W_mask = (torch.zeros_like(W_metric) == 1) ## 初始化一个全False的掩码if prune_n != 0:# structured n:m sparsity # 结构化的n:m稀疏性for ii in range(W_metric.shape[1]): # 遍历每个权重列if ii % prune_m == 0: # 对于每m列的开始位置tmp = W_metric[:, ii:(ii + prune_m)].float() # 计算当前列的度量W_mask.scatter_(1, ii + torch.topk(tmp, prune_n, dim=1, largest=False)[1], True) # 更新掩码else:sort_res = torch.sort(W_metric, dim=-1, stable=True) # 对度量进行排序if args.use_variant:# wanda variant # Wanda变体tmp_metric = torch.cumsum(sort_res[0], dim=1) # 计算累积度量sum_before = W_metric.sum(dim=1) # 计算剪枝前的总和alpha = 0.4alpha_hist = [0., 0.8]W_mask, cur_sparsity = return_given_alpha(alpha, sort_res, W_metric, tmp_metric,sum_before) # 根据alpha计算掩码和稀疏度while (torch.abs(cur_sparsity - args.sparsity_ratio) > 0.001) and (alpha_hist[1] - alpha_hist[0] >= 0.001):if cur_sparsity > args.sparsity_ratio: # 如果当前稀疏度大于目标稀疏度alpha_new = (alpha + alpha_hist[0]) / 2.0alpha_hist[1] = alphaelse:alpha_new = (alpha + alpha_hist[1]) / 2.0alpha_hist[0] = alphaalpha = alpha_newW_mask, cur_sparsity = return_given_alpha(alpha, sort_res, W_metric, tmp_metric,sum_before) # 重新计算掩码和稀疏度print(f"alpha found {alpha} sparsity {cur_sparsity:.6f}") # 打印找到的alpha值和稀疏度else:# unstructured pruning # 无结构剪枝indices = sort_res[1][:, :int(W_metric.shape[1] * args.sparsity_ratio)] # 计算需要剪枝的权重索引W_mask.scatter_(1, indices, True) # 更新掩码subset[name].weight.data[W_mask] = 0 ## 将权重设为零print_memory_usage(f"第 {i} 层剪枝后显存使用情况") # 打印剪枝后的显存使用情况for j in range(args.nsamples): # 对每个样本执行前向传播以验证剪枝效果with torch.no_grad(): # 禁用梯度计算outs[j] = layer(inps[j].unsqueeze(0), attention_mask=attention_mask, position_ids=position_ids)[0]inps, outs = outs, inps # 交换输入和输出以进行下一轮处理model.config.use_cache = use_cache # 恢复模型的use_cache配置torch.cuda.empty_cache() # 清空显存缓存print_memory_usage("清理缓存后的显存使用情况") # 打印清理缓存后的显存使用情况
5.4.2 实验运行
python main.py --model meta-llama/Llama-2-7b-hf --prune_method wanda --sparsity_ratio 0.5 --sparsity_type unstructured --save out/llama2_7b/unstructured/wanda/
详细解释:
- 加载
meta-llama/Llama-2-7b-hf
模型。 - 使用
wanda
剪枝方法对模型进行剪枝。 - 剪枝的稀疏率设为50%,即模型的50%参数会被剪掉。
- 剪枝类型是不结构化的稀疏(unstructured),参数可以任意位置剪枝。
- 最后,将剪枝后的模型保存到指定的目录
out/llama2_7b/unstructured/wanda/
5.4.3 实验结果
use device cuda:0
pruning starts
loading calibration data
Before data loading - Allocated memory: 12.68 GB
Before data loading - Reserved memory: 12.69 GB
After data loading - Allocated memory: 12.68 GB
After data loading - Reserved memory: 12.69 GB
Before calibration input preparation - Allocated memory: 12.68 GB
Before calibration input preparation - Reserved memory: 12.69 GB
After calibration input preparation - Allocated memory: 20.71 GB
After calibration input preparation - Reserved memory: 20.92 GB
Before forward pass of layer 0 - Allocated memory: 20.71 GB
Before forward pass of layer 0 - Reserved memory: 20.92 GB
After forward pass of layer 0 - Allocated memory: 20.71 GB
After forward pass of layer 0 - Reserved memory: 25.02 GB
pruning layer 0 name self_attn.q_proj
pruning layer 0 name self_attn.k_proj
pruning layer 0 name self_attn.v_proj
pruning layer 0 name self_attn.o_proj
pruning layer 0 name mlp.gate_proj
pruning layer 0 name mlp.down_proj
pruning layer 0 name mlp.up_proj
After pruning layer 0 - Allocated memory: 21.42 GB
After pruning layer 0 - Reserved memory: 25.02 GB
Before forward pass of layer 1 - Allocated memory: 21.42 GB
Before forward pass of layer 1 - Reserved memory: 27.02 GB
After forward pass of layer 1 - Allocated memory: 21.42 GB
After forward pass of layer 1 - Reserved memory: 27.02 GB
pruning layer 1 name self_attn.q_proj
pruning layer 1 name self_attn.k_proj
pruning layer 1 name self_attn.v_proj
pruning layer 1 name self_attn.o_proj
pruning layer 1 name mlp.gate_proj
pruning layer 1 name mlp.down_proj
pruning layer 1 name mlp.up_proj
After pruning layer 1 - Allocated memory: 21.42 GB
After pruning layer 1 - Reserved memory: 27.02 GB
Before forward pass of layer 2 - Allocated memory: 21.42 GB
Before forward pass of layer 2 - Reserved memory: 27.02 GB
After forward pass of layer 2 - Allocated memory: 21.42 GB
After forward pass of layer 2 - Reserved memory: 27.02 GB
pruning layer 2 name self_attn.q_proj
pruning layer 2 name self_attn.k_proj
pruning layer 2 name self_attn.v_proj
pruning layer 2 name self_attn.o_proj
pruning layer 2 name mlp.gate_proj
pruning layer 2 name mlp.down_proj
pruning layer 2 name mlp.up_proj
After pruning layer 2 - Allocated memory: 21.42 GB
After pruning layer 2 - Reserved memory: 27.02 GB
Before forward pass of layer 3 - Allocated memory: 21.42 GB
Before forward pass of layer 3 - Reserved memory: 27.02 GB
After forward pass of layer 3 - Allocated memory: 21.42 GB
After forward pass of layer 3 - Reserved memory: 27.02 GB
pruning layer 3 name self_attn.q_proj
pruning layer 3 name self_attn.k_proj
pruning layer 3 name self_attn.v_proj
pruning layer 3 name self_attn.o_proj
pruning layer 3 name mlp.gate_proj
pruning layer 3 name mlp.down_proj
pruning layer 3 name mlp.up_proj
After pruning layer 3 - Allocated memory: 21.42 GB
After pruning layer 3 - Reserved memory: 27.02 GB
Before forward pass of layer 4 - Allocated memory: 21.42 GB
Before forward pass of layer 4 - Reserved memory: 27.02 GB
After forward pass of layer 4 - Allocated memory: 21.42 GB
After forward pass of layer 4 - Reserved memory: 27.02 GB
pruning layer 4 name self_attn.q_proj
pruning layer 4 name self_attn.k_proj
pruning layer 4 name self_attn.v_proj
pruning layer 4 name self_attn.o_proj
pruning layer 4 name mlp.gate_proj
pruning layer 4 name mlp.down_proj
pruning layer 4 name mlp.up_proj
After pruning layer 4 - Allocated memory: 21.42 GB
After pruning layer 4 - Reserved memory: 27.02 GB
Before forward pass of layer 5 - Allocated memory: 21.42 GB
Before forward pass of layer 5 - Reserved memory: 27.02 GB
After forward pass of layer 5 - Allocated memory: 21.42 GB
After forward pass of layer 5 - Reserved memory: 27.02 GB
pruning layer 5 name self_attn.q_proj
pruning layer 5 name self_attn.k_proj
pruning layer 5 name self_attn.v_proj
pruning layer 5 name self_attn.o_proj
pruning layer 5 name mlp.gate_proj
pruning layer 5 name mlp.down_proj
pruning layer 5 name mlp.up_proj
After pruning layer 5 - Allocated memory: 21.42 GB
After pruning layer 5 - Reserved memory: 27.02 GB
Before forward pass of layer 6 - Allocated memory: 21.42 GB
Before forward pass of layer 6 - Reserved memory: 27.02 GB
After forward pass of layer 6 - Allocated memory: 21.42 GB
After forward pass of layer 6 - Reserved memory: 27.02 GB
pruning layer 6 name self_attn.q_proj
pruning layer 6 name self_attn.k_proj
pruning layer 6 name self_attn.v_proj
pruning layer 6 name self_attn.o_proj
pruning layer 6 name mlp.gate_proj
pruning layer 6 name mlp.down_proj
pruning layer 6 name mlp.up_proj
After pruning layer 6 - Allocated memory: 21.42 GB
After pruning layer 6 - Reserved memory: 27.02 GB
Before forward pass of layer 7 - Allocated memory: 21.42 GB
Before forward pass of layer 7 - Reserved memory: 27.02 GB
After forward pass of layer 7 - Allocated memory: 21.42 GB
After forward pass of layer 7 - Reserved memory: 27.02 GB
pruning layer 7 name self_attn.q_proj
pruning layer 7 name self_attn.k_proj
pruning layer 7 name self_attn.v_proj
pruning layer 7 name self_attn.o_proj
pruning layer 7 name mlp.gate_proj
pruning layer 7 name mlp.down_proj
pruning layer 7 name mlp.up_proj
After pruning layer 7 - Allocated memory: 21.42 GB
After pruning layer 7 - Reserved memory: 27.02 GB
Before forward pass of layer 8 - Allocated memory: 21.42 GB
Before forward pass of layer 8 - Reserved memory: 27.02 GB
After forward pass of layer 8 - Allocated memory: 21.42 GB
After forward pass of layer 8 - Reserved memory: 27.02 GB
pruning layer 8 name self_attn.q_proj
pruning layer 8 name self_attn.k_proj
pruning layer 8 name self_attn.v_proj
pruning layer 8 name self_attn.o_proj
pruning layer 8 name mlp.gate_proj
pruning layer 8 name mlp.down_proj
pruning layer 8 name mlp.up_proj
After pruning layer 8 - Allocated memory: 21.42 GB
After pruning layer 8 - Reserved memory: 27.02 GB
Before forward pass of layer 9 - Allocated memory: 21.42 GB
Before forward pass of layer 9 - Reserved memory: 27.02 GB
After forward pass of layer 9 - Allocated memory: 21.42 GB
After forward pass of layer 9 - Reserved memory: 27.02 GB
pruning layer 9 name self_attn.q_proj
pruning layer 9 name self_attn.k_proj
pruning layer 9 name self_attn.v_proj
pruning layer 9 name self_attn.o_proj
pruning layer 9 name mlp.gate_proj
pruning layer 9 name mlp.down_proj
pruning layer 9 name mlp.up_proj
After pruning layer 9 - Allocated memory: 21.42 GB
After pruning layer 9 - Reserved memory: 27.02 GB
Before forward pass of layer 10 - Allocated memory: 21.42 GB
Before forward pass of layer 10 - Reserved memory: 27.02 GB
After forward pass of layer 10 - Allocated memory: 21.42 GB
After forward pass of layer 10 - Reserved memory: 27.02 GB
pruning layer 10 name self_attn.q_proj
pruning layer 10 name self_attn.k_proj
pruning layer 10 name self_attn.v_proj
pruning layer 10 name self_attn.o_proj
pruning layer 10 name mlp.gate_proj
pruning layer 10 name mlp.down_proj
pruning layer 10 name mlp.up_proj
After pruning layer 10 - Allocated memory: 21.42 GB
After pruning layer 10 - Reserved memory: 27.02 GB
Before forward pass of layer 11 - Allocated memory: 21.42 GB
Before forward pass of layer 11 - Reserved memory: 27.02 GB
After forward pass of layer 11 - Allocated memory: 21.42 GB
After forward pass of layer 11 - Reserved memory: 27.02 GB
pruning layer 11 name self_attn.q_proj
pruning layer 11 name self_attn.k_proj
pruning layer 11 name self_attn.v_proj
pruning layer 11 name self_attn.o_proj
pruning layer 11 name mlp.gate_proj
pruning layer 11 name mlp.down_proj
pruning layer 11 name mlp.up_proj
After pruning layer 11 - Allocated memory: 21.42 GB
After pruning layer 11 - Reserved memory: 27.02 GB
Before forward pass of layer 12 - Allocated memory: 21.42 GB
Before forward pass of layer 12 - Reserved memory: 27.02 GB
After forward pass of layer 12 - Allocated memory: 21.42 GB
After forward pass of layer 12 - Reserved memory: 27.02 GB
pruning layer 12 name self_attn.q_proj
pruning layer 12 name self_attn.k_proj
pruning layer 12 name self_attn.v_proj
pruning layer 12 name self_attn.o_proj
pruning layer 12 name mlp.gate_proj
pruning layer 12 name mlp.down_proj
pruning layer 12 name mlp.up_proj
After pruning layer 12 - Allocated memory: 21.42 GB
After pruning layer 12 - Reserved memory: 27.02 GB
Before forward pass of layer 13 - Allocated memory: 21.42 GB
Before forward pass of layer 13 - Reserved memory: 27.02 GB
After forward pass of layer 13 - Allocated memory: 21.42 GB
After forward pass of layer 13 - Reserved memory: 27.02 GB
pruning layer 13 name self_attn.q_proj
pruning layer 13 name self_attn.k_proj
pruning layer 13 name self_attn.v_proj
pruning layer 13 name self_attn.o_proj
pruning layer 13 name mlp.gate_proj
pruning layer 13 name mlp.down_proj
pruning layer 13 name mlp.up_proj
After pruning layer 13 - Allocated memory: 21.42 GB
After pruning layer 13 - Reserved memory: 27.02 GB
Before forward pass of layer 14 - Allocated memory: 21.42 GB
Before forward pass of layer 14 - Reserved memory: 27.02 GB
After forward pass of layer 14 - Allocated memory: 21.42 GB
After forward pass of layer 14 - Reserved memory: 27.02 GB
pruning layer 14 name self_attn.q_proj
pruning layer 14 name self_attn.k_proj
pruning layer 14 name self_attn.v_proj
pruning layer 14 name self_attn.o_proj
pruning layer 14 name mlp.gate_proj
pruning layer 14 name mlp.down_proj
pruning layer 14 name mlp.up_proj
After pruning layer 14 - Allocated memory: 21.42 GB
After pruning layer 14 - Reserved memory: 27.02 GB
Before forward pass of layer 15 - Allocated memory: 21.42 GB
Before forward pass of layer 15 - Reserved memory: 27.02 GB
After forward pass of layer 15 - Allocated memory: 21.42 GB
After forward pass of layer 15 - Reserved memory: 27.02 GB
pruning layer 15 name self_attn.q_proj
pruning layer 15 name self_attn.k_proj
pruning layer 15 name self_attn.v_proj
pruning layer 15 name self_attn.o_proj
pruning layer 15 name mlp.gate_proj
pruning layer 15 name mlp.down_proj
pruning layer 15 name mlp.up_proj
After pruning layer 15 - Allocated memory: 21.42 GB
After pruning layer 15 - Reserved memory: 27.02 GB
Before forward pass of layer 16 - Allocated memory: 21.42 GB
Before forward pass of layer 16 - Reserved memory: 27.02 GB
After forward pass of layer 16 - Allocated memory: 21.42 GB
After forward pass of layer 16 - Reserved memory: 27.02 GB
pruning layer 16 name self_attn.q_proj
pruning layer 16 name self_attn.k_proj
pruning layer 16 name self_attn.v_proj
pruning layer 16 name self_attn.o_proj
pruning layer 16 name mlp.gate_proj
pruning layer 16 name mlp.down_proj
pruning layer 16 name mlp.up_proj
After pruning layer 16 - Allocated memory: 21.42 GB
After pruning layer 16 - Reserved memory: 27.02 GB
Before forward pass of layer 17 - Allocated memory: 21.42 GB
Before forward pass of layer 17 - Reserved memory: 27.02 GB
After forward pass of layer 17 - Allocated memory: 21.42 GB
After forward pass of layer 17 - Reserved memory: 27.02 GB
pruning layer 17 name self_attn.q_proj
pruning layer 17 name self_attn.k_proj
pruning layer 17 name self_attn.v_proj
pruning layer 17 name self_attn.o_proj
pruning layer 17 name mlp.gate_proj
pruning layer 17 name mlp.down_proj
pruning layer 17 name mlp.up_proj
After pruning layer 17 - Allocated memory: 21.42 GB
After pruning layer 17 - Reserved memory: 27.02 GB
Before forward pass of layer 18 - Allocated memory: 21.42 GB
Before forward pass of layer 18 - Reserved memory: 27.02 GB
After forward pass of layer 18 - Allocated memory: 21.42 GB
After forward pass of layer 18 - Reserved memory: 27.02 GB
pruning layer 18 name self_attn.q_proj
pruning layer 18 name self_attn.k_proj
pruning layer 18 name self_attn.v_proj
pruning layer 18 name self_attn.o_proj
pruning layer 18 name mlp.gate_proj
pruning layer 18 name mlp.down_proj
pruning layer 18 name mlp.up_proj
After pruning layer 18 - Allocated memory: 21.42 GB
After pruning layer 18 - Reserved memory: 27.02 GB
Before forward pass of layer 19 - Allocated memory: 21.42 GB
Before forward pass of layer 19 - Reserved memory: 27.02 GB
After forward pass of layer 19 - Allocated memory: 21.42 GB
After forward pass of layer 19 - Reserved memory: 27.02 GB
pruning layer 19 name self_attn.q_proj
pruning layer 19 name self_attn.k_proj
pruning layer 19 name self_attn.v_proj
pruning layer 19 name self_attn.o_proj
pruning layer 19 name mlp.gate_proj
pruning layer 19 name mlp.down_proj
pruning layer 19 name mlp.up_proj
After pruning layer 19 - Allocated memory: 21.42 GB
After pruning layer 19 - Reserved memory: 27.02 GB
Before forward pass of layer 20 - Allocated memory: 21.42 GB
Before forward pass of layer 20 - Reserved memory: 27.02 GB
After forward pass of layer 20 - Allocated memory: 21.42 GB
After forward pass of layer 20 - Reserved memory: 27.02 GB
pruning layer 20 name self_attn.q_proj
pruning layer 20 name self_attn.k_proj
pruning layer 20 name self_attn.v_proj
pruning layer 20 name self_attn.o_proj
pruning layer 20 name mlp.gate_proj
pruning layer 20 name mlp.down_proj
pruning layer 20 name mlp.up_proj
After pruning layer 20 - Allocated memory: 21.42 GB
After pruning layer 20 - Reserved memory: 27.02 GB
Before forward pass of layer 21 - Allocated memory: 21.42 GB
Before forward pass of layer 21 - Reserved memory: 27.02 GB
After forward pass of layer 21 - Allocated memory: 21.42 GB
After forward pass of layer 21 - Reserved memory: 27.02 GB
pruning layer 21 name self_attn.q_proj
pruning layer 21 name self_attn.k_proj
pruning layer 21 name self_attn.v_proj
pruning layer 21 name self_attn.o_proj
pruning layer 21 name mlp.gate_proj
pruning layer 21 name mlp.down_proj
pruning layer 21 name mlp.up_proj
After pruning layer 21 - Allocated memory: 21.42 GB
After pruning layer 21 - Reserved memory: 27.02 GB
Before forward pass of layer 22 - Allocated memory: 21.42 GB
Before forward pass of layer 22 - Reserved memory: 27.02 GB
After forward pass of layer 22 - Allocated memory: 21.42 GB
After forward pass of layer 22 - Reserved memory: 27.02 GB
pruning layer 22 name self_attn.q_proj
pruning layer 22 name self_attn.k_proj
pruning layer 22 name self_attn.v_proj
pruning layer 22 name self_attn.o_proj
pruning layer 22 name mlp.gate_proj
pruning layer 22 name mlp.down_proj
pruning layer 22 name mlp.up_proj
After pruning layer 22 - Allocated memory: 21.42 GB
After pruning layer 22 - Reserved memory: 27.02 GB
Before forward pass of layer 23 - Allocated memory: 21.42 GB
Before forward pass of layer 23 - Reserved memory: 27.02 GB
After forward pass of layer 23 - Allocated memory: 21.42 GB
After forward pass of layer 23 - Reserved memory: 27.02 GB
pruning layer 23 name self_attn.q_proj
pruning layer 23 name self_attn.k_proj
pruning layer 23 name self_attn.v_proj
pruning layer 23 name self_attn.o_proj
pruning layer 23 name mlp.gate_proj
pruning layer 23 name mlp.down_proj
pruning layer 23 name mlp.up_proj
After pruning layer 23 - Allocated memory: 21.42 GB
After pruning layer 23 - Reserved memory: 27.02 GB
Before forward pass of layer 24 - Allocated memory: 21.42 GB
Before forward pass of layer 24 - Reserved memory: 27.02 GB
After forward pass of layer 24 - Allocated memory: 21.42 GB
After forward pass of layer 24 - Reserved memory: 27.02 GB
pruning layer 24 name self_attn.q_proj
pruning layer 24 name self_attn.k_proj
pruning layer 24 name self_attn.v_proj
pruning layer 24 name self_attn.o_proj
pruning layer 24 name mlp.gate_proj
pruning layer 24 name mlp.down_proj
pruning layer 24 name mlp.up_proj
After pruning layer 24 - Allocated memory: 21.42 GB
After pruning layer 24 - Reserved memory: 27.02 GB
Before forward pass of layer 25 - Allocated memory: 21.42 GB
Before forward pass of layer 25 - Reserved memory: 27.02 GB
After forward pass of layer 25 - Allocated memory: 21.42 GB
After forward pass of layer 25 - Reserved memory: 27.02 GB
pruning layer 25 name self_attn.q_proj
pruning layer 25 name self_attn.k_proj
pruning layer 25 name self_attn.v_proj
pruning layer 25 name self_attn.o_proj
pruning layer 25 name mlp.gate_proj
pruning layer 25 name mlp.down_proj
pruning layer 25 name mlp.up_proj
After pruning layer 25 - Allocated memory: 21.42 GB
After pruning layer 25 - Reserved memory: 27.02 GB
Before forward pass of layer 26 - Allocated memory: 21.42 GB
Before forward pass of layer 26 - Reserved memory: 27.02 GB
After forward pass of layer 26 - Allocated memory: 21.42 GB
After forward pass of layer 26 - Reserved memory: 27.02 GB
pruning layer 26 name self_attn.q_proj
pruning layer 26 name self_attn.k_proj
pruning layer 26 name self_attn.v_proj
pruning layer 26 name self_attn.o_proj
pruning layer 26 name mlp.gate_proj
pruning layer 26 name mlp.down_proj
pruning layer 26 name mlp.up_proj
After pruning layer 26 - Allocated memory: 21.42 GB
After pruning layer 26 - Reserved memory: 27.02 GB
Before forward pass of layer 27 - Allocated memory: 21.42 GB
Before forward pass of layer 27 - Reserved memory: 27.02 GB
After forward pass of layer 27 - Allocated memory: 21.42 GB
After forward pass of layer 27 - Reserved memory: 27.02 GB
pruning layer 27 name self_attn.q_proj
pruning layer 27 name self_attn.k_proj
pruning layer 27 name self_attn.v_proj
pruning layer 27 name self_attn.o_proj
pruning layer 27 name mlp.gate_proj
pruning layer 27 name mlp.down_proj
pruning layer 27 name mlp.up_proj
After pruning layer 27 - Allocated memory: 21.42 GB
After pruning layer 27 - Reserved memory: 27.02 GB
Before forward pass of layer 28 - Allocated memory: 21.42 GB
Before forward pass of layer 28 - Reserved memory: 27.02 GB
After forward pass of layer 28 - Allocated memory: 21.42 GB
After forward pass of layer 28 - Reserved memory: 27.02 GB
pruning layer 28 name self_attn.q_proj
pruning layer 28 name self_attn.k_proj
pruning layer 28 name self_attn.v_proj
pruning layer 28 name self_attn.o_proj
pruning layer 28 name mlp.gate_proj
pruning layer 28 name mlp.down_proj
pruning layer 28 name mlp.up_proj
After pruning layer 28 - Allocated memory: 21.42 GB
After pruning layer 28 - Reserved memory: 27.02 GB
Before forward pass of layer 29 - Allocated memory: 21.42 GB
Before forward pass of layer 29 - Reserved memory: 27.02 GB
After forward pass of layer 29 - Allocated memory: 21.42 GB
After forward pass of layer 29 - Reserved memory: 27.02 GB
pruning layer 29 name self_attn.q_proj
pruning layer 29 name self_attn.k_proj
pruning layer 29 name self_attn.v_proj
pruning layer 29 name self_attn.o_proj
pruning layer 29 name mlp.gate_proj
pruning layer 29 name mlp.down_proj
pruning layer 29 name mlp.up_proj
After pruning layer 29 - Allocated memory: 21.42 GB
After pruning layer 29 - Reserved memory: 27.02 GB
Before forward pass of layer 30 - Allocated memory: 21.42 GB
Before forward pass of layer 30 - Reserved memory: 27.02 GB
After forward pass of layer 30 - Allocated memory: 21.42 GB
After forward pass of layer 30 - Reserved memory: 27.02 GB
pruning layer 30 name self_attn.q_proj
pruning layer 30 name self_attn.k_proj
pruning layer 30 name self_attn.v_proj
pruning layer 30 name self_attn.o_proj
pruning layer 30 name mlp.gate_proj
pruning layer 30 name mlp.down_proj
pruning layer 30 name mlp.up_proj
After pruning layer 30 - Allocated memory: 21.42 GB
After pruning layer 30 - Reserved memory: 27.02 GB
Before forward pass of layer 31 - Allocated memory: 21.42 GB
Before forward pass of layer 31 - Reserved memory: 27.02 GB
After forward pass of layer 31 - Allocated memory: 21.42 GB
After forward pass of layer 31 - Reserved memory: 27.02 GB
pruning layer 31 name self_attn.q_proj
pruning layer 31 name self_attn.k_proj
pruning layer 31 name self_attn.v_proj
pruning layer 31 name self_attn.o_proj
pruning layer 31 name mlp.gate_proj
pruning layer 31 name mlp.down_proj
pruning layer 31 name mlp.up_proj
After pruning layer 31 - Allocated memory: 21.42 GB
After pruning layer 31 - Reserved memory: 27.02 GB
After cleaning cache - Allocated memory: 21.42 GB
After cleaning cache - Reserved memory: 21.78 GB
******************************
layer 0 sparsity 0.500000
layer 1 sparsity 0.500000
layer 2 sparsity 0.500000
layer 3 sparsity 0.500000
layer 4 sparsity 0.500000
layer 5 sparsity 0.500000
layer 6 sparsity 0.500000
layer 7 sparsity 0.500000
layer 8 sparsity 0.500000
layer 9 sparsity 0.500000
layer 10 sparsity 0.500000
layer 11 sparsity 0.500000
layer 12 sparsity 0.500000
layer 13 sparsity 0.500000
layer 14 sparsity 0.500000
layer 15 sparsity 0.500000
layer 16 sparsity 0.500000
layer 17 sparsity 0.500000
layer 18 sparsity 0.500000
layer 19 sparsity 0.500000
layer 20 sparsity 0.500000
layer 21 sparsity 0.500000
layer 22 sparsity 0.500000
layer 23 sparsity 0.500000
layer 24 sparsity 0.500000
layer 25 sparsity 0.500000
layer 26 sparsity 0.500000
layer 27 sparsity 0.500000
layer 28 sparsity 0.500000
layer 29 sparsity 0.500000
layer 30 sparsity 0.500000
layer 31 sparsity 0.500000
sparsity sanity check 0.5000
******************************
evaluating on wikitext2
Downloading readme: 10.5kB [00:00, 10.3MB/s]
Downloading data: 100%|██████████████████████████████████████████████████████████████| 733k/733k [00:02<00:00, 353kB/s]
Downloading data: 100%|███████████████████████████████████████████████████████████| 6.36M/6.36M [00:01<00:00, 3.31MB/s]
Downloading data: 100%|██████████████████████████████████████████████████████████████| 657k/657k [00:01<00:00, 553kB/s]
Generating test split: 100%|████████████████████████████████████████████| 4358/4358 [00:00<00:00, 182353.77 examples/s]
Generating train split: 100%|█████████████████████████████████████████| 36718/36718 [00:00<00:00, 534412.48 examples/s]
Generating validation split: 100%|██████████████████████████████████████| 3760/3760 [00:00<00:00, 472031.82 examples/s]
nsamples 83
sample 0
sample 50
wikitext perplexity 6.461933135986328
5.4.4 输出文件结果
method actual_sparsity ppl_test
wanda 0.5000 6.4619
5.5 论文实验结果
6.模型训练时间估计
在训练Transformer模型时,模型参数量和训练总tokens数决定了所需的计算量。
6.1 训练时间估算方法
使用公式:
训练时间 ≈ 8 × token训练数 × 模型参数量 GPU数量 × GPU峰值flops × GPU利用率 \text{训练时间} \approx \frac{8 \times \text{token训练数} \times \text{模型参数量}}{\text{GPU数量} \times \text{GPU峰值flops} \times \text{GPU利用率}} 训练时间≈GPU数量×GPU峰值flops×GPU利用率8×token训练数×模型参数量
-
确定模型参数量和训练总tokens数:
- 模型参数量(例如:GPT-3 175B, LLaMA-65B, GLM-130B)。
- 训练总tokens数(例如:300B tokens, 1.4TB tokens, 400B tokens)。
-
计算训练所需的总浮点运算次数(FLOPS):
- 前向传递 + 后向传递 + 激活重计算的系数=1+2+1=4。
- 使用激活重计算的一次训练迭代中,对于每个token,每个模型参数,需要进行2∗4=8次浮点数运算
-
计算训练时间:
- 训练时间与GPU的峰值浮点运算能力和实际GPU利用率有关。
-
考虑端到端训练的GPU利用率:
- 训练时间不仅包括前向传递和后向传递的计算时间,还包括数据加载、优化器更新、多卡通信和记录日志的时间。
- 一般情况下,GPU利用率在30%到50%之间。
6.2 Nvidia A100算力情况
6.3 实例分析
-
GPT-3 175B:
-
硬件配置:1024张40GB显存的A100
-
训练数据:300B tokens
-
A100峰值性能:312TFLOPS
-
GPU利用率:45%
-
训练时间:34天
-
计算:
训练时间 ≈ 8 × 300 × 175 × 1 0 18 1024 × 312 × 0.45 × 1 0 12 \text{训练时间} \approx \frac{8 \times 300 \times 175 \times 10^{18}}{1024 \times 312 \times 0.45 \times 10^{12}} 训练时间≈1024×312×0.45×10128×300×175×1018训练时间 ≈ 420000 × 1 0 18 143769.6 × 1 0 12 \text{训练时间} \approx \frac{420000 \times 10^{18}}{143769.6 \times 10^{12}} 训练时间≈143769.6×1012420000×1018
训练时间 ≈ 2921340 seconds \text{训练时间} \approx 2921340 \text{ seconds} 训练时间≈2921340 seconds
将秒数转换为天:
2921340 seconds ≈ 34 days 2921340 \text{ seconds} \approx 34 \text{ days} 2921340 seconds≈34 days
-
-
LLaMA-65B:
- 硬件配置:2048张80GB显存的A100
- 训练数据:1.4TB tokens
- A100峰值性能:624TFLOPS
- GPU利用率:30%
- 训练时间:21天
-
GLM-130B:
- 硬件配置:768张40GB显存的A100
- 训练数据:400B tokens
- A100峰值性能:312TFLOPS
- GPU利用率:35%
- 训练时间:57天
7. 小工具—LLM 3D 可视化工具
**网站:**https://bbycroft.net/llm
效果图:
这个网站是一个3D可视化的工具,它可以让你直观地看到一个GPT-风格的语言模型(LLM)的内部结构和运行过程,它展示了一个基于Transformer的语言模型的主要组成部分
你可以通过鼠标和键盘来控制视角,放大缩小,旋转,拖动,查看每个部分的细节和功能。你还可以输入自己的文本,看看模型是如何处理和生成的。
8. 参考资料
- 官方说明
- 技术文档
- 爱鼓捣 – AI开发者de频道
- 如何准确的估计llm推理和微调的内存消耗
- Reducing Activation Recomputation in Large Transformer Models
- A Simple and Effective Pruning Approach for Large Language Models
- LLM训练指南(二):模型参数、计算量、显存、计算时间计算