当前位置: 首页 > 科技观察

消费级GPU成功运行1760亿参数大型模型

时间:2023-03-19 15:19:56 科技观察

在消费级GPU上运行大型模型是机器学习社区面临的持续挑战。语言模型的规模一直在变大,PaLM有540B个参数,OPT、GPT-3和BLOOM有大约176B个参数,模型还在往更大的方向发展。这些模型很难在易于访问的设备上运行。例如,BLOOM-176B需要在八个80GBA100GPU(每个约15,000美元)上运行以执行推理任务,而微调BLOOM-176B需要72个这样的GPU。PaLM等较大的模型将需要更多资源。我们需要找到在保持模型性能的同时减少这些模型的资源需求的方法。该领域已经开发了各种技术来尝试减小模型大小,例如量化和蒸馏。BLOOM是去年由1,000多名志愿者研究人员在一个名为“BigScience”的项目中创建的,该项目由人工智能初创公司HuggingFace在法国政府的资助下运营。BLOOM款于今年7月12日正式发布。使用Int8进行推理可显着减少模型的内存占用,而不会降低模型的预测性能。基于此,来自华盛顿大学、MetaAI研究所等机构(前身为FacebookAIResearch)的研究人员与HuggingFace联合进行了一项研究,试图让经过训练的BLOOM-176B在更少的GPU上运行,并将所提出的方法完全集成进入HuggingFace变形金刚。论文地址:https://arxiv.org/pdf/2208.07339.pdfGithub地址:https://github.com/timdettmers/bitsandbytes本研究提出了第一个数十亿规模的TransformerInt8量化过程,该过程不它会影响模型的推理性能。它可以加载具有16位或32位权重的175B参数的转换器,并将前馈和注意力投影层转换为8位。它将推理所需的内存减半,同时保持全精度性能。该研究将矢量量化和混合精度分解的组合命名为LLM.int8()。实验表明,通过使用LLM.int8(),可以在消费级GPU上使用多达175B参数的LLM进行推理,而不会降低性能。这种方法不仅揭示了异常值对模型性能的影响,而且首次使在具有消费级GPU(例如OPT-175B/BLOOM)的单个服务器上使用超大型模型成为可能。方法介绍机器学习模型的大小取决于参数的数量及其精度,通常为float32、float16或bfloat16之一。float32(FP32)代表标准化的IEEE32位浮点表示法,可以使用此数据类型表示范围广泛的浮点数。FP32为“指数”保留8位,为“尾数”保留23位,为数字的符号保留1位。此外,大多数硬件都支持FP32操作和指令。而float16(FP16)为指数保留5位,为尾数保留10位。这使得FP16数字的可表示范围远低于FP32,存在溢出(试图表示非常大的数字)和下溢(表示非常小的数字)的风险。你会在溢出时得到NaN(非数字)结果,如果你像在神经网络中那样进行顺序计算,很多工作都会失败。bfloat16(BF16)避免了这个问题。BF16为指数保留8位,为小数保留7位,这意味着BF16可以保留与FP32相同的动态范围。理想情况下,训练和推理应该在FP32中完成,但它比FP16/BF16慢,所以使用混合精度来提高训练速度。但在实践中,半精度权重在推理过程中也提供与FP32相似的质量。这意味着我们可以使用一半的精度权重和一半的GPU来获得相同的结果。但是,如果我们可以使用不同的数据类型以更少的内存存储这些权重呢?一种称为量化的方法已广泛用于深度学习。该研究首先在实验中将4字节的FP32精度替换为2字节的BF16/FP16半精度,并取得了几乎相同的推理结果。这样模型就缩小了一半。但是如果你进一步减少这个数字,准确率就会下降,推理的质量就会急剧下降。为了弥补这一点,该研究引入了8位量化。此方法使用四分之一的精度,因此只需要四分之一的模型大小,但它不会通过删除另一半位来实现。两种最常见的8位量化技术是零点量化和absmax(绝对最大值)量化。这两种方法将浮点值映射为更紧凑的int8(1字节)值。比如零点量化,如果数据范围是-1.0—1.0,量化到-127—127,它的扩展因子就是127。有了这个扩展因子,比如0.3的值会被扩展成0.3*127=38.1。量化通常会使用舍入,结果为38。如果取反,您将得到38/127=0.2992-本例中的量化误差为0.008。这些看似很小的错误在通过模型层传播时往往会累积和增长并导致性能下降。虽然这些技术能够量化深度学习模型,但它们通常会导致模型准确性下降。但是集成到HuggingFaceTransformers和Accelerate库中的LLM.int8()是第一种即使对于具有176B参数的大型模型(例如BLOOM)也不会降低性能的技术。LLM.int8()算法可以解释如下。本质上,LLM.int8()试图通过三个步骤进行矩阵乘法计算:从输入的隐藏状态中,逐列提取异常值(即大于某个阈值的值)。FP16中异常值与int8中非异常值的矩阵乘法。对FP16中的非异常值进行反量化,将异常值和非异常值相加得到完整的结果。这些步骤可以总结在下面的动画中:最后,研究还关注了一个问题:它比原生模型快吗?LLM.int8()方法的主要目的是在不降低性能的情况下使大型模型更易于访问。但是,如果它很慢,它就不是很有用。研究团队对多个模型的生成速度进行了基准测试,发现带有LLM.int8()的BLOOM-176B比fp16版本慢了大约15%到23%——完全可以接受。而较小的型号,如T5-3B和T5-11B,则具有更大的减速度。研究团队正在努力让这些小模型运行得更快。