Skip to content

Commit fc3bc56

Browse files
authored
【Hackathon 9th No.35】add test_moe_redundant_topk_select (PaddlePaddle#3867)
1 parent 7643e6e commit fc3bc56

File tree

1 file changed

+96
-0
lines changed

1 file changed

+96
-0
lines changed
Lines changed: 96 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,96 @@
1+
"""
2+
# Copyright (c) 2025 PaddlePaddle Authors. All Rights Reserved.
3+
#
4+
# Licensed under the Apache License, Version 2.0 (the "License"
5+
# you may not use this file except in compliance with the License.
6+
# You may obtain a copy of the License at
7+
#
8+
# http://www.apache.org/licenses/LICENSE-2.0
9+
#
10+
# Unless required by applicable law or agreed to in writing, software
11+
# distributed under the License is distributed on an "AS IS" BASIS,
12+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
# See the License for the specific language governing permissions and
14+
# limitations under the License.
15+
"""
16+
17+
import unittest
18+
19+
import numpy as np
20+
import paddle
21+
22+
from fastdeploy.model_executor.ops.gpu import moe_redundant_topk_select
23+
24+
25+
class TestMoERedundantTopKSelect(unittest.TestCase):
26+
def setUp(self):
27+
paddle.set_device("gpu")
28+
np.random.seed(42)
29+
30+
def _run_and_check(
31+
self,
32+
gating_shape,
33+
expert_num,
34+
moe_topk,
35+
apply_norm_weight=False,
36+
enable_softmax_top_k_fused=False,
37+
use_bias=False,
38+
):
39+
"""Helper function to run the operator and check."""
40+
gating_logits = paddle.to_tensor(np.random.rand(*gating_shape).astype("float32"))
41+
expert_id_to_ep_rank_array = paddle.to_tensor(
42+
np.random.randint(0, expert_num, size=(expert_num,)).astype("int32")
43+
)
44+
expert_in_rank_num_list = paddle.to_tensor(np.random.randint(1, 4, size=(expert_num,)).astype("int32"))
45+
tokens_per_expert_stats_list = paddle.zeros([expert_num], dtype="int32")
46+
bias = None
47+
if use_bias:
48+
bias = paddle.to_tensor(np.random.rand(*gating_shape[:-1], expert_num).astype("float32"))
49+
50+
outputs = moe_redundant_topk_select(
51+
gating_logits=gating_logits,
52+
expert_id_to_ep_rank_array=expert_id_to_ep_rank_array,
53+
expert_in_rank_num_list=expert_in_rank_num_list,
54+
tokens_per_expert_stats_list=tokens_per_expert_stats_list,
55+
bias=bias,
56+
moe_topk=moe_topk,
57+
apply_norm_weight=apply_norm_weight,
58+
enable_softmax_top_k_fused=enable_softmax_top_k_fused,
59+
redundant_ep_rank_num_plus_one=2,
60+
)
61+
62+
topk_ids, topk_weights = outputs
63+
64+
# Check shapes are correct
65+
expected_shape = [int(np.prod(gating_shape[:-1])), moe_topk]
66+
self.assertEqual(topk_ids.shape, expected_shape)
67+
self.assertEqual(topk_weights.shape, expected_shape)
68+
69+
# Check topk_ids are non-negative
70+
self.assertTrue(np.all(topk_ids.numpy() >= 0))
71+
72+
# Check topk weights are non-negative
73+
self.assertTrue(np.all(topk_weights.numpy() >= -1e-6))
74+
75+
# Check tokens_per_expert_stats_list has valid values
76+
self.assertEqual(tokens_per_expert_stats_list.shape[0], expert_num)
77+
self.assertTrue(np.all(tokens_per_expert_stats_list.numpy() >= 0))
78+
79+
def test_basic_case(self):
80+
self._run_and_check(gating_shape=(4, 16), expert_num=8, moe_topk=2)
81+
82+
def test_3d_input_case(self):
83+
self._run_and_check(gating_shape=(2, 3, 8), expert_num=8, moe_topk=2)
84+
85+
def test_with_bias(self):
86+
self._run_and_check(gating_shape=(3, 12), expert_num=4, moe_topk=2, use_bias=True)
87+
88+
def test_with_norm_weight(self):
89+
self._run_and_check(gating_shape=(5, 10), expert_num=4, moe_topk=2, apply_norm_weight=True)
90+
91+
def test_softmax_topk_fused(self):
92+
self._run_and_check(gating_shape=(6, 8), expert_num=8, moe_topk=2, enable_softmax_top_k_fused=True)
93+
94+
95+
if __name__ == "__main__":
96+
unittest.main()

0 commit comments

Comments
 (0)