Connect with us

人工智能

为大型语言模型推理和微调优化内存

mm
Memory for Large Language Model Inference

像GPT-4、Bloom和LLaMA这样的大型语言模型(LLM)通过扩大到数十亿参数,实现了令人惊叹的能力。然而,部署这些大型模型进行推理或微调由于其巨大的内存需求而具有挑战性。在这篇技术博客中,我们将探讨估计和优化LLM推理和微调过程中内存消耗的技术,涵盖各种硬件设置。

理解内存需求

加载LLM所需的内存主要由参数数量和用于存储参数的数值精度决定。一个简单的经验法则是:

  • 加载一个具有X十亿参数的模型,需要大约4X GB的VRAM,在32位浮点精度下
  • 加载一个具有X十亿参数的模型,需要大约2X GB的VRAM,在16位bfloat16/float16精度下

例如,加载175B参数的GPT-3模型,需要大约350GB的VRAM,在bfloat16精度下。截至今日,像NVIDIA A100和H100这样的最大商用GPU仅提供80GB的VRAM,这需要张量并行和模型并行技术。

在推理过程中,内存占用主要由模型参数和产生的临时激活张量决定。推理过程中峰值内存使用的高级估计是加载模型参数所需的内存与激活内存的总和。

量化推理内存

让我们使用OctoCode模型来量化推理内存需求,该模型大约有15亿参数,采用bfloat16格式(~31GB)。我们将使用Transformers库加载模型并生成文本:

from transformers import AutoModelForCausalLM, AutoTokenizer, pipeline
import torch

model = AutoModelForCausalLM.from_pretrained("bigcode/octocoder",
torch_dtype=torch.bfloat16,
device_map="auto",
pad_token_id=0)
tokenizer = AutoTokenizer.from_pretrained("bigcode/octocoder")
pipe = pipeline("text-generation", model=model, tokenizer=tokenizer)

prompt = "Question: 请编写一个Python函数来将字节转换为千兆字节。\n\nAnswer:"
result = pipe(prompt, max_new_tokens=60)[0]["generated_text"][len(prompt):]

def bytes_to_gigabytes(bytes):
return bytes / 1024 / 1024 / 1024

bytes_to_gigabytes(torch.cuda.max_memory_allocated())

输出:

29.0260648727417

峰值GPU内存使用量约为29GB,与我们对bfloat16格式下加载模型参数的估计31GB一致。

使用量化优化推理内存

虽然bfloat16是训练LLM的常用精度,但研究人员发现,将模型权重量化为较低精度数据类型(如8位整数(int8)或4位整数)可以在保持最小准确性损失的同时显著减少内存使用量,适用于文本生成等推理任务。

让我们看看OctoCode模型的8位和4位量化的内存节省:

</div>
# 8位量化
model = AutoModelForCausalLM.from_pretrained("bigcode/octocoder", load_in_8bit=True,
pad_token_id=0)
pipe = pipeline("text-generation", model=model, tokenizer=tokenizer)
result = pipe(prompt, max_new_tokens=60)[0]["generated_text"][len(prompt):]
bytes_to_gigabytes(torch.cuda.max_memory_allocated())</pre>
输出:
15.219234466552734
# 4位量化
model = AutoModelForCausalLM.from_pretrained("bigcode/octocoder", load_in_4bit=True,
low_cpu_mem_usage=True, pad_token_id=0)
pipe = pipeline("text-generation", model=model, tokenizer=tokenizer)
result = pipe(prompt, max_new_tokens=60)[0]["generated_text"][len(prompt):]
bytes_to_gigabytes(torch.cuda.max_memory_allocated())

输出:

9.543574333190918

使用8位量化,内存需求从31GB降低到15GB,而4位量化进一步降低到9.5GB!这使得可以在像RTX 3090(24GB VRAM)这样的消费者GPU上运行15B参数的OctoCode模型。

但是,请注意,更激进的量化(如4位)有时可能会导致与8位或bfloat16精度相比的准确性下降。用户应该根据自己的使用场景评估内存节省与准确性之间的权衡。

量化是一种强大的技术,可以通过大幅降低内存占用,使LLM能够在资源受限的环境中部署,如云实例、边缘设备,甚至移动电话。

估计微调内存

虽然量化主要用于高效推理,但像张量并行和模型并行这样的技术对于管理大型语言模型微调过程中的内存需求至关重要。

微调过程中的峰值内存消耗通常比推理高3-4倍,这是由于以下额外内存需求:

  • 梯度
  • 优化器状态
  • 用于反向传播的正向传播激活

