comdoleger commited on
Commit
fbfb150
·
verified ·
1 Parent(s): a23c9a5

Upload extensions_built_in/diffusion_models/hidream/src/models/moe.py with huggingface_hub

Browse files
extensions_built_in/diffusion_models/hidream/src/models/moe.py ADDED
@@ -0,0 +1,157 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import math
2
+ import torch
3
+ from torch import nn
4
+ import torch.nn.functional as F
5
+ from .attention import FeedForwardSwiGLU
6
+ from torch.distributed.nn.functional import all_gather
7
+
8
+ _LOAD_BALANCING_LOSS = []
9
+ def save_load_balancing_loss(loss):
10
+ global _LOAD_BALANCING_LOSS
11
+ _LOAD_BALANCING_LOSS.append(loss)
12
+
13
+ def clear_load_balancing_loss():
14
+ global _LOAD_BALANCING_LOSS
15
+ _LOAD_BALANCING_LOSS.clear()
16
+
17
+ def get_load_balancing_loss():
18
+ global _LOAD_BALANCING_LOSS
19
+ return _LOAD_BALANCING_LOSS
20
+
21
+ def batched_load_balancing_loss():
22
+ aux_losses_arr = get_load_balancing_loss()
23
+ alpha = aux_losses_arr[0][-1]
24
+ Pi = torch.stack([ent[1] for ent in aux_losses_arr], dim=0)
25
+ fi = torch.stack([ent[2] for ent in aux_losses_arr], dim=0)
26
+
27
+ fi_list = all_gather(fi)
28
+ fi = torch.stack(fi_list, 0).mean(0)
29
+
30
+ aux_loss = (Pi * fi).sum(-1).mean() * alpha
31
+ return aux_loss
32
+
33
+ # Modified from https://github.com/deepseek-ai/DeepSeek-V3/blob/main/inference/model.py
34
+ class MoEGate(nn.Module):
35
+ def __init__(self, embed_dim, num_routed_experts=4, num_activated_experts=2, aux_loss_alpha=0.01):
36
+ super().__init__()
37
+ self.top_k = num_activated_experts
38
+ self.n_routed_experts = num_routed_experts
39
+
40
+ self.scoring_func = 'softmax'
41
+ self.alpha = aux_loss_alpha
42
+ self.seq_aux = False
43
+
44
+ # topk selection algorithm
45
+ self.norm_topk_prob = False
46
+ self.gating_dim = embed_dim
47
+ self.weight = nn.Parameter(torch.empty((self.n_routed_experts, self.gating_dim)))
48
+ self.reset_parameters()
49
+
50
+ def reset_parameters(self) -> None:
51
+ import torch.nn.init as init
52
+ init.kaiming_uniform_(self.weight, a=math.sqrt(5))
53
+
54
+ def forward(self, hidden_states):
55
+ bsz, seq_len, h = hidden_states.shape
56
+ # print(bsz, seq_len, h)
57
+ ### compute gating score
58
+ hidden_states = hidden_states.view(-1, h)
59
+ logits = F.linear(hidden_states, self.weight, None)
60
+ if self.scoring_func == 'softmax':
61
+ scores = logits.softmax(dim=-1)
62
+ else:
63
+ raise NotImplementedError(f'insupportable scoring function for MoE gating: {self.scoring_func}')
64
+
65
+ ### select top-k experts
66
+ topk_weight, topk_idx = torch.topk(scores, k=self.top_k, dim=-1, sorted=False)
67
+
68
+ ### norm gate to sum 1
69
+ if self.top_k > 1 and self.norm_topk_prob:
70
+ denominator = topk_weight.sum(dim=-1, keepdim=True) + 1e-20
71
+ topk_weight = topk_weight / denominator
72
+ # this was in original and memory leaks, not needed
73
+
74
+ # ### expert-level computation auxiliary loss
75
+ # if self.training and self.alpha > 0.0:
76
+ # scores_for_aux = scores
77
+ # aux_topk = self.top_k
78
+ # # always compute aux loss based on the naive greedy topk method
79
+ # topk_idx_for_aux_loss = topk_idx.view(bsz, -1)
80
+ # if self.seq_aux:
81
+ # scores_for_seq_aux = scores_for_aux.view(bsz, seq_len, -1)
82
+ # ce = torch.zeros(bsz, self.n_routed_experts, device=hidden_states.device)
83
+ # ce.scatter_add_(1, topk_idx_for_aux_loss, torch.ones(bsz, seq_len * aux_topk, device=hidden_states.device)).div_(seq_len * aux_topk / self.n_routed_experts)
84
+ # aux_loss = (ce * scores_for_seq_aux.mean(dim = 1)).sum(dim = 1).mean() * self.alpha
85
+ # else:
86
+ # mask_ce = F.one_hot(topk_idx_for_aux_loss.view(-1), num_classes=self.n_routed_experts)
87
+ # ce = mask_ce.float().mean(0)
88
+
89
+ # Pi = scores_for_aux.mean(0)
90
+ # fi = ce * self.n_routed_experts
91
+ # aux_loss = (Pi * fi).sum() * self.alpha
92
+ # save_load_balancing_loss((aux_loss, Pi, fi, self.alpha))
93
+ # else:
94
+ aux_loss = None
95
+ return topk_idx, topk_weight, aux_loss
96
+
97
+ # Modified from https://github.com/deepseek-ai/DeepSeek-V3/blob/main/inference/model.py
98
+ class MOEFeedForwardSwiGLU(nn.Module):
99
+ def __init__(
100
+ self,
101
+ dim: int,
102
+ hidden_dim: int,
103
+ num_routed_experts: int,
104
+ num_activated_experts: int,
105
+ ):
106
+ super().__init__()
107
+ self.shared_experts = FeedForwardSwiGLU(dim, hidden_dim // 2)
108
+ self.experts = nn.ModuleList([FeedForwardSwiGLU(dim, hidden_dim) for i in range(num_routed_experts)])
109
+ self.gate = MoEGate(
110
+ embed_dim = dim,
111
+ num_routed_experts = num_routed_experts,
112
+ num_activated_experts = num_activated_experts
113
+ )
114
+ self.num_activated_experts = num_activated_experts
115
+
116
+ def forward(self, x):
117
+ wtype = x.dtype
118
+ identity = x
119
+ orig_shape = x.shape
120
+ topk_idx, topk_weight, aux_loss = self.gate(x)
121
+ x = x.view(-1, x.shape[-1])
122
+ flat_topk_idx = topk_idx.view(-1)
123
+ y = self.moe_infer(x, flat_topk_idx, topk_weight.view(-1, 1)).view(*orig_shape)
124
+ # this was in original and memory leaks, not needed
125
+ # if self.training:
126
+ # x = x.repeat_interleave(self.num_activated_experts, dim=0)
127
+ # y = torch.empty_like(x, dtype=wtype)
128
+ # for i, expert in enumerate(self.experts):
129
+ # y[flat_topk_idx == i] = expert(x[flat_topk_idx == i]).to(dtype=wtype)
130
+ # y = (y.view(*topk_weight.shape, -1) * topk_weight.unsqueeze(-1)).sum(dim=1)
131
+ # y = y.view(*orig_shape).to(dtype=wtype)
132
+ # #y = AddAuxiliaryLoss.apply(y, aux_loss)
133
+ # else:
134
+ # y = self.moe_infer(x, flat_topk_idx, topk_weight.view(-1, 1)).view(*orig_shape)
135
+ y = y + self.shared_experts(identity)
136
+ return y
137
+
138
+ # @torch.no_grad()
139
+ def moe_infer(self, x, flat_expert_indices, flat_expert_weights):
140
+ expert_cache = torch.zeros_like(x)
141
+ idxs = flat_expert_indices.argsort()
142
+ tokens_per_expert = flat_expert_indices.bincount().cpu().numpy().cumsum(0)
143
+ token_idxs = idxs // self.num_activated_experts
144
+ for i, end_idx in enumerate(tokens_per_expert):
145
+ start_idx = 0 if i == 0 else tokens_per_expert[i-1]
146
+ if start_idx == end_idx:
147
+ continue
148
+ expert = self.experts[i]
149
+ exp_token_idx = token_idxs[start_idx:end_idx]
150
+ expert_tokens = x[exp_token_idx]
151
+ expert_out = expert(expert_tokens)
152
+ expert_out.mul_(flat_expert_weights[idxs[start_idx:end_idx]])
153
+
154
+ # for fp16 and other dtype
155
+ expert_cache = expert_cache.to(expert_out.dtype)
156
+ expert_cache.scatter_reduce_(0, exp_token_idx.view(-1, 1).repeat(1, x.shape[-1]), expert_out, reduce='sum')
157
+ return expert_cache