会发生不同输入 LLM 为什么 上 GPU 在 相反的 不同
作者 | Anis Zakari
编译 | 岳扬
大少数技术工程师都了解,依赖库或依赖组件的版本不同都或者会造成系统行为发生变动。但在大言语模型(Large Language Models)畛域,由于算力需求庞大,在训练和推理义务中咱们都极度依赖 GPU。但是,很少有人真正看法到,改换 GPU 也会对 LLMs 的输入发生影响。
假设你想创立两个齐全分歧的开发环境:
本文将启动一次性试验来强调这一现象,说明差异出现的位置及其要素。
Note:假设对试验环节的重现或详细代码不感兴味,可以跳过本文展现代码片段,间接阅读“7. 为什么雷同的 inputs 和雷同的 LLMs 在两块不同 GPU 上生成的模型照应会有如此大的差异?”这局部内容。即使不看前面的代码片段,Conclusion 局部依然有助于咱们了解其中的原理。
01 为什么要写这篇文章?
有一天,我和一些人探讨为什么 OpenAI 和 Anthropic 的那些模型在设计时没有被构建为确定性的系统。我解释说,它们或者驳回了混合专家模型(Mixture of Experts, MoE)方法<sup>[1]</sup>,偶然不会将 tokens 路由给最优的专家模型,由于这些专家模型或者正忙于解决其余 tokens,所以或者会造成模型照应的不分歧。
另一个要素或者是 OpenAI 为了提高效率而对 queries 启动了批量解决。batches size 会依据传入的 queries 数量而变动,或者会扭转 GPU 的计算战略,从而造成不同的模型照应。
当有人指出,“不同的 GPU 也或者造成出现不同的模型照应,不是吗?”时,咱们之间的对话开局变得回味无穷起来了。
细心想一想……当咱们经常使用 OpenAI API 时,实践上是有一台远程主机帮咱们口头计算并前往模型照应。如今,假设这台机器并非总是在相反的算力基础设备上运转,那么最终失掉的模型照应就不会相反。
想到这一点,或者就会出现其余疑问:
这些疑问促使我想设置一个试验来突出这一现象,并探求它或者形成的影响有多大。
02 性能试验环境
为了突出这一现象,我将设置两个齐全相反的开发环境,它们惟一的区别在于其所经常使用的 GPU:第一个开发环境中经常使用的是 Nvidia Tesla T4,第二个开发环境经常使用的便是 Nvidia A10G。而后,咱们将经常使用 Mistral-7b-v0.1 启动测试,看看会出现什么。
要在 notebook 中运转试验,请依照以下步骤操作。
2.1 性能开发环境(Setup the environment)
1.性能 CUDA 版本
2.性能 transformers 和其余依赖
3.设置随机种子(random seeds)
注释 1:
仅设置 transformers.set_seed 应该就足够了,但我还是想要确保十拿九稳。
注释 2:
本例经常使用的是 Python 3.10。
2.2 加载 Mistral 模型
要从 Hugging Face 中加载 Mistral-7B-v0.1 模型,咱们须要在环境变量 HF_TOKEN 中设置 Hugging Face tokens。
本文将会经常使用量化版本的模型,降落计算精度来缩小 GPU 的内存占用。
2.3 经常使用 transformers 库中的 pipeline
咱们将经常使用 transformers 库中的 pipeline 来简化从大言语模型(LLMs)生成模型照应的环节。
为了确保模型输入是可预测和分歧的,咱们宿愿从大言语模型的 vocabulary 中继续预测出最有或者的 tokens,因此咱们可以将 top_k 设置为 1 或将 temperature 设置为凑近 0 的值。
此外,为了便捷起见,咱们将把
max_new_tokens
参数设置为 1,这样 LLMs 就能只用单个 token 成功揭示词。
当给出揭示词序列 “I enjoy walking in the” 时,大言语模型(LLMs)只会生成一个单词:“woods”。假设大言语模型(LLMs)正确地生成并输入了这个单词,咱们就可以继续启动试验了。
03 试验结果:T4 vs A10G
为了能够经常使用这两块 GPU,我经过 AWS SageMaker 启动了 ml.g4dn.xlarge (T4) 和 ml.g5.xlarge (A10G) 实例。
让咱们尝试运转一个便捷的 query :
T4 和 A10G 给我的模型照应是一样的:
到目前为止一切停顿顺利。不过,这只是一个冗长的 query 。在 RAG(检索增强生成)的运行场景里,咱们通常会解决不可胜数个 tokens 。如今让咱们经常使用在 Hugging Face 上托管的 llama-2-arxiv-papers-chunked 数据集来启动更大规模的 query 测试。
在上方的代码示例中,我将模拟 RAG 的上班形式,经常使用数据集索引 0、4518、4519 和 799 处失掉的文本片段。其中第 4518 和 4519 个数据块(chunks)探讨了 “Llama 2”,而其余片段则没有提及。咱们等候 LLMs 能基于这些高低文消息回答:“Llama 2 有什么特意之处?”该揭示词大略有 1, 个 tokens 长。
T4 模型的输入如下:
A10G 模型的输入如下:
确实很幽默。乍一看,由于两个模型照应扫尾相反,区别却不太清楚。但在“等等(etc)……”之后,两者就有所差异了。
T4 模型输入如下:“etc… This also means you can trust the output more since everything inside will be consistent across different runs!…”
A10G 模型输入如下:“etc… This also means you can be more confident when asking questions specifically related to topics covered within those texts…”
04 T4 Colab vs T4 SageMaker
想知道经常使用相反 GPU 的两个开发环境能否会发生相反的模型输入?我启动了一系列测试,结果确实齐全相反。
05 为什么相反的用户输入(inputs)和相反的 LLMs 在两个 GPUs 上生成的答案会如此不同?
最终,这些模型照应由于 LLMs 的自回归个性而变得一模一样。由于下一个 token 是依据之前的 tokens 选用的,任何纤细的变动都会引发一连串的连锁反响,就像蝴蝶效应(butterfly effect)一样。
请留意,这些模型照应并没有像揭示词中所要求的那样基于所提供的高低文。LLMs 并没有齐全遵照指点性揭示词(instructions),但这并不是很关键。
由于咱们假定 LLMs 总是基于前面的 tokens 选用概率(probabilities)最高的 token,所以咱们可以必需,区别在于如何在 GPU 上计算该概率(probabilities),上方让咱们来看一看如何计算该概率~
06 计算 tokens 的选用概率(probabilities)
为了打印出每个被选中 token 的概率,咱们将绕过惯例解决流程(pipeline),间接经常使用 tokenizer 和
model.generate
方法。这样咱们就能设置
return_dict_in_generate=True
和
output_scores=True
。接着,咱们就可以启动计算(compute)操作、对其启动归一化操作(normalize),并将 transition scores(译者注:在人造言语解决畛域,尤其是经常使用自回归模型生成文本时,模型会为每个 next token 调配一个概率分数,这个分数反映了该 token 作为 tokens 序列中 next token 的或者性大小。) 转换为概率(probabilities)。
上述代码会显示每个 token 的 ID、解码后的 token 以及其对应的概率(probability)。此处我只列出关系的模型输入内容,由于完整的内容十分长。
A10G Output:
好了,如今事件变得越来越幽默了。T4 和 A10G 上的概率值(probabilities)并不齐全分歧。普通状况下,这样并不会影响 tokens 的排序序列(不可在生成的 tokens 序列中发觉就任何不同),但有时刻确实会形成影响。
例如,在 T4 模型中,“trust” 出现的概率为 18.74 %,而在 A10G 上,“be” 出现的概率则更高,到达了 18.62 %。从这一点来看,由于大言语模型的自回归个性,生成的内容将会出现偏向(diverge)。
注释:量化大言语模型会降落计算精度(calculation precision),造成这类差异变得更为经常出现。
如今,一个十分正当的疑问就出现了:“为什么计算结果会由于 GPU 的不同而发生差异呢?”
07 为什么 GPU 不同,模型运算结果也不同?
只管我不是 CUDA expert(译者注:这类人能够熟练经常使用 CUDA C/C++ 编程言语来开发高性能的并行计算运行,并了解如何优化 GPU 上的计算义务来取得最佳性能。),但我启动过一些钻研。不同 GPU 之间的计算差异可以归因于以下几个要素:
并行计算解决(Parallel Computation Handling):
GPUs 的特点是能够高效地并行解决少量的计算义务。但是,不同 GPU 在治理这些并行义务时或者会有所差异,从而影响到运算顺序以及内存的访问形式。
这一点十分关键,由于在编程环节中,即使是数值大小相差很大的便捷加法也或者是 non-associative,从而影响到准确计算(precise calculations)的准确性。所谓 “Non-associativity” 是指:(a + b) + c ≠ a + (b + c)。
因此,计算义务会被宰割开来,独立启动解决,而后以 non-associative 形式组合在一同。因此,这些局部的内容如何从新组合会影响到最终结果。
这里有一个关于 non-associative computation 的便捷示例:
关于大言语模型(LLMs),数百万次的计算或者会由于重复出现的庞大误差而造成出现偏向(diverge),进而影响到序列生成环节中的字词选用。
配件架构(Hardware Architecture):
不同型号的 GPU,如 Nvidia Tesla T4 和 Nvidia A10G ,具有不同的配件架构。这些配件架构能够优化模型各个方面的性能,包含并行解决才干(parallel processing capabilities)、内存带宽(memory bandwidth)和计算单元(compute units)。
例如,T4 模型驳回了 Turing<sup>[2]</sup> 架构,而 A10G 模型基于 Ampere<sup>[3]</sup> 架构。
不同的模型架构象征着在浮点运算(floating-point arithmetic)、内存访问形式(memory access patterns)和其余底层操作上有着不同的成功形式。即使这些成功形式(implementations)存在纤细差异,也或者会造成计算结果出现差异。
例如,与针对更高计算精度而启动优化的模型架构相比,为了计算速度而优化的模型架构或者会发生不同的模型照应,即使两者都在口头相反的浮点运算。
模型量化的影响(Quantization Effects):
经过模型量化(Quantizing)来降落计算精度可以节俭内存资源和计算资源,但这样做也会引入额外的误差源(sources of error)。这些误差的影响因 GPU 对低精度运算(lower precision arithmetic)的解决形式不同而不同。
由于模型量化(quantization)环节中触及到对数值的近似解决,因此不同的 GPU 在解决这些近似值时或者会有所差异,从而最终会造成 token 的预测概率发生变动。
08 经常使用多个 GPU 水平裁减 LLMs 时须要留意什么?
这个疑问问得十分好,十分感谢!: )
假设只是便捷地参与相反型号的 GPU 数量(例如,从单个 A10G GPU 裁减到领有 4 个 A10G GPU 的实例),能否还有必要担忧?
经常使用多个 GPU 启动推理时,有几种战略可供选用:
09 Conclusion
咱们曾经证实了,即使是相反的开发环境(environment)、系统性能(settings)和随机种子(seed),不同的 GPU 也会造成 LLMs 发生不同的结果。随着揭示词长度的增长,这种不准确性(inaccuracies)也会随之参与,由于更长的揭示词须要更多的算力,这会加剧不准确性(inaccuracies)的流传并促成两个 GPU 之间的差异。此外,在启动模型量化的状况下,这种效应愈加清楚。
我并不是说这种状况必定是劫难性的,但这是咱们在解决 LLMs 的部署时须要留意的一个要素。
假设咱们开发时经常使用的 GPU 与消费环境中经常使用的 GPU 不同,应该设置测试试验确保性能依然坚持在可接受的范围内。假设咱们方案将 LLMs 裁减到领有不同 GPU 的新实例上,这一点也很关键。
假设你坚持读到了最后,那我可太快乐了,宿愿你会青睐这篇文章。假设你青睐的话,宿愿你能给我点赞,激励我继续写作,也欢迎在评论区中分享你的想法。
Anis Zakari
I’m a passionate ML/AI Engineer based in Paris. I am particularly interested in NLP, LLM, Software Engineering and Cloud Engineering subjects
文中链接
[1]
[2]
[3]
原文链接: