Files
deepspeedai--deepspeed/tests/unit/runtime/zero/test_unwrap_model.py
T
2026-07-13 13:18:33 +08:00

94 lines
2.7 KiB
Python

# Copyright (c) Microsoft Corporation.
# SPDX-License-Identifier: Apache-2.0
# DeepSpeed Team
import torch
import deepspeed
from deepspeed.runtime.zero import unwrap_model_for_generation
from deepspeed.accelerator import get_accelerator
from unit.common import DistributedTest, preferred_dtype
from unit.simple_model import SimpleModel
config = {
"train_batch_size": 2,
"steps_per_print": 1,
"optimizer": {
"type": "Adam",
"params": {
"lr": 0.00015
}
},
"zero_optimization": {
"stage": 3,
"stage3_param_persistence_threshold": 1,
"offload_param": {
"device": "cpu",
"pin_memory": True
}
}
}
if get_accelerator().is_bf16_supported():
config["bf16"] = {"enabled": True}
elif get_accelerator().is_fp16_supported():
config["fp16"] = {"enabled": True, "loss_scale": 138.}
class TestUnwrapModel(DistributedTest):
# gather across more than 1 gpu
world_size = 2
def test(self):
def hooks_exist(engine):
if engine.optimizer is not None and hasattr(engine.optimizer, "parameter_offload"):
optimizer_offload = engine.optimizer.parameter_offload
elif engine.optimizer is not None:
optimizer_offload = engine.optimizer
hooks = 0
for hook in optimizer_offload.forward_hooks:
hooks += 1
if hooks > 0:
return True
return False
model = SimpleModel(hidden_dim=100)
engine, _, _, _ = deepspeed.initialize(args=None, model=model, config=config)
with unwrap_model_for_generation(engine):
# assert no hooks
assert not hooks_exist(engine)
# assert parameters gathered
assert model.linears[0].weight.numel() != 0, "GatheredParameters should give a non-0-sized tensor"
# assert hooks
assert hooks_exist(engine)
class TestUnwrapModelTraceInvalidate(DistributedTest):
# unwrap_model_for_generation re-registers the ZeRO-3 hooks; without trace
# invalidation the next training step pops an empty fetch deque.
world_size = 2
def test(self):
model = SimpleModel(hidden_dim=100)
engine, _, _, _ = deepspeed.initialize(args=None, model=model, config=config)
x = torch.randn(2, 100, device=engine.device, dtype=preferred_dtype())
y = torch.empty(2, dtype=torch.long, device=engine.device).random_(100)
loss = engine(x, y)
engine.backward(loss)
engine.step()
with unwrap_model_for_generation(engine):
pass
loss = engine(x, y)
engine.backward(loss)
engine.step()