Files
2026-07-13 13:24:13 +08:00

214 lines
7.9 KiB
Python

import os
from functools import partial
import torch
from torch.distributed.fsdp import FullyShardedDataParallel, CPUOffload, MixedPrecision, ShardingStrategy, BackwardPrefetch
from torch.distributed.fsdp.wrap import transformer_auto_wrap_policy, size_based_auto_wrap_policy
from transformers.models.bart.modeling_bart import BartEncoderLayer
from transformers.trainer_pt_utils import get_module_class_from_name
from general_util.logger import get_child_logger
"""
Refer to https://pytorch.org/blog/introducing-pytorch-fully-sharded-data-parallel-api/,
and https://pytorch.org/tutorials/intermediate/FSDP_tutorial.html.
"""
logger = get_child_logger(__name__)
def torch_fsdp_initialize_default(model,
device,
fp16: bool = True,
fp16_bfloat16: bool = False,
cpu_offload=False):
my_auto_wrap_policy = partial(transformer_auto_wrap_policy,
transformer_layer_cls={BartEncoderLayer})
ignored_modules = []
for dec_layer in model.model.decoder.layers:
ignored_modules.append(dec_layer.encoder_attn)
ignored_modules.append(dec_layer.encoder_attn_layer_norm)
if fp16:
fp16_type = torch.float16 if not fp16_bfloat16 else torch.bfloat16
mixed_precision_cfg = MixedPrecision(param_dtype=fp16_type, reduce_dtype=fp16_type, buffer_dtype=fp16_type)
else:
mixed_precision_cfg = None
fsdp_model = FullyShardedDataParallel(
model,
mixed_precision=mixed_precision_cfg,
auto_wrap_policy=my_auto_wrap_policy,
sharding_strategy=ShardingStrategy.FULL_SHARD,
cpu_offload=CPUOffload(offload_params=cpu_offload),
ignored_modules=ignored_modules,
device_id=device,
)
return fsdp_model
def torch_fsdp_init_decoder_freeze(model,
device,
fp16: bool = True,
fp16_bfloat16: bool = False,
cpu_offload=False):
my_auto_wrap_policy = partial(transformer_auto_wrap_policy,
transformer_layer_cls={BartEncoderLayer})
ignored_modules = [model.model.decoder]
# for dec_layer in model.model.decoder.layers:
# ignored_modules.append(dec_layer.encoder_attn)
# ignored_modules.append(dec_layer.encoder_attn_layer_norm)
if fp16:
fp16_type = torch.float16 if not fp16_bfloat16 else torch.bfloat16
mixed_precision_cfg = MixedPrecision(param_dtype=fp16_type, reduce_dtype=fp16_type, buffer_dtype=fp16_type)
else:
mixed_precision_cfg = None
fsdp_model = FullyShardedDataParallel(
model,
mixed_precision=mixed_precision_cfg,
auto_wrap_policy=my_auto_wrap_policy,
sharding_strategy=ShardingStrategy.FULL_SHARD,
cpu_offload=CPUOffload(offload_params=cpu_offload),
ignored_modules=ignored_modules,
device_id=device,
)
return fsdp_model
def torch_fsdp_init_quantizer_ignore(model,
device,
fp16: bool = True,
fp16_bfloat16: bool = False,
cpu_offload=False):
my_auto_wrap_policy = partial(transformer_auto_wrap_policy,
transformer_layer_cls={BartEncoderLayer})
if hasattr(model, "get_non_sharded_modules"):
ignored_modules = model.get_non_sharded_modules()
else:
ignored_modules = [model.quantizer, model.dense1, model.dense2]
logger.info(f"FSDP ignored modules: {ignored_modules}")
if fp16:
fp16_type = torch.float16 if not fp16_bfloat16 else torch.bfloat16
mixed_precision_cfg = MixedPrecision(param_dtype=fp16_type, reduce_dtype=fp16_type, buffer_dtype=fp16_type)
else:
mixed_precision_cfg = None
fsdp_model = FullyShardedDataParallel(
model,
mixed_precision=mixed_precision_cfg,
auto_wrap_policy=my_auto_wrap_policy,
sharding_strategy=ShardingStrategy.FULL_SHARD,
cpu_offload=CPUOffload(offload_params=cpu_offload),
ignored_modules=ignored_modules,
device_id=device,
)
return fsdp_model
def torch_fsdp_size_auto_wrap(model,
device,
fp16: bool = True,
fp16_bfloat16: bool = False,
cpu_offload: bool = False,
min_num_params: int = 1e8):
my_auto_wrap_policy = partial(size_based_auto_wrap_policy,
min_num_params=min_num_params)
# ignored_modules = []
# for dec_layer in model.model.decoder.layers:
# ignored_modules.append(dec_layer.encoder_attn)
# ignored_modules.append(dec_layer.encoder_attn_layer_norm)
if fp16:
fp16_type = torch.float16 if not fp16_bfloat16 else torch.bfloat16
mixed_precision_cfg = MixedPrecision(param_dtype=fp16_type, reduce_dtype=fp16_type, buffer_dtype=fp16_type)
else:
mixed_precision_cfg = None
fsdp_model = FullyShardedDataParallel(
model,
mixed_precision=mixed_precision_cfg,
auto_wrap_policy=my_auto_wrap_policy,
sharding_strategy=ShardingStrategy.FULL_SHARD,
cpu_offload=CPUOffload(offload_params=cpu_offload),
# ignored_modules=ignored_modules,
device_id=device,
)
return fsdp_model
def torch_fsdp_peft_auto_wrap(model,
device,
fp16: bool = True,
fp16_bfloat16: bool = False,
cpu_offload: bool = False,):
from peft.utils.other import fsdp_auto_wrap_policy
if fp16:
fp16_type = torch.float16 if not fp16_bfloat16 else torch.bfloat16
mixed_precision_cfg = MixedPrecision(param_dtype=fp16_type, reduce_dtype=fp16_type, buffer_dtype=fp16_type)
else:
mixed_precision_cfg = None
fsdp_model = FullyShardedDataParallel(
model,
mixed_precision=mixed_precision_cfg,
auto_wrap_policy=fsdp_auto_wrap_policy(model),
cpu_offload=CPUOffload(offload_params=cpu_offload),
# ignored_modules=ignored_modules,
device_id=device,
)
return fsdp_model
def torch_fsdp_transformer_init(model,
device,
fp16: bool = True,
fp16_bfloat16: bool = False,
cpu_offload=False):
transformer_cls_to_wrap = set()
fsdp_transformer_layer_cls = os.environ.get("FSDP_TRANSFORMER_CLS_TO_WRAP", "").split(",")
assert isinstance(fsdp_transformer_layer_cls, list)
for layer_class in fsdp_transformer_layer_cls:
transformer_cls = get_module_class_from_name(model, layer_class)
if transformer_cls is None:
raise Exception("Could not find the transformer layer class to wrap in the model.")
else:
transformer_cls_to_wrap.add(transformer_cls)
auto_wrap_policy = partial(
transformer_auto_wrap_policy,
# Transformer layer class to wrap
transformer_layer_cls=transformer_cls_to_wrap,
)
if fp16:
fp16_type = torch.float16 if not fp16_bfloat16 else torch.bfloat16
mixed_precision_cfg = MixedPrecision(param_dtype=fp16_type, reduce_dtype=fp16_type, buffer_dtype=fp16_type)
else:
mixed_precision_cfg = None
fsdp_model = FullyShardedDataParallel(
model,
mixed_precision=mixed_precision_cfg,
auto_wrap_policy=auto_wrap_policy,
sharding_strategy=ShardingStrategy.FULL_SHARD,
cpu_offload=CPUOffload(offload_params=cpu_offload),
backward_prefetch=BackwardPrefetch.BACKWARD_POST,
device_id=device,
)
logger.info(fsdp_model)
return fsdp_model