-
Notifications
You must be signed in to change notification settings - Fork 409
Expand file tree
/
Copy pathmoe_utils.py
More file actions
77 lines (65 loc) · 2.99 KB
/
moe_utils.py
File metadata and controls
77 lines (65 loc) · 2.99 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
# SPDX-FileCopyrightText: Copyright (c) 2024 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
# SPDX-License-Identifier: Apache-2.0
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
"""Utilities for Mixture-of-Experts (MoE) model export."""
from pathlib import Path
import torch.nn as nn
def save_expert_token_count_table(model: nn.Module, output_dir: str | Path | None = None):
"""Collect expert_token_count from all quantized MoE layers and save as an HTML table.
The table has rows for each MoE layer and columns for each expert, with cell values
showing the number of tokens routed to that expert during calibration.
Args:
model: The model containing quantized MoE layers with ``expert_token_count`` attributes.
output_dir: Directory to save the HTML file. Defaults to current directory.
"""
rows = []
for name, module in model.named_modules():
if hasattr(module, "expert_token_count") and module.expert_token_count.numel() > 0:
rows.append((name, module.expert_token_count))
if not rows:
return
num_experts = rows[0][1].shape[0]
assert all(r[1].shape[0] == num_experts for r in rows), (
"All MoE layers must have the same number of experts"
)
html_parts = [
"<html><head><style>",
"table { border-collapse: collapse; font-family: monospace; }",
"th, td { border: 1px solid #ccc; padding: 4px 8px; text-align: right; }",
"th { background: #f0f0f0; }",
"</style></head><body>",
"<h2>Expert Calib Token Counts (per MoE layer)</h2>",
"<table><tr><th>Layer/Expert</th>",
]
html_parts.extend(f"<th>{i}</th>" for i in range(num_experts))
html_parts.append("</tr>")
for name, counts in rows:
avg = counts.float().mean().item()
html_parts.append(f"<tr><td>{name}</td>")
for c in counts.tolist():
if avg > 0 and c < avg * 0.05:
style = ' style="background: #ff6666;"'
elif avg > 0 and c < avg * 0.1:
style = ' style="background: #ffcccc;"'
else:
style = ""
html_parts.append(f"<td{style}>{c}</td>")
html_parts.append("</tr>")
html_parts.append("</table></body></html>")
html_content = "\n".join(html_parts)
if output_dir is None:
output_dir = Path(".")
output_path = Path(output_dir) / ".moe.html"
output_path.write_text(html_content, encoding="utf-8")
print(f"\033[1mExpert token count table saved to {output_path}\033[0m")