# 使用分布式数据并行（DDP）进行多 GPU 微调

假设我们有多张 GPU，并且想要使用所有 GPU 对模型进行微调！为此，最直接的策略是使用分布式数据并行（Distributed Data Parallel, DDP），它会在每个 GPU 设备上创建模型的一个副本，在训练期间为每个副本提供数据集中不同的样本，并在每次优化器步骤时汇总它们对权重更新的贡献。

为什么我们要这样做？随着训练中加入更多 GPU，我们在每步训练中处理的样本数量会增加，使每次梯度更新更稳定，并且随着每增加一张 GPU，大幅提高训练吞吐量。

下面是如何使用 Unsloth 的命令行界面（CLI）执行此操作的逐步指南！

**注意：** Unsloth 的 DDP 将适用于你任何的训练脚本，而不仅限于通过我们的 CLI！更多细节在下方。

#### 从源码安装 Unsloth

我们将从 GitHub 克隆 Unsloth 并进行安装。请考虑使用一个 [虚拟环境](https://docs.python.org/3/tutorial/venv.html)；我们喜欢使用 `uv venv –python 3.12 && source .venv/bin/activate`，但任何虚拟环境创建工具都可以。

```bash
git clone https://github.com/unslothai/unsloth.git
cd unsloth
pip install .
```

#### 选择用于微调的目标模型和数据集

在本演示中，我们将微调 [Qwen/Qwen3-8B](https://huggingface.co/Qwen/Qwen3-8B) 在 [yahma/alpaca-cleaned](https://huggingface.co/datasets/yahma/alpaca-cleaned) 聊天数据集上。这是一个有监督微调（Supervised Fine-Tuning，SFT）工作负载，通常用于将基础模型调整为所需的对话风格，或提高模型在下游任务上的性能。

### 使用 Unsloth CLI！

首先，让我们查看内置于 CLI 的帮助信息（我们在若干位置用“...”作了简略）：

{% code expandable="true" %}

```bash
$ python unsloth-cli.py --help
用法：unsloth-cli.py [-h] [--model_name MODEL_NAME] [--max_seq_length MAX_SEQ_LENGTH] [--dtype DTYPE]
                      [--load_in_4bit] [--dataset DATASET] [--r R] [--lora_alpha LORA_ALPHA]
                      [--lora_dropout LORA_DROPOUT] [--bias BIAS]
                      [--use_gradient_checkpointing USE_GRADIENT_CHECKPOINTING]
…

🦥 使用 unsloth 更快地微调你的大模型！

选项：
  -h, --help            显示此帮助信息并退出

🤖 模型选项：
  --model_name MODEL_NAME
                        要加载的模型名称
  --max_seq_length MAX_SEQ_LENGTH
                        最大序列长度，默认是 2048。我们内部自动支持 RoPE 缩放
                        ！
…

🧠 LoRA 选项：
  这些选项用于配置 LoRA 模型。

  --r R                 LoRA 模型的秩（rank），默认是 16。（常见取值：8、16、32、64、128）
  --lora_alpha LORA_ALPHA
                        LoRA 的 alpha 参数，默认是 16。（常见取值：8、16、32、64、128）
…

🎓 训练选项：
  --per_device_train_batch_size PER_DEVICE_TRAIN_BATCH_SIZE
                        训练时每个设备的批大小，默认是 2。
  --per_device_eval_batch_size PER_DEVICE_EVAL_BATCH_SIZE
                        评估时每个设备的批大小，默认是 4。
  --gradient_accumulation_steps GRADIENT_ACCUMULATION_STEPS
                        梯度累积步数，默认是 4。
…
```

{% endcode %}

这应该能让你了解可以传递给 CLI 以训练模型的可用选项！

对于多 GPU 训练（在本例中为 DDP），我们将使用 [torchrun](https://docs.pytorch.org/docs/stable/elastic/run.html) 启动器，它允许你在单节点或多节点环境中启动多个分布式训练进程。在我们的例子中，我们将重点放在单节点（即一台机器）情况，配备两块 H100 GPU。

让我们也通过使用 `nvidia-smi` 命令行工具检查一下 GPU 状态：

{% code expandable="true" %}

```bash
$ nvidia-smi
Mon Nov 24 12:53:00 2025       
+-----------------------------------------------------------------------------------------+
| NVIDIA-SMI 580.95.05              驱动版本: 580.95.05      CUDA 版本: 13.0     |
+-----------------------------------------+------------------------+----------------------+
| GPU  名称                 持久化模式 | 总线 ID           显示 A | 易失性不可纠正 ECC |
| 风扇  温度   性能          功耗:使用/上限 |           内存使用情况 | GPU 利用率  计算 模式 |
|                                         |                        |               MIG 模式 |
|=========================================+========================+======================|
|   0  NVIDIA H100 80GB HBM3          On  |   00000000:04:00.0 Off |                    0 |
| N/A   32C    P0             69W /  700W |       0MiB /  81559MiB |      0%      默认 |
|                                         |                        |             已禁用 |
+-----------------------------------------+------------------------+----------------------+
|   1  NVIDIA H100 80GB HBM3          On  |   00000000:05:00.0 Off |                    0 |
| N/A   30C    P0             68W /  700W |       0MiB /  81559MiB |      0%      默认 |
|                                         |                        |             已禁用 |
+-----------------------------------------+------------------------+----------------------+

+-----------------------------------------------------------------------------------------+
| 进程：                                                                                 |
|  GPU   GI   CI              PID   类型   进程名称                        GPU 内存 |
|        ID   ID                                                               使用      |
|=========================================================================================|
|  未发现正在运行的进程                                                               |
+-----------------------------------------------------------------------------------------+
```

{% endcode %}

太好了！我们有两块 H100 GPU，正如预期。由于目前没有进行任何训练或将模型加载到内存，两者的内存使用均为 0MiB。

要开始你的训练运行，请发出如下命令：

{% code expandable="true" %}

```bash
# 必需：
#   --model_name
#   --dataset
# 可选；可在这些参数上进行试验：
#   --learning_rate、--max_seq_length、--per_device_train_batch_size、--gradient_accumulation_steps、--max_steps
# 在训练结束时保存模型：
#   --save_model

torchrun --nproc_per_node=2 unsloth-cli.py \
  --model_name=Qwen/Qwen3-8B \
  --dataset=yahma/alpaca-cleaned \
  --learning_rate=2e-5 \
  --max_seq_length=2048 \
  --per_device_train_batch_size=1 \
  --gradient_accumulation_steps=4 \
  --max_steps=1000 \
  --save_model
```

{% endcode %}

如果你有更多的 GPU，可以相应地设置 `--nproc_per_node` 以利用它们。

**注意：** 你可以将该 `torchrun` 启动器用于你任何的 Unsloth 训练脚本，包括 [脚本](https://github.com/unslothai/notebooks/tree/main/python_scripts) 从我们的免费 Colab 笔记本转换而来，并且在使用 >1 张 GPU 训练时 DDP 会自动启用！

再次查看 `nvidia-smi` 在训练进行中时：

{% code expandable="true" %}

```bash
$ nvidia-smi
Mon Nov 24 12:58:42 2025
+-----------------------------------------------------------------------------------------+
| NVIDIA-SMI 580.95.05              驱动版本: 580.95.05      CUDA 版本: 13.0     |
+-----------------------------------------+------------------------+----------------------+
| GPU  名称                 持久化模式 | 总线 ID           显示 A | 易失性不可纠正 ECC |
| 风扇  温度   性能          功耗:使用/上限 |           内存使用情况 | GPU 利用率  计算 模式 |
|                                         |                        |               MIG 模式 |
|=========================================+========================+======================|
|   0  NVIDIA H100 80GB HBM3          On  |   00000000:04:00.0 Off |                    0 |
| N/A   38C    P0            193W /  700W |   18903MiB /  81559MiB |     25%      默认 |
|                                         |                        |             已禁用 |
+-----------------------------------------+------------------------+----------------------+
|   1  NVIDIA H100 80GB HBM3          On  |   00000000:05:00.0 Off |                    0 |
| N/A   37C    P0            199W /  700W |   18905MiB /  81559MiB |     28%      默认 |
|                                         |                        |             已禁用 |
+-----------------------------------------+------------------------+----------------------+

+-----------------------------------------------------------------------------------------+
| 进程：                                                                                 |
|  GPU   GI   CI              PID   类型   进程名称                        GPU 内存 |
|        ID   ID                                                               使用      |
|=========================================================================================|
|    0   N/A  N/A            4935      C   ...und/unsloth/.venv/bin/python3      18256MiB |
|    0   N/A  N/A            4936      C   ...und/unsloth/.venv/bin/python3        630MiB |
|    1   N/A  N/A            4935      C   ...und/unsloth/.venv/bin/python3        630MiB |
|    1   N/A  N/A            4936      C   ...und/unsloth/.venv/bin/python3      18258MiB |
+-----------------------------------------------------------------------------------------+
```

{% endcode %}

我们可以看到两块 GPU 现在每块 H100 大约使用 \~19GB 的显存！

检查训练日志，我们看到能够以约 \~1.1 次迭代/秒的速度训练。即使我们增加更多 GPU，这个训练速度也大致保持恒定，因此我们的训练吞吐量会随着 GPU 数量的增加近似线性增长！

### 训练指标

我们在几个短的秩为 16 的 LoRA 微调上进行了测试，使用了 [unsloth/Llama-3.2-1B-Instruct](https://huggingface.co/unsloth/Llama-3.2-1B-Instruct) 在 [yahma/alpaca-cleaned](https://huggingface.co/datasets/yahma/alpaca-cleaned) 数据集，以演示使用多 GPU 的 DDP 训练时提高的训练吞吐量。

<figure><img src="/files/20e491316b8f7a44944f2f18aa51bf5c027d7cf8" alt="" width="375"><figcaption></figcaption></figure>

上图比较了两次 Llama-3.2-1B-Instruct LoRA 微调在 500 个训练步骤内的训练损失，单 GPU 训练（粉色）与多 GPU DDP 训练（蓝色）。

注意损失曲线在尺度和趋势上匹配，但在其他方面有 *些* 不同，因为 *多 GPU 训练在每步处理的训练数据是单 GPU 的两倍*。这导致了稍有不同的训练曲线，在逐步基础上具有更少的变动。

<figure><img src="/files/8032b41222272c0e2e886853ce3d982d801ab3cd" alt="" width="375"><figcaption></figcaption></figure>

上图绘制了相同两次微调的训练进展。

注意多 GPU 的 DDP 训练在遍历一轮训练数据时所需的步数仅为单 GPU 训练的一半。这是因为每个 GPU 可以在每步处理一个独立的小批次（大小为 `per_device_train_batch_size`）。然而，由于模型权重更新需要分布式通信，DDP 训练的每步时间略慢。随着 GPU 数量的增加，训练吞吐量会继续近似线性增长（但分布式通信会带来一个小的且逐渐增大的开销）。

这些相同的损失和训练轮次进度行为也适用于 QLoRA 微调，在 QLoRA 中我们以 4 位精度加载基础模型以节省更多的 GPU 内存。这在 GPU 显存有限的情况下训练大型模型时尤其有用：

<figure><img src="/files/ec9afe7fabf48c449e4c2023ae315f0251674be3" alt="" width="375"><figcaption></figcaption></figure>

在 500 个训练步骤内比较两次 Llama-3.2-1B-Instruct QLoRA 微调的训练损失，单 GPU 训练（橙色）与多 GPU DDP 训练（紫色）。

<figure><img src="/files/08f8e4368d26664707fbf878920c09c21362e576" alt="" width="375"><figcaption></figcaption></figure>

相同两次微调的训练进度比较。


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://unsloth.ai/docs/zh/ji-chu/multi-gpu-training-with-unsloth/ddp.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
