NeMo
Megatron-LM / megatron /core /resharding /execution.py
KexuanShi's picture
Upload folder using huggingface_hub
88e6849 verified
Raw
History Blame Contribute Delete
2.49 kB
# Copyright (c) 2024, NVIDIA CORPORATION. All rights reserved.
from __future__ import annotations
import logging
from typing import List, Tuple
import torch
import torch.distributed as dist
from .copy_services.base import CopyService
from .utils import ReshardPlan
logger = logging.getLogger(__name__)
def execute_reshard_plan(
plan: ReshardPlan,
src_module: torch.nn.Module,
dst_module: torch.nn.Module,
service: CopyService,
) -> None:
"""
Execute a reshard plan (from centralized controller).
A communication service must be provided to abstract transport.
Expected service API: submit_send(tensor, dest_rank), submit_recv(tensor, src_rank), run().
"""
src_params = {name: p for name, p in src_module.named_parameters(recurse=True)}
dst_params = {name: p for name, p in dst_module.named_parameters(recurse=True)}
submit_send_with_id = getattr(service, "submit_send_with_id", None)
submit_recv_with_id = getattr(service, "submit_recv_with_id", None)
# Submit sends
for op in plan.send_ops:
src_param = src_params.get(op.param_name)
if src_param is not None:
src_view = src_param.data[op.my_slice].contiguous()
if submit_send_with_id is not None and op.task_id is not None:
submit_send_with_id(op.task_id, src_view, op.peer_rank)
else:
service.submit_send(src_view, op.peer_rank)
# Submit recvs
recv_writebacks: List[Tuple[torch.Tensor, torch.nn.Parameter, tuple[slice, ...]]] = []
for op in plan.recv_ops:
dst_param = dst_params.get(op.param_name)
if dst_param is not None:
dst_slice_view = dst_param.data[op.my_slice]
recv_buffer = torch.empty_like(dst_slice_view.contiguous())
if submit_recv_with_id is not None and op.task_id is not None:
submit_recv_with_id(op.task_id, recv_buffer, op.peer_rank)
else:
service.submit_recv(recv_buffer, op.peer_rank)
recv_writebacks.append((recv_buffer, dst_param, op.my_slice))
# Execute
logger.info(f"Executing {len(plan.send_ops)} sends + {len(plan.recv_ops)} recvs")
service.run()
dist.barrier()
# Write back received buffers into their destination parameter slices
for recv_buffer, dst_param, dst_slice in recv_writebacks:
with torch.no_grad():
dst_param.data[dst_slice].copy_(recv_buffer)
logger.info("Reshard complete")