LLMs规格对应推理及微调时所需的显存
LLMs规格对应推理及微调时所需的显存
基础术语解释
推理(Inference):使用预训练模型根据输入数据进行文本的过程。
微调(Fine-tuning):在特定数据集上进一步训练预训练模型以使其适应特定任务的过程。
内存消耗:在 LLM 推理和微调期间存储和处理数据所需的计算机内存量。
优化器:一些优化算法(如带有动量的优化器)需要保存一些状态信息,以便在每次更新时进行调整。这些状态信息也会占用一定的显存。
批处理大小(BatchSize): 批处理大小是指一次推理中处理的样本数量。较大的批处理大小可能会增加显存使用,因为需要同时存储多个样本的计算结果。
我们为什么要知道这个显存大小的对应关系
高效的资源分配:通过准确估计显存需求,开发人员可以优化分配资源,确保 NLP 任务的顺利执行。
成本优化:高效的内存消耗转化为更低的硬件要求和更低的运营成本,使 LLM 部署对企业和组织来说更具经济可行性。
模型部署:优化内存使用率,使 LLM 在资源受限的环境中(如边缘设备和云服务器)的部署更加顺畅,从而扩展了 LLM 的可访问性和适用性。
整体对应关系
对于一个模型,推理和微调是不同的。
想要进行相应操作,首先模型需要运行起来-即本身的运行显存;其次就是具体操作需要的显存。对于推理,只需要加一个推理显存;对于微调,则需要给优化器提供显存和微调显存。
对于一个模型需要的显存就是所有显存加起来的结果:
推理:模型显存+推理显存
微调:模型显存+推理显存+优化器显存
下图为整体需要显存的关系:
对代码各部分需要填写信息的说明
模型大小
其中model size是模型大小,8.03B就是8.03billion。67M就是67million。tensor type是模型精度类型,F32代表32bit。 BF16代表16bit。int32代表32bit(int为量化时的表示)
量化处理
量化处理就是一种模型压缩技术(就是放压缩包里了),通过将浮点数参数映射到较低位数的整数,从而在一定程度上降低了模型的计算和存储成本。可以从32bit搞到8bit,最后是用8bit来计算的。
优化器参数
一些优化算法(如带有动量的优化器)需要保存一些状态信息,以便在每次更新时进行调整。这些状态信息也会占用一定的显存。比如:
采用 AdamW 优化器:每个参数占用8个字节,需要维护两个状态。意味着优化器所使用的显存量是模型权重的 2 倍;
采用 经过 bitsandbytes 优化的 AdamW 优化器:每个参数占用2个字节,相当于权重的一半;
采用 SGD 优化器:占用显存和模型权重一样。
批处理通路大小的设置
机器学习中的batch_size
,即批量大小,是一个超参数,其具体值取决于多种因素,包括但不限于模型的复杂性、训练数据的大小、以及可用的计算资源(如GPU内存)。没有一个固定的值适用于所有情况,但是可以根据经验提供一些指导性建议。
小至中等数据集与模型:对于较小或中等规模的数据集和模型,batch_size
通常设置在32至128之间。这个范围通常是一个不错的起点,可以在不同的模型和任务上进行尝试和微调。
大规模模型与大数据集:对于较大的模型和数据集,尤其是在使用GPU或其他高性能计算资源时,
batch_size
可能会设置得更大,范围在256、512甚至更高。较大的batch_size
可以提高内存利用率和加速训练过程,但同时也可能需要更多的内存资源。小批量与Minibatch训练:有时,由于内存限制,可能需要使用较小的
batch_size
,如16、8甚至1(随机梯度下降)。这种情况下,每次更新使用的数据较少,可能使训练过程更加噪声化,但对于内存受限的情况,这是可行的解决方案。考虑内存限制:在实际应用中,最大可用的
batch_size
往往受到硬件内存限制的约束。尤其在GPU训练中,较大的batch_size
需要较多的内存空间。如果遇到内存溢出错误,需要减小batch_size
来适应硬件能力。自动调优工具:还有一些自动化工具和库,如TensorFlow的
tf.data
API和PyTorch的torch.utils.data.DataLoader
,其中包含可以自动调整batch_size
的功能,以在给定的硬件约束下最大化性能。
综上所述,合适的batch_size
取决于具体任务、模型结构以及计算资源。通常,通过实验找到在特定情况下性能最佳的batch_size
是一种常见的做法。此外,还可以考虑使用动态调整batch_size
的策略来进一步优化模型训练过程。
计算代码:
from transformers import AutoConfig
model_name = "shenzhi-wang/Llama3-8B-Chinese-Chat" # @param {type: "string"}这里要改!!
model_config = AutoConfig.from_pretrained(model_name)
hidden_layers = model_config.num_hidden_layers
hidden_size = model_config.hidden_size
attention_heads = model_config.num_attention_heads
print("Model: "+str(model_name))
print("Hidden Layers (L): "+str(hidden_layers))
print("Hidden Size (h): "+str(hidden_size))
print("Attention Heads (a): "+str(attention_heads)+"\n")
#Number of parameters in the model (in billions)
#模型大小即model size
nb_billion_parameters = 8.03 # @param {type:"number"}这里要改!!截图看model size位置
print("Number of parameters in the model (n): "+str(nb_billion_parameters)+"B")
#Precision of the parameters in the model
#模型精度大小即后边tensor type 是多少填多少,如果量化处理则除以4。
bitwidth_model = 16 # @param {type:"integer"}这里要改!!截图里看tensor type位置
print("Bitwidth of the model's parameters (p): "+str(bitwidth_model)+"-bit")
#Precision of the parameters in the optimizer
#优化器精度,根据使用的优化器类型选择是模型精度的多少倍
bitwidth_optimizer = 8 # @param {type:"integer"}这里要改!!模型精度的0.5、1、2倍
print("Bitwidth of the optimizer's parameters (o): "+str(bitwidth_optimizer)+"-bit")
#The maximum number of tokens in a sequence
#问或答最大的tokens是多少,一般正常说话200以内即可。大段文字
seqlen = 64 # @param {type:"integer"}这里要改!!就说个hello
print("Sequence length (s): "+str(seqlen))
#The batch size
#就是一次处理通路(简单理解)
batch_size = 8 # @param {type:"integer"}这里要改!!根据上边选择,咱就是小模型选8.
print("Batch size (b): "+str(batch_size)+"\n")
def estimate_consumption():
#34 sbh + 5as²b
return round((34*seqlen*batch_size*hidden_size + 5*attention_heads*seqlen*seqlen*batch_size)*2/(1024**3),2)
def estimate_optimizer_size():
return round((2*nb_billion_parameters*bitwidth_optimizer/8*(1000**3))/(1024**3),2)
def estimate_model_size():
return round(nb_billion_parameters*bitwidth_model/8*(1000**3)/(1024**3),2)
activation_consumption = estimate_consumption()
model_consumption = estimate_model_size()
optimizer_consumption = estimate_optimizer_size()
#print("Memory consumption of the model: "+str(model_consumption)+" GB\n")
print("模型本身需要的显存: "+str(model_consumption)+" GB\n")
print("模型优化器需要的显存: "+str(optimizer_consumption)+" GB")
print("微调部分需要的显存: "+str(activation_consumption*hidden_layers)+" GB")
print("想微调这个模型我需要多少显存: "+str(model_consumption+optimizer_consumption+activation_consumption*hidden_layers)+" GB\n")
print("使用模型进行推理需要的显存: "+str(activation_consumption)+" GB")
print("想使用此模型推理总共需要的显存: "+str(model_consumption+activation_consumption)+" GB")
附:查tokens数量的方法
目前,在公开渠道没有专门针对查询句子对应于大型语言模型(LLM)内tokens数量的专用网站。这是因为不同的语言模型如GPT系列(GPT-3, GPT-4等),BERT系列(BERT, RoBERTa等)可能使用不同的分词机制和字典,导致相同的句子在不同模型中被分解成不同数量的tokens。
不过,你可以通过以下几种方法来近似获取某句话对应的tokens数量:
使用具体模型的分词工具:大多数大型语言模型都会提供相应的分词工具。例如,对于使用Transformers库的模型,你可以通过安装相应的Python包然后使用其提供的分词器来计算tokens数量。
例如,对于GPT-2或GPT-3,使用transformers库中的分词器示例代码如下:
from transformers import GPT2Tokenizer
# Load the tokenizer
tokenizer = GPT2Tokenizer.from_pretrained("gpt2")
# Encode the text
text = "这是一段示例文本。"
encoded_input = tokenizer.encode(text)
tokens = tokenizer.convert_ids_to_tokens(encoded_input)
# Output the number of tokens
print(f"Number of tokens: {len(tokens)}")
print(f"Tokens: {tokens}")
查阅官方文档或API:对于一些提供API服务的大型语言模型,官方文档有时会提供关于其分词系统的详细说明,包括但不限于tokens的具体定义、计算方法等。
在线编程环境:一些在线的编程环境或笔记本服务,如Google Colab,提供了运行Python代码的能力,也可以用来安装必要的库,并运行上面的代码片段以查询tokens数量。