29#if defined(__AVX2__) || defined(__AVX512F__)
57 if (!scores || !indices || n <= 0 || k <= 0) {
67 float local_values[k];
68 for (
int i = 0; i < k; i++) {
70 local_values[i] = scores[i];
75 for (
int i = 1; i < k; i++) {
76 if (local_values[i] < local_values[min_idx]) {
82 for (
int i = k; i < n; i++) {
83 if (scores[i] > local_values[min_idx]) {
86 local_values[min_idx] = scores[i];
90 for (
int j = 1; j < k; j++) {
91 if (local_values[j] < local_values[min_idx]) {
99 for (
int i = 1; i < k; i++) {
100 float val = local_values[i];
101 int idx = indices[i];
103 while (j >= 0 && local_values[j] < val) {
104 local_values[j + 1] = local_values[j];
105 indices[j + 1] = indices[j];
108 local_values[j + 1] = val;
109 indices[j + 1] = idx;
114 for (
int i = 0; i < k; i++) {
115 values[i] = local_values[i];
142 if (!scores || !indices || !weights || n <= 0 || k <= 0) {
152 topk_f32(scores, n, k, indices, values);
156 float max_val = values[0];
157 for (
int i = 1; i < k; i++) {
158 if (values[i] > max_val) {
165 for (
int i = 0; i < k; i++) {
166 weights[i] = expf(values[i] - max_val);
171 float inv_sum = 1.0f / sum;
172 for (
int i = 0; i < k; i++) {
173 weights[i] *= inv_sum;
179 if (n_experts <= 0) {
182 return ((
size_t)n_experts *
sizeof(
float) + 63u) & ~(size_t)63u;
185#if defined(__AVX512F__) && defined(__AVX512DQ__)
187static inline __m512 ck_moe_ggml_expf512(__m512 x)
189 const __m512 r = _mm512_set1_ps(0x1.8p23f);
190 const __m512 z = _mm512_fmadd_ps(x, _mm512_set1_ps(0x1.715476p+0f), r);
191 const __m512 n = _mm512_sub_ps(z, r);
192 const __m512 b = _mm512_fnmadd_ps(
193 n, _mm512_set1_ps(0x1.7f7d1cp-20f),
194 _mm512_fnmadd_ps(n, _mm512_set1_ps(0x1.62e4p-1f), x));
195 const __mmask16 d = _mm512_cmp_ps_mask(
196 _mm512_abs_ps(n), _mm512_set1_ps(192.0f), _CMP_GT_OQ);
197 const __m512 u = _mm512_mul_ps(b, b);
198 const __m512 j = _mm512_fmadd_ps(
201 _mm512_set1_ps(0x1.0e4020p-7f), b,
202 _mm512_set1_ps(0x1.573e2ep-5f)),
205 _mm512_set1_ps(0x1.555e66p-3f), b,
206 _mm512_set1_ps(0x1.fffdb6p-2f))),
209 _mm512_set1_ps(0x1.ffffecp-1f), b,
210 _mm512_set1_ps(1.0f)));
211 const __m512 res = _mm512_scalef_ps(j, n);
212 if (_mm512_kortestz(d, d)) {
215 const __m512 zero = _mm512_setzero_ps();
216 const __m512 alt = _mm512_mask_blend_ps(
217 _mm512_cmp_ps_mask(n, zero, _CMP_LE_OQ),
218 _mm512_set1_ps(INFINITY), zero);
219 return _mm512_mask_blend_ps(d, res, alt);
223#if defined(__AVX2__) && defined(__FMA__)
224static inline __m256 ck_moe_ggml_expf256(__m256 x)
226 const __m256 r = _mm256_set1_ps(0x1.8p23f);
227 const __m256 z = _mm256_fmadd_ps(x, _mm256_set1_ps(0x1.715476p+0f), r);
228 const __m256 n = _mm256_sub_ps(z, r);
229 const __m256 b = _mm256_fnmadd_ps(
231 _mm256_set1_ps(0x1.7f7d1cp-20f),
232 _mm256_fnmadd_ps(n, _mm256_set1_ps(0x1.62e4p-1f), x));
233 const __m256i e = _mm256_slli_epi32(_mm256_castps_si256(z), 23);
234 const __m256 k = _mm256_castsi256_ps(
235 _mm256_add_epi32(e, _mm256_castps_si256(_mm256_set1_ps(1))));
236 const __m256i c = _mm256_castps_si256(_mm256_cmp_ps(
237 _mm256_andnot_ps(_mm256_set1_ps(-0.f), n),
240 const __m256 u = _mm256_mul_ps(b, b);
241 const __m256 j = _mm256_fmadd_ps(
244 _mm256_set1_ps(0x1.0e4020p-7f),
246 _mm256_set1_ps(0x1.573e2ep-5f)),
249 _mm256_set1_ps(0x1.555e66p-3f),
251 _mm256_set1_ps(0x1.fffdb6p-2f))),
253 _mm256_mul_ps(_mm256_set1_ps(0x1.ffffecp-1f), b));
254 if (!_mm256_movemask_ps(_mm256_castsi256_ps(c))) {
255 return _mm256_fmadd_ps(j, k, k);
257 const __m256i g = _mm256_and_si256(
258 _mm256_castps_si256(_mm256_cmp_ps(
259 n, _mm256_setzero_ps(), _CMP_LE_OQ)),
260 _mm256_set1_epi32(0x82000000u));
261 const __m256 s1 = _mm256_castsi256_ps(
262 _mm256_add_epi32(g, _mm256_set1_epi32(0x7f000000u)));
263 const __m256 s2 = _mm256_castsi256_ps(_mm256_sub_epi32(e, g));
264 const __m256i d = _mm256_castps_si256(_mm256_cmp_ps(
265 _mm256_andnot_ps(_mm256_set1_ps(-0.f), n),
269 _mm256_and_ps(_mm256_castsi256_ps(d), _mm256_mul_ps(s1, s1)),
271 _mm256_castsi256_ps(d),
274 _mm256_castsi256_ps(c),
275 _mm256_mul_ps(_mm256_fmadd_ps(s2, j, s2), s1)),
277 _mm256_castsi256_ps(c),
278 _mm256_fmadd_ps(k, j, k)))));
289#if defined(__AVX512F__) && defined(__AVX512DQ__)
290 for (; expert + 15 < n_experts; expert += 16) {
291 const __m512 value = ck_moe_ggml_expf512(_mm512_sub_ps(
292 _mm512_loadu_ps(logits + expert), _mm512_set1_ps(max_value)));
293 _mm512_storeu_ps(probabilities + expert, value);
294 sum += (double)_mm512_reduce_add_ps(value);
296#elif defined(__AVX2__) && defined(__FMA__)
297 for (; expert + 7 < n_experts; expert += 8) {
298 const __m256 value = ck_moe_ggml_expf256(_mm256_sub_ps(
299 _mm256_loadu_ps(logits + expert), _mm256_set1_ps(max_value)));
300 _mm256_storeu_ps(probabilities + expert, value);
301 __m128 half = _mm_add_ps(
302 _mm256_extractf128_ps(value, 1), _mm256_castps256_ps128(value));
303 half = _mm_add_ps(half, _mm_movehl_ps(half, half));
304 half = _mm_add_ss(half, _mm_movehdup_ps(half));
305 sum += (double)_mm_cvtss_f32(half);
308 for (; expert < n_experts; ++expert) {
309 const float value = expf(logits[expert] - max_value);
310 probabilities[expert] = value;
311 sum += (double)value;
323 float routed_scaling_factor,
325 size_t workspace_bytes)
328 if (!logits || !indices || !weights || !workspace || rows <= 0 ||
329 n_experts <= 0 || top_k <= 0 || top_k > n_experts ||
330 !isfinite(routed_scaling_factor) || required == 0 ||
331 workspace_bytes < required) {
335 float *probabilities = (
float *)workspace;
336 for (
int row = 0; row < rows; ++row) {
337 const float *row_logits = logits + (size_t)row * (
size_t)n_experts;
338 int *row_indices = indices + (size_t)row * (
size_t)top_k;
339 float *row_weights = weights + (size_t)row * (
size_t)top_k;
340 float max_value = -INFINITY;
341 for (
int expert = 0; expert < n_experts; ++expert) {
342 if (!isfinite(row_logits[expert])) {
345 if (row_logits[expert] > max_value) {
346 max_value = row_logits[expert];
351 probabilities, row_logits, n_experts, max_value);
352 const float inverse_softmax_sum = (float)(1.0 / softmax_sum);
353 for (
int expert = 0; expert < n_experts; ++expert) {
354 probabilities[expert] *= inverse_softmax_sum;
357 topk_f32(probabilities, n_experts, top_k, row_indices, NULL);
358 double selected_sum_f64 = 0.0;
359 for (
int slot = 0; slot < top_k; ++slot) {
360 row_weights[slot] = probabilities[row_indices[slot]];
361 selected_sum_f64 += (double)row_weights[slot];
363 float selected_sum = (float)selected_sum_f64;
364 if (selected_sum < 6.103515625e-5f) {
365 selected_sum = 6.103515625e-5f;
367 for (
int slot = 0; slot < top_k; ++slot) {
369 (row_weights[slot] / selected_sum) * routed_scaling_factor;
382 float routed_scaling_factor,
384 size_t workspace_bytes)
387 logits, indices, weights, rows, n_experts, top_k,
388 routed_scaling_factor, workspace, workspace_bytes);
392 for (
size_t index = 0; index < (size_t)rows * (
size_t)top_k; ++index) {
409 const float *weights,
410 const float *d_weights,
413 int n_experts_or_keys,
416 if (!indices || !weights || !d_weights || !d_scores ||
417 num_tokens <= 0 || n_experts_or_keys <= 0 || k <= 0) {
421 const size_t total = (size_t)num_tokens * (
size_t)n_experts_or_keys;
422 for (
size_t i = 0; i < total; ++i) {
426 for (
int t = 0; t < num_tokens; ++t) {
427 const int *row_indices = indices + (size_t)t * (
size_t)k;
428 const float *row_weights = weights + (size_t)t * (
size_t)k;
429 const float *row_d_weights = d_weights + (size_t)t * (
size_t)k;
430 float *row_d_scores = d_scores + (size_t)t * (
size_t)n_experts_or_keys;
433 for (
int i = 0; i < k; ++i) {
434 const int idx = row_indices[i];
435 if (idx >= 0 && idx < n_experts_or_keys) {
436 dot += row_weights[i] * row_d_weights[i];
440 for (
int i = 0; i < k; ++i) {
441 const int idx = row_indices[i];
442 if (idx >= 0 && idx < n_experts_or_keys) {
443 row_d_scores[idx] += row_weights[i] * (row_d_weights[i] - dot);
472 if (!scores || !indices || num_tokens <= 0 || n_experts <= 0 || k <= 0) {
476 for (
int t = 0; t < num_tokens; t++) {
477 const float *token_scores = scores + t * n_experts;
478 int *token_indices = indices + t * k;
481 float *token_weights = weights + t * k;
484 topk_f32(token_scores, n_experts, k, token_indices, NULL);
502 if (!scores || n <= 0) {
507 float max_val = scores[0];
512 __m512 vmax = _mm512_set1_ps(-FLT_MAX);
513 __m512i vidx = _mm512_setzero_si512();
514 __m512i vcur_max_idx = _mm512_setzero_si512();
517 for (; i + 16 <= n; i += 16) {
518 __m512 v = _mm512_loadu_ps(&scores[i]);
519 __m512i cur_idx = _mm512_add_epi32(
520 _mm512_set1_epi32(i),
521 _mm512_setr_epi32(0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15)
524 __mmask16 gt_mask = _mm512_cmp_ps_mask(v, vmax, _CMP_GT_OQ);
525 vmax = _mm512_mask_blend_ps(gt_mask, vmax, v);
526 vcur_max_idx = _mm512_mask_blend_epi32(gt_mask, vcur_max_idx, cur_idx);
532 _mm512_storeu_ps(vals, vmax);
533 _mm512_storeu_si512(idxs, vcur_max_idx);
537 for (
int j = 1; j < 16; j++) {
538 if (vals[j] > max_val) {
546 if (scores[i] > max_val) {
557 for (
int i = 1; i < n; i++) {
558 if (scores[i] > max_val) {
592 const int ok = (target_token >= 0 && draft_token == target_token) ? 1 : 0;
597 if (verified_token) {
598 *verified_token = ok ? draft_token : target_token;
616 int *target_position,
621 int next_count = token_count ? *token_count : 0;
622 if (token_buffer && token_count && next_count >= 0 && next_count < max_tokens) {
623 token_buffer[next_count] = verified_token;
625 *token_count = next_count;
628 if (target_position) {
629 *target_position += 1;
630 if (draft_position) {
631 *draft_position = *target_position;
633 }
else if (draft_position) {
634 *draft_position += 1;
638 if (accepted_count) {
639 *accepted_count += 1;
642 if (rejected_count) {
643 *rejected_count += 1;
670 for (
int pos = 0; pos < k; ++pos) {
671 if (indices[pos] < 0 || val > values[pos] || (val == values[pos] && idx < indices[pos])) {
672 for (
int j = k - 1; j > pos; --j) {
673 indices[j] = indices[j - 1];
674 values[j] = values[j - 1];
684 const float *correction_bias,
693 float routed_scaling_factor,
696 if (!scores || !indices || !weights || rows <= 0 || n_experts <= 0 ||
697 top_k <= 0 || n_group <= 0 || topk_group <= 0) {
700 if (top_k > n_experts) top_k = n_experts;
701 if (n_group > n_experts) n_group = n_experts;
702 if (topk_group > n_group) topk_group = n_group;
703 const int experts_per_group = n_experts / n_group;
704 if (experts_per_group <= 0 || experts_per_group * n_group != n_experts) {
708 for (
int r = 0; r < rows; ++r) {
709 const float *row_probs = scores + (size_t)r * (
size_t)n_experts;
710 float row_scores[n_experts];
711 for (
int e = 0; e < n_experts; ++e) {
712 row_scores[e] = apply_sigmoid
713 ? (1.0f / (1.0f + expf(-row_probs[e])))
716 int *row_indices = indices + (size_t)r * (
size_t)top_k;
717 float *row_weights = weights + (size_t)r * (
size_t)top_k;
719 int selected_groups[topk_group];
720 float selected_group_scores[topk_group];
721 for (
int i = 0; i < topk_group; ++i) {
722 selected_groups[i] = -1;
723 selected_group_scores[i] = -FLT_MAX;
726 for (
int g = 0; g < n_group; ++g) {
727 float best0 = -FLT_MAX;
728 float best1 = -FLT_MAX;
729 const int start = g * experts_per_group;
730 for (
int j = 0; j < experts_per_group; ++j) {
731 const int e =
start + j;
732 const float v = row_scores[e] + (correction_bias ? correction_bias[e] : 0.0f);
736 }
else if (v > best1) {
740 const float group_score = best0 + ((experts_per_group >= 2) ? best1 : 0.0f);
745 float out_choice[top_k];
746 for (
int i = 0; i < top_k; ++i) {
748 out_choice[i] = -FLT_MAX;
751 for (
int sg = 0; sg < topk_group; ++sg) {
752 const int g = selected_groups[sg];
754 const int start = g * experts_per_group;
755 for (
int j = 0; j < experts_per_group; ++j) {
756 const int e =
start + j;
757 const float v = row_scores[e] + (correction_bias ? correction_bias[e] : 0.0f);
762 float denom = 1.0e-20f;
763 for (
int i = 0; i < top_k; ++i) {
764 const int e = out_idx[i];
765 const float w = (e >= 0 && e < n_experts) ? row_scores[e] : 0.0f;
770 for (
int i = 0; i < top_k; ++i) {
771 float w = row_weights[i];
772 if (norm_topk_prob) {
775 row_weights[i] = w * routed_scaling_factor;
781 const float *correction_bias,
790 float routed_scaling_factor)
793 scores, correction_bias, indices, weights, rows, n_experts, top_k,
794 n_group, topk_group, norm_topk_prob, routed_scaling_factor, 0
799 const float *correction_bias,
808 float routed_scaling_factor)
811 logits, correction_bias, indices, weights, rows, n_experts, top_k,
812 n_group, topk_group, norm_topk_prob, routed_scaling_factor, 1
static uint16_t float_to_bf16(float f)
static float bf16_to_float(uint16_t v)
void topk_batched_f32(const float *scores, int num_tokens, int n_experts, int k, int *indices, float *weights)
Batched top-K selection for multiple tokens.
void topk_softmax_backward_f32(const int *indices, const float *weights, const float *d_weights, float *d_scores, int num_tokens, int n_experts_or_keys, int k)
Backward for hard top-k followed by softmax over selected values.
void group_limited_topk_router_sigmoid_f32(const float *logits, const float *correction_bias, int *indices, float *weights, int rows, int n_experts, int top_k, int n_group, int topk_group, int norm_topk_prob, float routed_scaling_factor)
int moe_softmax_topk_router_llama_f32_workspace(const float *logits, int *indices, float *weights, int rows, int n_experts, int top_k, float routed_scaling_factor, void *workspace, size_t workspace_bytes)
static double ck_moe_llama_softmax_row(float *probabilities, const float *logits, int n_experts, float max_value)
int argmax_f32(const float *scores, int n)
Find index of maximum value.
static void ck_topk_insert_desc(int idx, float val, int *indices, float *values, int k)
size_t moe_softmax_topk_router_workspace_bytes(int n_experts)
void nemotron_group_limited_topk_router_f32(const float *scores, const float *correction_bias, int *indices, float *weights, int rows, int n_experts, int top_k, int n_group, int topk_group, int norm_topk_prob, float routed_scaling_factor)
void topk_f32(const float *scores, int n, int k, int *indices, float *values)
Find top-K indices and values from a score vector.
void speculative_verify_greedy_f32(const float *target_logits, int vocab_size, int draft_token, int *accepted, int *verified_token)
Greedy one-token speculative verification.
void topk_softmax_f32(const float *scores, int n, int k, int *indices, float *weights)
Find top-K indices with softmax-normalized weights.
void speculative_commit_one_i32(int accepted, int verified_token, int *token_buffer, int *token_count, int max_tokens, int *target_position, int *draft_position, int *accepted_count, int *rejected_count)
Commit one verified speculative token and update decode counters.
int moe_softmax_topk_router_pytorch_bf16_workspace(const float *logits, int *indices, float *weights, int rows, int n_experts, int top_k, float routed_scaling_factor, void *workspace, size_t workspace_bytes)
static void group_limited_topk_router_f32_impl(const float *scores, const float *correction_bias, int *indices, float *weights, int rows, int n_experts, int top_k, int n_group, int topk_group, int norm_topk_prob, float routed_scaling_factor, int apply_sigmoid)