Files
2026-07-13 12:40:42 +08:00

181 lines
6.2 KiB
Python

# Copyright (c) 2025 PaddlePaddle Authors. All Rights Reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
import unittest
import numpy as np
import paddle
from paddle.distributed.fleet.meta_parallel import zero_bubble_utils
class TestZuroBubble(unittest.TestCase):
def setUp(self):
paddle.seed(42)
def test_weight_grad_store(self):
def fake_func():
return
zero_bubble_utils.WeightGradStore.put(fake_func)
np.testing.assert_equal(
zero_bubble_utils.WeightGradStore.funcs_queue.empty(), True
)
zero_bubble_utils.WeightGradStore.flush()
np.testing.assert_equal(
zero_bubble_utils.WeightGradStore.funcs_queue.empty(), False
)
zero_bubble_utils.WeightGradStore.pop()
np.testing.assert_equal(
zero_bubble_utils.WeightGradStore.funcs_queue.empty(), True
)
def test_zero_bubble_utils(self):
zero_bubble_utils.WeightGradStore.enabled = False
paddle.seed(42)
input = paddle.randn([2, 4096, 2048])
input.stop_gradient = False
splitbw_linear = zero_bubble_utils.SplitBWLinear(
2048, 2048, bias_attr=True
)
o = splitbw_linear(input)
o.mean().backward()
paddle.seed(42)
ref_input = paddle.randn([2, 4096, 2048])
ref_input.stop_gradient = False
ref_linear = paddle.nn.Linear(2048, 2048, bias_attr=True)
o_ref = ref_linear(ref_input)
o_ref.mean().backward()
np.testing.assert_equal(o._md5sum(), o_ref._md5sum())
np.testing.assert_equal(input.grad._md5sum(), ref_input.grad._md5sum())
np.testing.assert_equal(
splitbw_linear.weight.grad._md5sum(),
ref_linear.weight.grad._md5sum(),
)
np.testing.assert_equal(
splitbw_linear.bias.grad._md5sum(), ref_linear.bias.grad._md5sum()
)
zero_bubble_utils.WeightGradStore.enabled = True
paddle.seed(42)
input = paddle.randn([2, 4096, 2048])
input.stop_gradient = False
splitbw_linear = zero_bubble_utils.SplitBWLinear(
2048, 2048, bias_attr=True
)
o = splitbw_linear(input)
o.mean().backward()
np.testing.assert_equal(splitbw_linear.weight.grad, None)
zero_bubble_utils.WeightGradStore.flush()
zero_bubble_utils.WeightGradStore.pop()
np.testing.assert_equal(
splitbw_linear.weight.grad._md5sum(),
ref_linear.weight.grad._md5sum(),
)
def test_zero_bubble_utils_no_bias(self):
zero_bubble_utils.WeightGradStore.enabled = True
paddle.seed(42)
ref_input = paddle.randn([2, 4096, 2048])
ref_input.stop_gradient = False
ref_linear = paddle.nn.Linear(2048, 2048, bias_attr=False)
o_ref = ref_linear(ref_input)
o_ref.mean().backward()
paddle.seed(42)
input = paddle.randn([2, 4096, 2048])
input.stop_gradient = False
splitbw_linear = zero_bubble_utils.SplitBWLinear(
2048, 2048, bias_attr=False
)
o = splitbw_linear(input)
o.mean().backward()
np.testing.assert_equal(splitbw_linear.weight.grad, None)
zero_bubble_utils.WeightGradStore.flush()
zero_bubble_utils.WeightGradStore.pop()
np.testing.assert_equal(o._md5sum(), o_ref._md5sum())
np.testing.assert_equal(input.grad._md5sum(), ref_input.grad._md5sum())
np.testing.assert_equal(
splitbw_linear.weight.grad._md5sum(),
ref_linear.weight.grad._md5sum(),
)
def test_zero_bubble_with_main_grad(self):
def _update_main_grad_hook(param):
@paddle.autograd.no_grad()
def param_hook(tmp_grad):
if tmp_grad is not None and tmp_grad._is_initialized():
if param.main_grad is None:
param.main_grad = (
paddle.base.framework.core.eager.Tensor(
value=tmp_grad.cast(paddle.float32).value(),
place=tmp_grad.place,
name="main_grad@" + param.name,
)
)
else:
# 梯度累加
param.main_grad.add_(tmp_grad)
tmp_grad._clear_data()
return param_hook
zero_bubble_utils.WeightGradStore.enabled = False
paddle.seed(42)
ref_input = paddle.randn([2, 4096, 2048])
ref_input.stop_gradient = False
ref_linear = paddle.nn.Linear(2048, 2048, bias_attr=False)
paddle.seed(42)
input = paddle.randn([2, 4096, 2048])
input.stop_gradient = False
splitbw_linear = zero_bubble_utils.SplitBWLinear(
2048, 2048, bias_attr=False
)
for param in splitbw_linear.parameters():
if not hasattr(param, "main_grad"):
param.main_grad = None
param._register_grad_hook(_update_main_grad_hook(param))
for param in ref_linear.parameters():
if not hasattr(param, "main_grad"):
param.main_grad = None
param._register_grad_hook(_update_main_grad_hook(param))
o_ref = ref_linear(ref_input)
o_ref.mean().backward()
o = splitbw_linear(input)
o.mean().backward()
np.testing.assert_equal(o._md5sum(), o_ref._md5sum())
np.testing.assert_equal(input.grad._md5sum(), ref_input.grad._md5sum())
np.testing.assert_equal(
splitbw_linear.weight.main_grad._md5sum(),
ref_linear.weight.main_grad._md5sum(),
)
if __name__ == "__main__":
unittest.main()