From 90e20c49faf457639b7c6831467a5d11edd4edf3 Mon Sep 17 00:00:00 2001 From: ice Date: Sat, 27 Sep 2025 09:33:20 +0800 Subject: [PATCH 1/6] =?UTF-8?q?feat:=20=E6=96=87=E6=A1=A3=E6=94=B9?= =?UTF-8?q?=E8=BF=9B?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../distributed/utils/global_scatter_cn.rst | 62 +++++++++++++++---- 1 file changed, 49 insertions(+), 13 deletions(-) diff --git a/docs/api/paddle/distributed/utils/global_scatter_cn.rst b/docs/api/paddle/distributed/utils/global_scatter_cn.rst index af101e3ea86..f812688f763 100644 --- a/docs/api/paddle/distributed/utils/global_scatter_cn.rst +++ b/docs/api/paddle/distributed/utils/global_scatter_cn.rst @@ -9,28 +9,28 @@ global_scatter global_scatter 根据 local_count 将 x 的数据分发到 n_expert * world_size 个 expert,然后根据 global_count 接收数据。 其中 expert 是用户定义的专家网络,n_expert 是指每张卡拥有的专家网络数目,world_size 是指运行网络的显卡数目。 -如下图所示,world_size 是 2,n_expert 是 2,x 的 batch_size 是 4,local_count 是[2, 0, 2, 0],0 卡的 global_count 是[2, 0, , ], -1 卡的 global_count 是[2, 0, ,](因为篇幅问题,这里只展示在 0 卡运算的数据),在 global_scatter 算子里, -local_count[i]代表向第 (i // n_expert)张卡的第 (i % n_expert)个 expert 发送 local_expert[i]个数据, -global_count[i]代表从第 (i // n_expert)张卡接收 global_count[i]个数据给本卡的 第(i % n_expert)个 expert。 +如下图所示,world_size 是 2,n_expert 是 2,x 的 batch_size 是 4,local_count 是[2, 0, 2, 0],0 卡的 global_count 是 [2, 0, , ], +1 卡的 global_count 是 [2, 0, ,](因为篇幅问题,这里只展示在 0 卡运算的数据),在 global_scatter 算子里, +local_count[i] 代表向第 (i // n_expert) 张卡的第 (i % n_expert) 个 expert 发送 local_expert[i] 个数据, +global_count[i]代表从第 (i // n_expert) 张卡接收 global_count[i] 个数据给本卡的 第(i % n_expert)个 expert。 图中的 rank0 代表第 0 张卡,rank1 代表第 1 张卡。 global_scatter 发送数据的流程如下: -local_count[0]代表从 x 里取出 2 个 batch 的数据向第 0 张卡的第 0 个 expert 发送 2 个数据; +local_count[0] 代表从 x 里取出 2 个 batch 的数据向第 0 张卡的第 0 个 expert 发送 2 个数据; -local_count[1]代表从 x 里取出 0 个 batch 的数据向第 0 张卡的第 1 个 expert 发送 0 个数据; +local_count[1] 代表从 x 里取出 0 个 batch 的数据向第 0 张卡的第 1 个 expert 发送 0 个数据; -local_count[2]代表从 x 里取出 2 个 batch 的数据向第 1 张卡的第 0 个 expert 发送 2 个数据; +local_count[2] 代表从 x 里取出 2 个 batch 的数据向第 1 张卡的第 0 个 expert 发送 2 个数据; -local_count[3]代表从 x 里取出 0 个 batch 的数据向第 1 张卡的第 1 个 expert 发送 0 个数据; +local_count[3] 代表从 x 里取出 0 个 batch 的数据向第 1 张卡的第 1 个 expert 发送 0 个数据; -所以第 0 张卡的 global_count[0]等于 2,代表从第 0 张卡接收 2 个 batch 的数据给第 0 个 expert; +所以第 0 张卡的 global_count[0] 等于 2,代表从第 0 张卡接收 2 个 batch 的数据给第 0 个 expert; -第 0 张卡的 global_count[1]等于 0,代表从第 0 张卡接收 0 个 batch 的数据给第 1 个 expert; +第 0 张卡的 global_count[1] 等于 0,代表从第 0 张卡接收 0 个 batch 的数据给第 1 个 expert; -第 1 张卡的 global_count[0]等于 2,代表从第 0 张卡接收 2 个 batch 的数据给第 0 个 expert; +第 1 张卡的 global_count[0] 等于 2,代表从第 0 张卡接收 2 个 batch 的数据给第 0 个 expert; -第 1 张卡的 global_count[1]等与 0,代表从第 0 张卡接收 0 个 batch 的数据给第 1 个 expert。 +第 1 张卡的 global_count[1] 等与 0,代表从第 0 张卡接收 0 个 batch 的数据给第 1 个 expert。 .. image:: ../img/global_scatter_gather.png @@ -52,4 +52,40 @@ Tensor,从所有 expert 接收的数据,按照每个 expert 排列。 代码示例 ::::::::: -COPY-FROM: paddle.distributed.utils.global_scatter + +.. code-block:: python + + # required: distributed + import numpy as np + import paddle + from paddle.distributed import init_parallel_env + + # 初始化并行环境 + init_parallel_env() + n_expert = 2 + world_size = 2 + d_model = 2 + in_feat = d_model + local_input_buf = np.array([[1, 2],[3, 4],[5, 6],[7, 8],[9, 10]], dtype=np.float32) + if paddle.distributed.ParallelEnv().local_rank == 0: + local_count = np.array([2, 1, 1, 1]) + global_count = np.array([2, 1, 1, 1]) + else: + local_count = np.array([1, 1, 2, 1]) + global_count = np.array([1, 1, 2, 1]) + local_input_buf = paddle.to_tensor(local_input_buf, dtype="float32", stop_gradient=False) + local_count = paddle.to_tensor(local_count, dtype="int64") + global_count = paddle.to_tensor(global_count, dtype="int64") + a = paddle.distributed.utils.global_scatter(local_input_buf, local_count, global_count) + a.stop_gradient = False + print(a) + # rank 0 输出: [[1, 2], [3, 4], [1, 2], [5, 6], [3, 4]] + # rank 1 输出: [[7, 8], [5, 6], [7, 8], [9, 10], [9, 10]] + # backward test + c = a * a + c.backward() + print("local_input_buf.grad: ", local_input_buf.grad) + # rank 0 输出: [[2, 4], [6, 8], [10, 12], [14, 16], [18, 20]] + # rank 1 输出: [[2, 4], [6, 8], [10, 12], [14, 16], [18, 20]] + # 喵喵喵AwA + From 843fc4fc1989af85e4d50167b215f29619fef9c5 Mon Sep 17 00:00:00 2001 From: ice Date: Sat, 27 Sep 2025 09:35:29 +0800 Subject: [PATCH 2/6] =?UTF-8?q?feat:=20=E6=96=87=E6=A1=A3=E4=BC=98?= =?UTF-8?q?=E5=8C=96?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- docs/api/paddle/distributed/utils/global_scatter_cn.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/api/paddle/distributed/utils/global_scatter_cn.rst b/docs/api/paddle/distributed/utils/global_scatter_cn.rst index f812688f763..e41560a9346 100644 --- a/docs/api/paddle/distributed/utils/global_scatter_cn.rst +++ b/docs/api/paddle/distributed/utils/global_scatter_cn.rst @@ -12,7 +12,7 @@ global_scatter 根据 local_count 将 x 的数据分发到 n_expert * world_size 如下图所示,world_size 是 2,n_expert 是 2,x 的 batch_size 是 4,local_count 是[2, 0, 2, 0],0 卡的 global_count 是 [2, 0, , ], 1 卡的 global_count 是 [2, 0, ,](因为篇幅问题,这里只展示在 0 卡运算的数据),在 global_scatter 算子里, local_count[i] 代表向第 (i // n_expert) 张卡的第 (i % n_expert) 个 expert 发送 local_expert[i] 个数据, -global_count[i]代表从第 (i // n_expert) 张卡接收 global_count[i] 个数据给本卡的 第(i % n_expert)个 expert。 +global_count[i] 代表从第 (i // n_expert) 张卡接收 global_count[i] 个数据给本卡的 第(i % n_expert)个 expert。 图中的 rank0 代表第 0 张卡,rank1 代表第 1 张卡。 global_scatter 发送数据的流程如下: From 8412c2addd537dd9ad478f209077311f732bff6b Mon Sep 17 00:00:00 2001 From: ice Date: Sat, 27 Sep 2025 22:02:02 +0800 Subject: [PATCH 3/6] =?UTF-8?q?remove:=20=E5=BC=82=E5=B8=B8=20=E5=BC=95?= =?UTF-8?q?=E7=94=A8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../distributed/utils/global_scatter_cn.rst | 39 ------------------- 1 file changed, 39 deletions(-) diff --git a/docs/api/paddle/distributed/utils/global_scatter_cn.rst b/docs/api/paddle/distributed/utils/global_scatter_cn.rst index e41560a9346..83629999150 100644 --- a/docs/api/paddle/distributed/utils/global_scatter_cn.rst +++ b/docs/api/paddle/distributed/utils/global_scatter_cn.rst @@ -50,42 +50,3 @@ local_count[3] 代表从 x 里取出 0 个 batch 的数据向第 1 张卡的第 ::::::::: Tensor,从所有 expert 接收的数据,按照每个 expert 排列。 -代码示例 -::::::::: - -.. code-block:: python - - # required: distributed - import numpy as np - import paddle - from paddle.distributed import init_parallel_env - - # 初始化并行环境 - init_parallel_env() - n_expert = 2 - world_size = 2 - d_model = 2 - in_feat = d_model - local_input_buf = np.array([[1, 2],[3, 4],[5, 6],[7, 8],[9, 10]], dtype=np.float32) - if paddle.distributed.ParallelEnv().local_rank == 0: - local_count = np.array([2, 1, 1, 1]) - global_count = np.array([2, 1, 1, 1]) - else: - local_count = np.array([1, 1, 2, 1]) - global_count = np.array([1, 1, 2, 1]) - local_input_buf = paddle.to_tensor(local_input_buf, dtype="float32", stop_gradient=False) - local_count = paddle.to_tensor(local_count, dtype="int64") - global_count = paddle.to_tensor(global_count, dtype="int64") - a = paddle.distributed.utils.global_scatter(local_input_buf, local_count, global_count) - a.stop_gradient = False - print(a) - # rank 0 输出: [[1, 2], [3, 4], [1, 2], [5, 6], [3, 4]] - # rank 1 输出: [[7, 8], [5, 6], [7, 8], [9, 10], [9, 10]] - # backward test - c = a * a - c.backward() - print("local_input_buf.grad: ", local_input_buf.grad) - # rank 0 输出: [[2, 4], [6, 8], [10, 12], [14, 16], [18, 20]] - # rank 1 输出: [[2, 4], [6, 8], [10, 12], [14, 16], [18, 20]] - # 喵喵喵AwA - From 895eb14cc0c8e3edda1d24bc64d35abc4394ce77 Mon Sep 17 00:00:00 2001 From: ice Date: Sun, 28 Sep 2025 10:33:23 +0800 Subject: [PATCH 4/6] =?UTF-8?q?feat:=20=E4=BB=A3=E7=A0=81=E5=9D=97?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../distributed/utils/global_scatter_cn.rst | 38 +++++++++++++++++++ 1 file changed, 38 insertions(+) diff --git a/docs/api/paddle/distributed/utils/global_scatter_cn.rst b/docs/api/paddle/distributed/utils/global_scatter_cn.rst index 83629999150..41e0e4ba0ff 100644 --- a/docs/api/paddle/distributed/utils/global_scatter_cn.rst +++ b/docs/api/paddle/distributed/utils/global_scatter_cn.rst @@ -50,3 +50,41 @@ local_count[3] 代表从 x 里取出 0 个 batch 的数据向第 1 张卡的第 ::::::::: Tensor,从所有 expert 接收的数据,按照每个 expert 排列。 +代码示例 +::::::::: + +.. code-block:: python + >>> # doctest: +REQUIRES(env:DISTRIBUTED) + >>> import paddle + >>> from paddle.distributed import init_parallel_env + >>> from paddle.distributed.utils import moe_utils + >>> init_parallel_env() + >>> n_expert = 2 + >>> world_size = 2 + >>> d_model = 2 + >>> in_feat = d_model + >>> local_input_buf = paddle.to_tensor( + ... [[1, 2],[3, 4],[5, 6],[7, 8],[9, 10]], + ... dtype='float32', + ... stop_gradient=False + ... ) + >>> if paddle.distributed.ParallelEnv().local_rank == 0: + ... local_count = paddle.to_tensor([2, 1, 1, 1], dtype="int64") + ... global_count = paddle.to_tensor([2, 1, 1, 1], dtype="int64") + >>> else: + ... local_count = paddle.to_tensor([1, 1, 2, 1], dtype="int64") + ... global_count = paddle.to_tensor([1, 1, 2, 1], dtype="int64") + >>> a = moe_utils.global_scatter(local_input_buf, + ... local_count, + ... global_count + ... ) + >>> a.stop_gradient = False + >>> print(a) + >>> # rank 0 的 输出: [[1, 2], [3, 4], [1, 2], [5, 6], [3, 4]] + >>> # rank 1 的 输出: [[7, 8], [5, 6], [7, 8], [9, 10], [9, 10]] + >>> # 反向传播测试 + >>> c = a * a + >>> c.backward() + >>> print("local_input_buf.grad: ", local_input_buf.grad) + >>> # rank 0 的 输出: [[2, 4], [6, 8], [10, 12], [14, 16], [18, 20]] + >>> # rank 1 d 输出: [[2, 4], [6, 8], [10, 12], [14, 16], [18, 20]] From 18244e090d18ae5b7c1204a85963b950f6aa151a Mon Sep 17 00:00:00 2001 From: ice Date: Tue, 30 Sep 2025 18:37:55 +0800 Subject: [PATCH 5/6] remove: code block --- .../distributed/utils/global_scatter_cn.rst | 39 ------------------- 1 file changed, 39 deletions(-) diff --git a/docs/api/paddle/distributed/utils/global_scatter_cn.rst b/docs/api/paddle/distributed/utils/global_scatter_cn.rst index 41e0e4ba0ff..faa7ec26a8a 100644 --- a/docs/api/paddle/distributed/utils/global_scatter_cn.rst +++ b/docs/api/paddle/distributed/utils/global_scatter_cn.rst @@ -49,42 +49,3 @@ local_count[3] 代表从 x 里取出 0 个 batch 的数据向第 1 张卡的第 返回 ::::::::: Tensor,从所有 expert 接收的数据,按照每个 expert 排列。 - -代码示例 -::::::::: - -.. code-block:: python - >>> # doctest: +REQUIRES(env:DISTRIBUTED) - >>> import paddle - >>> from paddle.distributed import init_parallel_env - >>> from paddle.distributed.utils import moe_utils - >>> init_parallel_env() - >>> n_expert = 2 - >>> world_size = 2 - >>> d_model = 2 - >>> in_feat = d_model - >>> local_input_buf = paddle.to_tensor( - ... [[1, 2],[3, 4],[5, 6],[7, 8],[9, 10]], - ... dtype='float32', - ... stop_gradient=False - ... ) - >>> if paddle.distributed.ParallelEnv().local_rank == 0: - ... local_count = paddle.to_tensor([2, 1, 1, 1], dtype="int64") - ... global_count = paddle.to_tensor([2, 1, 1, 1], dtype="int64") - >>> else: - ... local_count = paddle.to_tensor([1, 1, 2, 1], dtype="int64") - ... global_count = paddle.to_tensor([1, 1, 2, 1], dtype="int64") - >>> a = moe_utils.global_scatter(local_input_buf, - ... local_count, - ... global_count - ... ) - >>> a.stop_gradient = False - >>> print(a) - >>> # rank 0 的 输出: [[1, 2], [3, 4], [1, 2], [5, 6], [3, 4]] - >>> # rank 1 的 输出: [[7, 8], [5, 6], [7, 8], [9, 10], [9, 10]] - >>> # 反向传播测试 - >>> c = a * a - >>> c.backward() - >>> print("local_input_buf.grad: ", local_input_buf.grad) - >>> # rank 0 的 输出: [[2, 4], [6, 8], [10, 12], [14, 16], [18, 20]] - >>> # rank 1 d 输出: [[2, 4], [6, 8], [10, 12], [14, 16], [18, 20]] From 55469d6a7ba15ebc8cf32855493eccbcfe520ffd Mon Sep 17 00:00:00 2001 From: ice Date: Wed, 1 Oct 2025 11:58:03 +0800 Subject: [PATCH 6/6] Delete docs/api/paddle/distributed/utils/global_scatter_cn.rst --- .../distributed/utils/global_scatter_cn.rst | 51 ------------------- 1 file changed, 51 deletions(-) delete mode 100644 docs/api/paddle/distributed/utils/global_scatter_cn.rst diff --git a/docs/api/paddle/distributed/utils/global_scatter_cn.rst b/docs/api/paddle/distributed/utils/global_scatter_cn.rst deleted file mode 100644 index faa7ec26a8a..00000000000 --- a/docs/api/paddle/distributed/utils/global_scatter_cn.rst +++ /dev/null @@ -1,51 +0,0 @@ -.. _cn_api_paddle_distributed_utils_global_scatter: - -global_scatter -------------------------------- - - -.. py:function:: paddle.distributed.utils.global_scatter(x, local_count, global_count, group=None, use_calc_stream=True) - -global_scatter 根据 local_count 将 x 的数据分发到 n_expert * world_size 个 expert,然后根据 global_count 接收数据。 -其中 expert 是用户定义的专家网络,n_expert 是指每张卡拥有的专家网络数目,world_size 是指运行网络的显卡数目。 - -如下图所示,world_size 是 2,n_expert 是 2,x 的 batch_size 是 4,local_count 是[2, 0, 2, 0],0 卡的 global_count 是 [2, 0, , ], -1 卡的 global_count 是 [2, 0, ,](因为篇幅问题,这里只展示在 0 卡运算的数据),在 global_scatter 算子里, -local_count[i] 代表向第 (i // n_expert) 张卡的第 (i % n_expert) 个 expert 发送 local_expert[i] 个数据, -global_count[i] 代表从第 (i // n_expert) 张卡接收 global_count[i] 个数据给本卡的 第(i % n_expert)个 expert。 -图中的 rank0 代表第 0 张卡,rank1 代表第 1 张卡。 -global_scatter 发送数据的流程如下: - -local_count[0] 代表从 x 里取出 2 个 batch 的数据向第 0 张卡的第 0 个 expert 发送 2 个数据; - -local_count[1] 代表从 x 里取出 0 个 batch 的数据向第 0 张卡的第 1 个 expert 发送 0 个数据; - -local_count[2] 代表从 x 里取出 2 个 batch 的数据向第 1 张卡的第 0 个 expert 发送 2 个数据; - -local_count[3] 代表从 x 里取出 0 个 batch 的数据向第 1 张卡的第 1 个 expert 发送 0 个数据; - -所以第 0 张卡的 global_count[0] 等于 2,代表从第 0 张卡接收 2 个 batch 的数据给第 0 个 expert; - -第 0 张卡的 global_count[1] 等于 0,代表从第 0 张卡接收 0 个 batch 的数据给第 1 个 expert; - -第 1 张卡的 global_count[0] 等于 2,代表从第 0 张卡接收 2 个 batch 的数据给第 0 个 expert; - -第 1 张卡的 global_count[1] 等与 0,代表从第 0 张卡接收 0 个 batch 的数据给第 1 个 expert。 - - -.. image:: ../img/global_scatter_gather.png - :width: 800 - :alt: global_scatter_gather - :align: center - -参数 -::::::::: - - **x** (Tensor) - 输入 Tensor。Tensor 的数据类型必须是 float16、float32、 float64、int32、int64。 - - **local_count** (Tensor) - 拥有 n_expert * world_size 个数据的 Tensor,用于表示有多少数据发送。Tensor 的数据类型必须是 int64。 - - **global_count** (Tensor) - 拥有 n_expert * world_size 个数据的 Tensor,用于表示有多少数据接收。Tensor 的数据类型必须是 int64。 - - **group** (Group,可选) - new_group 返回的 Group 实例,或者设置为 None 表示默认地全局组。默认值:None。 - - **use_calc_stream** (bool,可选) - 标识使用计算流还是通信流。默认值:True,表示使用计算流。 - -返回 -::::::::: -Tensor,从所有 expert 接收的数据,按照每个 expert 排列。