| from typing import Tuple | |
| import torch | |
| from sglang.srt.eplb.eplb_algorithms.deepseek import rebalance_experts_hierarchical | |
| def rebalance_experts( | |
| weight: torch.Tensor, | |
| num_replicas: int, | |
| num_groups: int, | |
| num_nodes: int, | |
| num_gpus: int, | |
| enable_hierarchical: bool, | |
| active_ranks: torch.Tensor, | |
| ) -> Tuple[torch.Tensor, torch.Tensor, torch.Tensor]: | |
| """ | |
| Entry point for expert-parallelism load balancer. | |
| Parameters: | |
| weight: [layers, num_logical_experts], the load statistics for all logical experts | |
| num_replicas: number of physical experts, must be a multiple of `num_gpus` | |
| num_groups: number of expert groups | |
| num_nodes: number of server nodes, where the intra-node network (e.g, NVLink) is faster | |
| num_gpus: number of GPUs, must be a multiple of `num_nodes` | |
| Returns: | |
| physical_to_logical_map: [layers, num_replicas], the expert index of each replica | |
| logical_to_physical_map: [layers, num_logical_experts, X], the replica indices for each expert | |
| expert_count: [layers, num_logical_experts], number of physical replicas for each logical expert | |
| """ | |
| num_layers, num_logical_experts = weight.shape | |
| weight = weight.float().cpu() | |
| num_active_ranks = active_ranks.sum().item() | |
| num_local_experts = num_replicas // num_gpus | |
| if num_active_ranks < num_gpus: | |
| # Must fall back to global load-balance policy | |
| # and fix some params | |
| phy2log, phyrank, logcnt = rebalance_experts_hierarchical( | |
| weight, | |
| num_local_experts * num_active_ranks, | |
| 1, | |
| 1, | |
| num_active_ranks, | |
| ) | |
| elif enable_hierarchical: | |
| # use hierarchical load-balance policy | |
| phy2log, phyrank, logcnt = rebalance_experts_hierarchical( | |
| weight, num_replicas, num_groups, num_nodes, num_gpus | |
| ) | |
| else: | |
| # use global load-balance policy | |
| phy2log, phyrank, logcnt = rebalance_experts_hierarchical( | |
| weight, num_replicas, 1, 1, num_gpus | |
| ) | |
| maxlogcnt = logcnt.max().item() | |
| log2phy: torch.Tensor = torch.full( | |
| (num_layers, num_logical_experts, maxlogcnt), | |
| -1, | |
| dtype=torch.int64, | |
| device=logcnt.device, | |
| ) | |
| log2phy.view(num_layers, -1).scatter_( | |
| -1, | |
| phy2log * maxlogcnt + phyrank, | |
| torch.arange( | |
| num_local_experts * num_active_ranks, | |
| dtype=torch.int64, | |
| device=log2phy.device, | |
| ).expand(num_layers, -1), | |
| ) | |
| if num_active_ranks < num_gpus: | |
| phy2log_slices = list( | |
| phy2log.view(num_layers, num_active_ranks, -1).unbind(dim=1) | |
| ) | |
| active_ranks_list = active_ranks.tolist() | |
| for idx, active_rank in enumerate(active_ranks_list): | |
| if not active_rank: | |
| phy2log_slices.insert(idx, torch.zeros_like(phy2log_slices[0])) | |
| log2phy = torch.where( | |
| log2phy >= idx * num_local_experts, | |
| log2phy + num_local_experts, | |
| log2phy, | |
| ) | |
| phy2log = torch.stack(phy2log_slices, dim=1).contiguous().view(num_layers, -1) | |
| return phy2log, log2phy, logcnt | |
Xet Storage Details
- Size:
- 3.23 kB
- Xet hash:
- ae132de636600b3cb73ab3dbcddfb4d9df0917aed2ef1a862c3a7b5880df6f5b
·
Xet efficiently stores files, intelligently splitting them into unique chunks and accelerating uploads and downloads. More info.