使用自定义的硬件进行训练¶
运行模型训练和推理所使用的硬件对性能有很大影响。关于 GPU 的深入探讨,请务必查看 Tim Dettmer 的优秀 博客文章。
让我们来看一些关于 GPU 设置的实际建议。
GPU¶
当你训练更大的模型时,基本上有三种选择:
- 更大的 GPU
- 更多的 GPU
- 更多的 CPU 和 NVMe(通过 DeepSpeed-Infinity 卸载)
我们从单个 GPU 的情况开始谈起。
电源和冷却¶
如果你购买了昂贵的高端 GPU,请确保为其提供正确的电源和充分的冷却。
电源:
一些高端消费级 GPU 卡有 2 个甚至 3 个 PCI-E 8 针电源接口。确保每个接口都插有独立的 12V PCI-E 8 针电缆。不要使用同一根电缆两端的两个分叉头(通常称为猪尾巴电缆)。例如,如果你的 GPU 有两个电源接口,那么你应该从电源供应器 (PSU) 连接两根 PCI-E 8 针电缆到 GPU,而不是一根带有两个 PCI-E 8 针连接头的电缆。否则,你无法充分发挥卡的性能。
每个 PCI-E 8 针电源电缆需要插入 PSU 的 12V 电源线,可以提供高达 150W 的功率。
有些其他卡可能使用 PCI-E 12 针连接器,这些连接器可以提供高达 500-600W 的功率。
低端卡可能使用 6 针连接器,这些连接器可以提供高达 75W 的功率。
此外,你还需要一个高质量的 PSU,它能提供稳定的电压。一些低质量的 PSU 可能无法为卡提供所需的稳定电压,以使其在峰值状态下运行。
当然,PSU 必须有足够的剩余瓦数来为卡供电。
冷却:
当 GPU 过热时,它会开始降低性能,甚至在过热时关闭。很难确定 GPU 在高负载下最佳的目标温度是多少,但通常只要低于 +80°C 就可以了,而 70-75°C 是一个非常好的范围。通常在温度达到约 84-90°C 时,性能开始下降。除了降低性能外,长时间的高温还可能缩短 GPU 的使用寿命。
接下来,我们来看看使用多个 GPU 时最重要的方面之一:连接性。
多 GPU 连接性¶
如果你使用多个 GPU,卡之间的互连方式可能会对总训练时间产生巨大影响。如果 GPU 在同一物理节点上,你可以运行:
nvidia-smi topo -m
这将告诉你 GPU 如何互连。在具有双 GPU 并且通过 NVLink 连接的机器上,你可能会看到类似以下内容:
而在没有 NVLink 的不同机器上,你可能会看到:
报告包括以下图例:
所以第一个报告中的 NV2 告诉我们 GPU 之间通过 2 条 NVLink 连接,而第二个报告中的 PHB 表明我们有一个典型的消费级 PCIe+桥接设置。
检查你的设置中使用的是哪种连接类型。其中一些可以使卡之间的通信更快(例如 NVLink),而另一些则较慢(例如 PHB)。
根据使用的可扩展性解决方案的不同,连接速度的影响可能是重大或轻微的。如果 GPU 需要很少同步(如 DDP),较慢的连接影响较小。如果 GPU 需要频繁互相发送消息(如 ZeRO-DP),那么更快的连接变得非常关键,以实现更快的训练。
NVLink¶
NVLink 是由 Nvidia 开发的一种基于线缆的串行多通道近程通信链路。
每一代新产品的带宽都会更快。例如,根据 Nvidia Ampere GA102 GPU 架构白皮书 中的引用:
第三代 NVLink® GA102 GPU 使用 NVIDIA 的第三代 NVLink 接口,该接口包括四条 x4 链路,每条链路在两个 GPU 之间提供 14.0625 GB/s 的双向带宽。四条链路总共提供 56.25 GB/s 的双向带宽,以及 112.5 GB/s 的总带宽。两块 RTX 3090 GPU 可以通过 NVLink 连接以实现 SLI。(注意,不支持 3-Way 和 4-Way SLI 配置。)
因此,在 nvidia-smi topo -m 的输出报告中,NVX 的 X 越高越好。这取决于你的 GPU 架构。
让我们比较一下在 openai-community/gpt2 语言模型上使用小样本 wikitext 进行训练的执行情况。
结果如下:
| NVLink | 时间 (秒) |
|---|---|
| Y | 101 |
| N | 131 |
可以看到,使用 NVLink 完成训练大约快 23%。在第二个基准测试中,我们使用 NCCL_P2P_DISABLE=1 告诉 GPU 不使用 NVLink。
以下是完整的基准测试代码和输出:
# DDP 使用 NVLink
rm -r /tmp/test-clm; CUDA_VISIBLE_DEVICES=0,1 torchrun \
--nproc_per_node 2 examples/pytorch/language-modeling/run_clm.py --model_name_or_path openai-community/gpt2 \
--dataset_name wikitext --dataset_config_name wikitext-2-raw-v1 --do_train \
--output_dir /tmp/test-clm --per_device_train_batch_size 4 --max_steps 200
{'train_runtime': 101.9003, 'train_samples_per_second': 1.963, 'epoch': 0.69}
# DDP 不使用 NVLink
rm -r /tmp/test-clm; CUDA_VISIBLE_DEVICES=0,1 NCCL_P2P_DISABLE=1 torchrun \
--nproc_per_node 2 examples/pytorch/language-modeling/run_clm.py --model_name_or_path openai-community/gpt2 \
--dataset_name wikitext --dataset_config_name wikitext-2-raw-v1 --do_train \
--output_dir /tmp/test-clm --per_device_train_batch_size 4 --max_steps 200
{'train_runtime': 131.4367, 'train_samples_per_second': 1.522, 'epoch': 0.69}
硬件:2 块 TITAN RTX,每块 24GB 内存 + 2 条 NVLink (NV2 在 nvidia-smi topo -m 中)
软件:pytorch-1.8-to-be + cuda-11.0 / transformers==4.3.0.dev0