BitNet.cpp 是一款微软开源的、针对 1 比特大语言模型 (LLM) 的高性能推理框架,可在 CPU 上实现快速且无损的推理。它通过优化的内核,如 I2_S、TL1 和 TL2,在 x86 和 ARM 架构上显著提升了推理速度和能耗效率,为在本地设备上部署大型语言模型提供了新的可能,让百亿参数的大语言模型在你的笔记本电脑上也能流畅运行。
迈向高效的大语言模型时代
近年来,大型语言模型(LLM)如 ChatGPT 的横空出世,彻底改变了自然语言处理领域,展现出强大的语言理解和生成能力,推动了人机交互方式的变革。然而,LLM 通常需要庞大的计算资源和存储空间,这限制了其在个人电脑、手机等资源受限设备上的部署和应用。为了解决这一问题,研究人员开始探索模型量化技术,通过降低模型权重的精度来压缩模型规模和计算开销,其中,1 比特量化技术将模型权重压缩到极致,每个权重仅用 1 个比特表示,极大地降低了模型的存储和计算成本,为LLM的普及化应用带来了新的希望。
BitNet.cpp:1 比特大语言模型的推理利器
BitNet.cpp是由微软研究院开发的一款针对 1 比特大语言模型(如 BitNet 和 BitNet b1.58)的推理框架。它提供了一套优化的内核,支持在 CPU 上进行快速且无损的 1 比特模型推理,让每个人都能在自己的设备上体验LLM的强大能力。
核心优势:速度、能耗与精度兼得
BitNet.cpp 的核心优势在于它能够在显著提升推理速度、大幅降低能耗的同时,确保推理精度不受影响,实现了性能、效率和质量的完美平衡。
显著提升推理速度
BitNet.cpp 在 x86 和 ARM 架构上均实现了显著的推理速度提升。在 x86 CPU 上,它实现了 2.37 倍至 6.17 倍的加速;在 ARM CPU 上,它实现了 1.37 倍至 5.07 倍的加速。模型规模越大,性能提升越显著。 例如,BitNet.cpp 可以在单个 CPU 上运行 1000 亿参数的 BitNet b1.58 模型,速度可达人类阅读速度(每秒 5-7 个 token),这意味着你可以在没有GPU加速的情况下,也能流畅地与百亿参数的大语言模型进行交互。
图1:Apple M2 芯片上不同规模 BitNet b1.58 模型的推理速度对比(bitnet.cpp vs. llama.cpp)
图2:Intel i7-13700H 芯片上不同规模 BitNet b1.58 模型的推理速度对比(bitnet.cpp vs. llama.cpp)
大幅降低能耗
BitNet.cpp 的低精度计算特性使其能够显著降低模型的能耗,这对于移动设备等功耗敏感的场景尤为重要。在 Apple M2 上,BitNet.cpp 的能耗降低了 55.4% 至 70.0%;在 Intel i7-13700H 上,能耗节省更为显著,范围为 71.9% 至 82.2%。 这意味着,使用BitNet.cpp,你可以在更长时间内使用你的笔记本电脑或手机运行LLM,而不用担心电池电量过快耗尽。
确保推理精度
BitNet.cpp 采用了创新的量化和推理技术,例如三进制 BitNet b1.58,在将模型权重压缩到 1 比特的同时,实现了无损推理,即推理结果与全精度模型完全一致。 这意味着,你可以在享受 BitNet.cpp带来的速度和效率提升的同时,无需担心模型精度下降带来的负面影响。
技术揭秘:优化内核
BitNet.cpp 提供了一套优化的内核,包括 I2_S、TL1 和 TL2,以支持在 x86 和 ARM 架构上对 1.58 比特模型进行快速、无损的推理。
I2_S 内核
I2_S 内核的思路是将原本需要更高精度存储的模型权重,压缩成更小的 2 比特存储,从而节省存储空间和读取时间。
可以把它想象成一个高效的压缩算法:在模型存储时,它将每个权重值转换成对应的 2 比特代码;在推理计算时,它再将这些 2 比特代码还原成原本的权重值进行计算。虽然多了压缩和解压缩的步骤,但由于 2 比特存储相比更高精度存储节省了大量的空间和读取时间,最终反而提升了整体推理速度。
TL1 内核
TL1 内核则更进一步,它利用了一种叫做“查找表”(Lookup Table,简称LUT)的技术来加速计算。
假设我们要计算两个数的乘积,传统方法是直接进行乘法运算。但 TL1 内核的做法是,预先计算好所有可能的两个数的乘积,并将结果存储在一个表格里。在推理计算时,只需要根据这两个数的值去查表找到对应的结果即可,无需再进行乘法运算。
TL1 内核将每两个权重值组合在一起,生成一个 4 比特的索引,这个索引对应着查找表中的一个位置,该位置存储了这两个权重与对应激活值相乘后的结果。通过查表的方式,TL1 内核避免了大量的乘法运算,从而大幅提升了推理速度。
TL2 内核
TL2 内核与 TL1 内核的原理类似,也采用了查找表技术,但它更加极致,将每三个权重压缩成一个 5 比特的索引(1比特符号位 + 4比特索引位)。
这种方式进一步提高了压缩率,减少了存储空间和读取时间,但也增加了查找表的复杂度。TL2 内核更适用于内存带宽受限的场景,因为它能最大程度地减少数据读取量。
性能评测:速度与能耗的双重提升
为了评估 BitNet.cpp 的性能,研究人员在不同规模的模型(从 1.25 亿到 1000 亿参数)和不同架构的 CPU(ARM 和 x86)上进行了测试,涵盖了从小型到超大型的各种LLM模型,以及常见的CPU架构。
推理速度对比
测试结果表明,BitNet.cpp 在 ARM 和 x86 架构上均实现了显著的推理速度提升,尤其是在模型规模较大的情况下。 图1和图2展示了 BitNet.cpp 和 llama.cpp 在 Apple M2 和 Intel i7-13700H 芯片上运行不同规模 BitNet b1.58 模型的推理速度对比。可以看出,BitNet.cpp 的推理速度 consistently surpasses llama.cpp,尤其是在处理大型模型时,优势更加明显。
能耗对比
测试结果表明,BitNet.cpp 在降低能耗方面表现出色,尤其是在模型规模较大的情况下。 下表展示了 BitNet.cpp 和 llama.cpp 在 Apple M2 和 Intel i7-13700H 芯片上运行 7 亿、70 亿和 700 亿参数模型的能耗对比。可以看出,BitNet.cpp 的能耗 significantly lower than llama.cpp,尤其是在运行大型模型时,能耗优势更加突出。
CPU | Kernel | 700M (J/token) | 7B (J/token) | 70B (J/token) |
Apple M2 | llama.cpp | 0.314 | 3.013 | 28.02 |
Apple M2 | bitnet.cpp | 0.140 | 1.068 | 8.42 |
Intel i7-13700H | llama.cpp | 1.367 | 11.305 | N/A |
Intel i7-13700H | bitnet.cpp | 0.384 | 2.017 | 17.33 |
表1:不同规模 BitNet b1.58 模型在不同 CPU 上的能耗对比(bitnet.cpp vs. llama.cpp)
推理精度验证
为了验证 BitNet.cpp 的推理精度,研究人员随机选择了 1000 个提示,并将 BitNet.cpp 和 llama.cpp 生成的输出与 FP32 内核的输出进行了比较,以确保BitNet.cpp在加速和降低能耗的同时,不会牺牲模型的推理质量。结果表明,BitNet.cpp 实现了无损推理,其输出与 FP32 内核的输出完全一致,这证明了 BitNet.cpp 在保证推理速度和能耗效率的同时,也能保持模型的推理精度。
未来展望:拓展平台,优化训练,探索协同设计
BitNet.cpp 团队计划将 BitNet.cpp 扩展到更多平台和设备,包括移动设备、NPU 和 GPU,让更多用户能够在不同设备上体验 1 比特 LLM 的优势。未来还将进行 1 比特 LLM 训练优化,探索更高效的训练方法,并探索 1 比特 LLM 定制硬件和软件栈的协同设计,进一步提升 1 比特 LLM 的性能和效率。
相关链接
• BitNet.cpp GitHub 仓库: https://github.com/microsoft/BitNet
• BitNet 论文: https://arxiv.org/abs/2310.11453