mirror of
https://github.com/hanzoai/gym-v1.git
synced 2026-10-30 18:35:21 +00:00
95 lines
2.7 KiB
Python
95 lines
2.7 KiB
Python
import torch
|
|
from torch.nn import utils as nn_utils
|
|
from typing import List, Optional, Union
|
|
from abc import ABC, abstractmethod
|
|
|
|
from .strategy import Strategy
|
|
from .optim import OptimSpec, ensure_optim_spec
|
|
|
|
|
|
class CommunicationModule(ABC):
|
|
"""Abstract base class for communication modules."""
|
|
|
|
@abstractmethod
|
|
def __init__(self):
|
|
pass
|
|
|
|
@abstractmethod
|
|
def communicate(self, model, rank: int, num_nodes: int, local_step: int) -> None:
|
|
"""
|
|
Perform communication for the given model.
|
|
|
|
Args:
|
|
model: The model to communicate
|
|
rank: Current node rank
|
|
num_nodes: Total number of nodes
|
|
local_step: Current local step count
|
|
"""
|
|
pass
|
|
|
|
@abstractmethod
|
|
def _init_node(self, model, rank: int, num_nodes: int) -> None:
|
|
"""
|
|
Initialize the communication module for the given model.
|
|
"""
|
|
pass
|
|
|
|
|
|
class CommunicateOptimizeStrategy(Strategy):
|
|
"""
|
|
Base class for strategies that interleave communication and optimization.
|
|
|
|
This strategy:
|
|
1. Performs local optimization step
|
|
2. Applies communication modules when the derived strategy decides
|
|
"""
|
|
|
|
def __init__(
|
|
self,
|
|
communication_modules: List[CommunicationModule],
|
|
optim_spec: Optional[Union[str, OptimSpec]] = None,
|
|
max_norm: Optional[float] = None,
|
|
**kwargs,
|
|
):
|
|
super().__init__(**kwargs)
|
|
|
|
self.optim_spec = ensure_optim_spec(optim_spec) or OptimSpec(
|
|
torch.optim.AdamW
|
|
)
|
|
|
|
self.communication_modules = communication_modules
|
|
self.max_norm = max_norm
|
|
|
|
# Set strategy reference in communication modules that need it
|
|
for comm_module in self.communication_modules:
|
|
comm_module.strategy = self
|
|
|
|
def step(self):
|
|
# Gradient clipping if specified
|
|
if self.max_norm:
|
|
nn_utils.clip_grad_norm_(self.model.parameters(), max_norm=self.max_norm)
|
|
|
|
# Local optimization step
|
|
self.optim.step()
|
|
|
|
# Communication phase - let derived strategies decide when
|
|
self._communicate()
|
|
|
|
super().step()
|
|
|
|
def _communicate(self):
|
|
"""Apply all communication modules sequentially. Override in derived classes for custom timing."""
|
|
for comm_module in self.communication_modules:
|
|
comm_module.communicate(
|
|
self.model, self.rank, self.num_nodes, self.local_step
|
|
)
|
|
|
|
def _init_node(self, model, rank, num_nodes):
|
|
super()._init_node(model, rank, num_nodes)
|
|
|
|
for comm_module in self.communication_modules:
|
|
comm_module._init_node(model, rank, num_nodes)
|
|
|
|
self.optim = self.optim_spec.build(model)
|
|
self._setup_scheduler()
|