摘要:如果你想要评估结果完全可复现 (在特定的输入 prompt 和硬件条件下),你可以把 batch size 可以设为 1。但如果增大 batch size (硬件条件允许的话) 将会加快推理速度。
这是 大模型评估排障指南 系列文章的第一篇,敬请关注系列文章:
关于推理
关于 公式解析
关于可复现性
模型运行非常慢怎么办?
调整 batch size
如果你想要评估结果完全可复现 (在特定的输入 prompt 和硬件条件下),你可以把 batch size 可以设为 1。但如果增大 batch size (硬件条件允许的话) 将会加快推理速度。
数据并行
你可以将模型加载到多个 GPU 上,然后将数据集分为多个子集并分配给每个 GPU,最后汇总全部计算结果。 这意味着每个数据流是被并行同时处理的,从而将总执行时间缩短至 GPU 数分之一。尽量把 GPU 都放在一个节点上来避免跨节点传输瓶颈。
调整代码
不同的推理库由于代码优化的种种差异,推理速度不尽相同。你可能需要做一些对比试验来选出速度最快的库。如果模型层面你使用 pytorch 实现,建议可以参考这份推理优化清单。https://pytorch.org/serve/performance_checklist.html
调整精度
你可以通过调整计算精度来减小模型大小,进而加快推理速度。虽然 float32 精度 (每个数字使用 32 位存储) 的模型计算非常精确,但其消耗的内存和计算资源却非常大。降低精度为 blfoat16 或 float16 (半精度) 可以加速一倍,而且不会影响计算结果。如果需要更进一步加速,可以尝试量化为更低精度,如 8 比特或 4 比特 (可以使用 gptq 或 bitsandbytes 库完成量化)。低位矩阵计算速度更快 (不过有些量化库反而有些慢,最好在你自己的模型上测试一下),模型占用内存也更少。
内存占用非常大怎么办?
= *
模型所需总内存等于总参数量乘以一个参数所需的字节数。其中 1 个字节 (Byte) 是 8 比特 (bit),精度因子视情况取值 (float32 为 4、float16 或 bfoat16 为 2、8bit 为 1、4bit 为 0.5)。
这就是基本的估算方法。
实际使用时我建议这样计算: = * ( * 110%)。因为推理阶段除了加载模型还需要加载数据,总内存需求会更多。
一个 GPU 都装不下怎么办?
量化
第一个明显的方法是降低 : 从 float32 降低到 4bit 可以降低 8 倍的内存占用! 不过精度太低也会导致结果变差。对于一些模型 (尤其是中等规模的模型) float16 或 8bit 就足够 (低精度对大型模型的影响较小,可能是因为信息冗余)。
模型并行
模型并行包含一系列技术:拆分大模型为多个小型子模型、分配子模型到不同的 GPU 上运行等。这种方法不会一次性地加载整个模型,因此减少了内存需求,但可能会更慢。
模型并行有两种方法:
管线并行。即在 layer 级拆分模型,不同的 layer 被分配到不同的 GPU 上。由于推理时前向过程是线性的,例如 layer 1 的输出是 layer 2 的输入,因此 layer 2 分配的 GPU 需要等待 layer 1 的计算结束才能开始 (也叫 “冒泡 (bubble)”),同时数据和中间结果也需要 GPU 间传输,这也就导致执行速度较慢。不过可以通过将输入拆分为更小的批次来缓解冒泡,Pytorch 的原生库PiPPy就支持这一功能,也是 accelerate 库后台实现并行的方法。https://github.com/pytorch/PiPPy
张量并行。即在矩阵计算级拆分模型,矩阵按行或者列被拆分且分配到不同的 GPU 上计算以及合并结果。如果多个 GPU 在同一个节点上 (避免跨节点传输瓶颈),这种并行方法会非常高效,但是代码实现有些困难。好在 vllm 库已经实现了,加速效果 非常明显。
更多并行方法 (包括数据并行等) 可以参考这篇文档。https://hf.co/docs/transformers/v4.15.0/en/parallelism
用 CPU 减负
CPU 卸载可以将部分模型和计算从 GPU 转移到 CPU 上,以减少 GPU 内存占用。不过相比于其他方法,CPU 卸载要 慢得多,主要原因是需要将数据在设备之间频繁移动。
例如,Deepspeed 的ZeRO-Offload可以将参数同时分配到 CPU 和 GPU (在 ZeRO-2 论文中有更详细的优化说明) 上。其中梯度、优化器状态、以及优化过程中的 fp32 模型参数在 CPU 上传递,而前向和反向过程中的 fp16 参数可以在 GPU 上传递,从而利用 CPU 内存优化并优化 GPU 计算,同时减少两者之间的通信。
ZeRO-Offloadhttps://arxiv.org/abs/2101.06840
模型装进 GPU 但还是报 OOMs 错误怎么办?
你可能遇到了上下文大小相关的问题。
我们建议:
同时加载模型以及 dummy 数据,测试 GPU 是否会内存溢出,注意 dummy 数据的上下文长度应足够大 (能够代表你的任务)。
降低 batch size,或者关闭自动搜索 batch size 功能 (如果启用,有时会导致 OOM 错误)。
更一般地,确保输入模型的样本的上下文大小是按从大到小的顺序,这样如果上下文大小过大,模型就会直接报错,避免了模型一开始正常运行,直到某个时间才出问题。
英文原文:https://raw.githubusercontent.com/huggingface/evaluation-guidebook/refs/heads/main/translations/zh/contents/troubleshooting/troubleshooting-inference.md
原文作者: clefourrier
译者: SuSung-boy
来源:焱焱课堂