| 491 | } |
| 492 | |
| 493 | static void moe_gate( |
| 494 | float* moe_weights, |
| 495 | std::optional<QTensor> moegate_bias, |
| 496 | int* active_experts, |
| 497 | float* x, |
| 498 | int n_routed_experts, |
| 499 | int n_active_routed, |
| 500 | bool norm_topk_prob, |
| 501 | float routed_scaling_factor, |
| 502 | ScoringFunc scoring_func, |
| 503 | TopKMethod topk_method, |
| 504 | int n_group, |
| 505 | int topk_group |
| 506 | ) { |
| 507 | // Set moe_weights[:n_active_routed] to the weights of the top K experts. |
| 508 | // Set active_experts[:n_active_routed] to the indices of the top K experts. |
| 509 | if (scoring_func == ScoringFunc::SOFTMAX) { |
| 510 | softmax(x, x, n_routed_experts); |
| 511 | } else if (scoring_func == ScoringFunc::SIGMOID) { |
| 512 | for (int i = 0; i < n_routed_experts; i++) { |
| 513 | x[i] = sigmoid(x[i]); |
| 514 | } |
| 515 | } |
| 516 | |
| 517 | if (moegate_bias) { |
| 518 | float* bias_data = static_cast<float*>(moegate_bias->data); |
| 519 | for (int i = 0; i < n_routed_experts; ++i) { |
| 520 | x[i] += bias_data[i]; |
| 521 | } |
| 522 | } |
| 523 | |
| 524 | // top k |
| 525 | float wsum = 0.0f; |
| 526 | if (topk_method == TopKMethod::GREEDY) { |
| 527 | assert(n_routed_experts <= 256); |
| 528 | std::array<uint8_t, 32> mask{}; |
| 529 | for (int k = 0; k < n_active_routed; ++k) { |
| 530 | int best = -1; |
| 531 | for (int j = 0; j < n_routed_experts; ++j) { |
| 532 | int mask_i = j / 8; |
| 533 | int mask_r = j % 8; |
| 534 | if ((mask[mask_i] & (1ull << mask_r)) == 0 && (best == -1 || x[j] > x[best])) { |
| 535 | best = j; |
| 536 | } |
| 537 | } |
| 538 | |
| 539 | active_experts[k] = best; |
| 540 | wsum += x[active_experts[k]]; |
| 541 | int best_mask_i = best / 8; |
| 542 | int best_mask_r = best % 8; |
| 543 | mask[best_mask_i] |= 1ull << best_mask_r; |
| 544 | } |
| 545 | } else if (topk_method == TopKMethod::GROUP_LIMITED_GREEDY) { |
| 546 | int group_size = n_routed_experts / n_group; |
| 547 | |
| 548 | // First pass: select topk_group within each group |
| 549 | std::array<uint8_t, 32> mask{}; |
| 550 |
no test coverage detected