@@ -1070,7 +1070,8 @@ ggml_tensor * llm_graph_context::build_moe_ffn(
10701070 float w_scale,
10711071 llama_expert_gating_func_type gating_op,
10721072 int il,
1073- ggml_tensor * probs_in) const {
1073+ ggml_tensor * probs_in,
1074+ ggml_tensor * gate_up_exps) const {
10741075 return build_moe_ffn (
10751076 cur,
10761077 gate_inp, /* gate_inp_b */ nullptr ,
@@ -1086,7 +1087,8 @@ ggml_tensor * llm_graph_context::build_moe_ffn(
10861087 w_scale,
10871088 gating_op,
10881089 il,
1089- probs_in
1090+ probs_in,
1091+ gate_up_exps
10901092 );
10911093}
10921094
@@ -1109,7 +1111,9 @@ ggml_tensor * llm_graph_context::build_moe_ffn(
11091111 float w_scale,
11101112 llama_expert_gating_func_type gating_op,
11111113 int il,
1112- ggml_tensor * probs_in) const {
1114+ ggml_tensor * probs_in,
1115+ ggml_tensor * gate_up_exps,
1116+ ggml_tensor * gate_up_exps_b) const {
11131117 const int64_t n_embd = cur->ne [0 ];
11141118 const int64_t n_tokens = cur->ne [1 ];
11151119 const bool weight_before_ffn = arch == LLM_ARCH_LLAMA4 ; // for llama4, we apply the sigmoid-ed weights before the FFN
@@ -1248,38 +1252,60 @@ ggml_tensor * llm_graph_context::build_moe_ffn(
12481252 cb (cur, " ffn_moe_weighted" , il);
12491253 }
12501254
1251- ggml_tensor * up = build_lora_mm_id (up_exps, cur, selected_experts); // [n_ff, n_expert_used, n_tokens]
1252- cb (up, " ffn_moe_up " , il) ;
1255+ ggml_tensor * up = nullptr ;
1256+ ggml_tensor * experts = nullptr ;
12531257
1254- if (up_exps_b ) {
1255- up = ggml_add_id (ctx0, up, up_exps_b, selected_experts);
1256- cb (up, " ffn_moe_up_biased " , il);
1257- }
1258+ if (gate_up_exps ) {
1259+ // merged gate_up path: one mul_mat_id, then split into gate and up views
1260+ ggml_tensor * gate_up = build_lora_mm_id (gate_up_exps, cur, selected_experts); // [n_ff*2, n_expert_used, n_tokens]
1261+ cb (gate_up, " ffn_moe_gate_up " , il);
12581262
1259- ggml_tensor * experts = nullptr ;
1260- if (gate_exps) {
1261- cur = build_lora_mm_id (gate_exps, cur, selected_experts); // [n_ff, n_expert_used, n_tokens]
1263+ if (gate_up_exps_b) {
1264+ gate_up = ggml_add_id (ctx0, gate_up, gate_up_exps_b, selected_experts);
1265+ cb (gate_up, " ffn_moe_gate_up_biased" , il);
1266+ }
1267+
1268+ const int64_t n_ff = gate_up->ne [0 ] / 2 ;
1269+ cur = ggml_view_3d (ctx0, gate_up, n_ff, gate_up->ne [1 ], gate_up->ne [2 ], gate_up->nb [1 ], gate_up->nb [2 ], 0 );
12621270 cb (cur, " ffn_moe_gate" , il);
1271+ up = ggml_view_3d (ctx0, gate_up, n_ff, gate_up->ne [1 ], gate_up->ne [2 ], gate_up->nb [1 ], gate_up->nb [2 ], n_ff * gate_up->nb [0 ]);
1272+ cb (up, " ffn_moe_up" , il);
12631273 } else {
1264- cur = up;
1265- }
1274+ // separate gate and up path
1275+ up = build_lora_mm_id (up_exps, cur, selected_experts); // [n_ff, n_expert_used, n_tokens]
1276+ cb (up, " ffn_moe_up" , il);
12661277
1267- if (gate_exps_b) {
1268- cur = ggml_add_id (ctx0, cur, gate_exps_b, selected_experts);
1269- cb (cur, " ffn_moe_gate_biased" , il);
1278+ if (up_exps_b) {
1279+ up = ggml_add_id (ctx0, up, up_exps_b, selected_experts);
1280+ cb (up, " ffn_moe_up_biased" , il);
1281+ }
1282+
1283+ if (gate_exps) {
1284+ cur = build_lora_mm_id (gate_exps, cur, selected_experts); // [n_ff, n_expert_used, n_tokens]
1285+ cb (cur, " ffn_moe_gate" , il);
1286+ } else {
1287+ cur = up;
1288+ }
1289+
1290+ if (gate_exps_b) {
1291+ cur = ggml_add_id (ctx0, cur, gate_exps_b, selected_experts);
1292+ cb (cur, " ffn_moe_gate_biased" , il);
1293+ }
12701294 }
12711295
1296+ const bool has_gate = gate_exps || gate_up_exps;
1297+
12721298 switch (type_op) {
12731299 case LLM_FFN_SILU :
1274- if (gate_exps ) {
1300+ if (has_gate ) {
12751301 cur = ggml_swiglu_split (ctx0, cur, up);
12761302 cb (cur, " ffn_moe_swiglu" , il);
12771303 } else {
12781304 cur = ggml_silu (ctx0, cur);
12791305 cb (cur, " ffn_moe_silu" , il);
12801306 } break ;
12811307 case LLM_FFN_GELU :
1282- if (gate_exps ) {
1308+ if (has_gate ) {
12831309 cur = ggml_geglu_split (ctx0, cur, up);
12841310 cb (cur, " ffn_moe_geglu" , il);
12851311 } else {
@@ -1295,15 +1321,15 @@ ggml_tensor * llm_graph_context::build_moe_ffn(
12951321 cb (cur, " ffn_moe_swiglu_oai" , il);
12961322 } break ;
12971323 case LLM_FFN_RELU :
1298- if (gate_exps ) {
1324+ if (has_gate ) {
12991325 cur = ggml_reglu_split (ctx0, cur, up);
13001326 cb (cur, " ffn_moe_reglu" , il);
13011327 } else {
13021328 cur = ggml_relu (ctx0, cur);
13031329 cb (cur, " ffn_moe_relu" , il);
13041330 } break ;
13051331 case LLM_FFN_RELU_SQR :
1306- if (gate_exps ) {
1332+ if (has_gate ) {
13071333 // TODO: add support for gated squared relu
13081334 GGML_ABORT (" fatal error: gated squared relu not implemented" );
13091335 } else {
0 commit comments