一个保守的估计是,微调具有X十亿参数的LLM,需要大约4 * (2X) = 8X GB的VRAM,在bfloat16精度下。

例如,微调7B参数的LLaMA模型,需要大约7 * 8 = 56GB的VRAM,每个GPU在bfloat16精度下。这超过了当前GPU的内存容量,需要分布式微调技术。

分布式微调技术

已经提出了几种分布式微调方法,以克服大型模型的GPU内存限制:

  1. 数据并行: 数据并行的经典方法在多个GPU上复制整个模型,同时分割和分发训练数据批次。这减少了训练时间,但不减少每个GPU上的峰值内存需求。
  2. ZeRO Stage 3: 数据并行的高级形式,分割模型参数、梯度和优化器状态,分布在GPU上。它通过仅在训练的不同阶段在每个GPU上保留所需的分割数据来减少与经典数据并行相比的内存使用。
  3. 张量并行: 与复制模型不同,张量并行将模型参数分割为行或列,分布在GPU上。每个GPU操作一组分割的参数、梯度和优化器状态,从而实现了显著的内存节省。
  4. 管道并行: 该技术将模型层分割到不同的GPU/工作器,每个设备执行一组层。激活在工作器之间传递,减少峰值内存,但增加了通信开销。

估计这些分布式方法的内存使用量很棘手,因为参数、梯度、激活和优化器状态的分布在技术之间有所不同。此外,模型的不同组件(如变压器主体和语言建模头)可能表现出不同的内存分配行为。

LLMem解决方案

研究人员最近提出了LLMem,一种解决方案,准确估计在多个GPU上应用分布式微调方法时的GPU内存消耗。

估计预训练LLM的GPU内存使用

估计预训练LLM的GPU内存使用

LLMem考虑了诸如在计算前重组参数(ZeRO Stage 3)、反向传播中的输出收集(张量并行)以及变压器主体和语言建模头的不同内存分配策略等因素。

实验结果表明,LLMem可以估计单个GPU上微调LLM的峰值GPU内存使用,误差率高达1.6%,优于当前最先进的DNNMem的平均误差率42.6%。当将分布式微调方法应用于多个GPU上的超过十亿参数的LLM时,LLMem实现了令人印象深刻的平均误差率3.0%。

通过预先准确估计内存需求,LLMem可以帮助用户选择最有效的分布式微调方法,避免内存不足问题,同时最小化训练时间。

新兴技术

虽然量化、张量并行和模型并行是成熟的技术,但研究人员继续探索新方法,以推动高效LLM训练和部署的边界。

  1. LoRA和QLoRA: 这些技术涉及训练一个较小的残差适配器模块来更新预训练的LLM,而不是直接微调大量参数。这可以在保持大部分模型性能的同时实现显著的内存节省。
  2. FlashAttention: 自注意力机制是变压器模型中的内存和计算瓶颈。FlashAttention用线性复杂度近似标准注意力,减少内存需求从输入序列长度的二次到线性。
  3. Mixture-of-Experts: 该方法有条件地将每个输入数据样本路由到一个专用专家模型,而不是通过整个模型处理它。这一动态稀疏性可以通过仅为每个样本激活一组专家来节省内存。
  4. 逆模型手术: 研究人员已经探索了通过迭代删除不太重要的组件(如注意力头)来进行模型压缩,权衡内存/速度与准确性。
  5. 卸载: 最后,卸载参数、优化器状态或激活到CPU RAM或磁盘的技术可以补充有限的GPU内存用于大型模型。

这些尖端方法说明了专注于使高效LLM训练和部署在各种硬件环境中普及的充满活力的研究生态系统。

结论

大型语言模型的内存需求对其在实际应用中的广泛采用提出了重大挑战。通过了解内存估计技术,并利用量化、分布式训练策略和新兴创新,我们可以在资源受限的设备上优化LLM部署。

像LLMem这样的工具为准确的内存估计铺平了道路,使用户能够选择最合适的微调配置。随着硬件的演进和研究的进步,我们可以期待更高效的LLM训练和推理,从而推动自然语言处理和人工智能的进步。

在模型容量、准确性和资源利用之间找到合适的平衡对于解锁大型语言模型在各个领域和用例中的全部潜力至关重要。通过采用内存优化技术,我们更接近一个未来,顶级语言AI是可访问的、可扩展的和可持续的。

我过去五年一直沉浸在令人着迷的机器学习和深度学习世界中。我的热情和专业知识使我能够为超过50个不同的软件工程项目做出贡献,特别注重人工智能/机器学习。我的持续好奇心也使我对自然语言处理产生了兴趣,这是一个我渴望进一步探索的领域。