Skip to content

Commit fd920cf

Browse files
committed
test(paged): cover MoE swiglu down chain
Assisted-by: Claude:opus-4.8 [Claude Code] Signed-off-by: Ettore Di Giacinto <mudler@localai.io>
1 parent 51168c5 commit fd920cf

1 file changed

Lines changed: 92 additions & 0 deletions

File tree

tests/test-backend-ops.cpp

Lines changed: 92 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4447,6 +4447,91 @@ struct test_mul_mat_id_fusion : public test_case {
44474447
}
44484448
};
44494449

4450+
// Merged MoE gate_up -> SWIGLU -> down MUL_MAT_ID chain.
4451+
struct test_moe_swiglu_down : public test_case {
4452+
const ggml_type type_a;
4453+
const int n_mats;
4454+
const int n_used;
4455+
const int64_t n_ff;
4456+
const int64_t n_tokens;
4457+
const int64_t n_embd;
4458+
4459+
std::string vars() override {
4460+
return VARS_TO_STR6(type_a, n_mats, n_used, n_ff, n_tokens, n_embd);
4461+
}
4462+
4463+
double max_nmse_err() override {
4464+
return 5e-4;
4465+
}
4466+
4467+
double max_nmse_err(ggml_backend_t backend) override {
4468+
if ((type_a == GGML_TYPE_MXFP4 || type_a == GGML_TYPE_NVFP4) && backend_has_feature(backend, "BLACKWELL_NATIVE_FP4")) {
4469+
// This whole-graph gate compounds two native-FP4 MUL_MAT_ID ops with
4470+
// SWIGLU between them, so it needs slightly more room than the
4471+
// single-op FP4 MUL_MAT_ID gate.
4472+
return 2.5e-2;
4473+
}
4474+
return max_nmse_err();
4475+
}
4476+
4477+
uint64_t op_flops(ggml_tensor * t) override {
4478+
GGML_UNUSED(t);
4479+
return 2 * n_ff * n_embd * n_tokens * n_used * 3;
4480+
}
4481+
4482+
test_moe_swiglu_down(ggml_type type_a = GGML_TYPE_F32, int n_mats = 128, int n_used = 8,
4483+
int64_t n_ff = 768, int64_t n_tokens = 128, int64_t n_embd = 2048)
4484+
: type_a(type_a), n_mats(n_mats), n_used(n_used), n_ff(n_ff), n_tokens(n_tokens), n_embd(n_embd) {
4485+
GGML_ASSERT(n_used <= n_mats);
4486+
}
4487+
4488+
ggml_tensor * build_graph(ggml_context * ctx) override {
4489+
ggml_tensor * gate_up = ggml_new_tensor_3d(ctx, type_a, n_embd, 2 * n_ff, n_mats);
4490+
ggml_set_name(gate_up, "gate_up");
4491+
4492+
ggml_tensor * down = ggml_new_tensor_3d(ctx, type_a, n_ff, n_embd, n_mats);
4493+
ggml_set_name(down, "down");
4494+
4495+
ggml_tensor * ids = ggml_new_tensor_2d(ctx, GGML_TYPE_I32, n_mats, n_tokens);
4496+
ggml_set_name(ids, "ids");
4497+
if (n_used != n_mats) {
4498+
ids = ggml_view_2d(ctx, ids, n_used, n_tokens, ids->nb[1], 0);
4499+
ggml_set_name(ids, "view_of_ids");
4500+
}
4501+
4502+
ggml_tensor * cur = ggml_new_tensor_3d(ctx, GGML_TYPE_F32, n_embd, n_used, n_tokens);
4503+
ggml_set_name(cur, "cur");
4504+
4505+
ggml_tensor * gate_up_out = ggml_mul_mat_id(ctx, gate_up, cur, ids);
4506+
ggml_set_name(gate_up_out, "gate_up_out");
4507+
4508+
ggml_tensor * gate = ggml_view_3d(ctx, gate_up_out, n_ff, n_used, n_tokens, gate_up_out->nb[1], gate_up_out->nb[2], 0);
4509+
ggml_set_name(gate, "gate");
4510+
4511+
ggml_tensor * up = ggml_view_3d(ctx, gate_up_out, n_ff, n_used, n_tokens, gate_up_out->nb[1], gate_up_out->nb[2], n_ff * gate_up_out->nb[0]);
4512+
ggml_set_name(up, "up");
4513+
4514+
ggml_tensor * act = ggml_swiglu_split(ctx, gate, up);
4515+
ggml_set_name(act, "swiglu");
4516+
4517+
ggml_tensor * out = ggml_mul_mat_id(ctx, down, act, ids);
4518+
ggml_set_name(out, "out");
4519+
4520+
return out;
4521+
}
4522+
4523+
void initialize_tensors(ggml_context * ctx) override {
4524+
init_mul_mat_id_tensors(ctx, n_mats);
4525+
}
4526+
4527+
bool run_whole_graph() override { return true; }
4528+
4529+
std::string op_desc(ggml_tensor * t) override {
4530+
GGML_UNUSED(t);
4531+
return "MOE_SWIGLU_DOWN";
4532+
}
4533+
};
4534+
44504535
// GGML_OP_OUT_PROD
44514536
struct test_out_prod : public test_case {
44524537
const ggml_type type_a;
@@ -8759,6 +8844,13 @@ static std::vector<std::unique_ptr<test_case>> make_test_cases_eval() {
87598844
}
87608845
}
87618846

8847+
// [paged Phase 7] Merged MoE gate_up -> SWIGLU -> down projection gate for the
8848+
// serving candidate that fuses SWIGLU into NVFP4 down-input quantization.
8849+
test_cases.emplace_back(new test_moe_swiglu_down(GGML_TYPE_F32, 8, 2, 32, 8, 64));
8850+
for (int n : {16, 33, 64, 128, 130, 200}) {
8851+
test_cases.emplace_back(new test_moe_swiglu_down(GGML_TYPE_NVFP4, 128, 8, 768, n, 2048));
8852+
}
8853+
87628854
// [paged P0 / track B] NVFP4/MXFP4 dense decode-shape mmq_y-down bit-exact gate.
87638855
// The dense FP4 weight GEMM is the track-B target; P1 lowers mmq_y (the weight-row tile) on the
87648856
// NVFP4 decode path to raise resident-CTA occupancy. mmq_y is a pure N-row tiling knob, so a

0 commit comments

Comments
 (0)