Allocate per-layer KV state: a raw sliding window for all layers, plus * compressed attention/indexer caches for layers whose ratio is nonzero. */
| 8482 | matvec_iq2_xxs_accum_ctx ctx = { |
| 8483 | .out = out, |
| 8484 | .in_dim = in_dim0, |
| 8485 | .n_expert = n_expert, |
| 8486 | }; |
| 8487 | for (int i = 0; i < n_expert; i++) { |
| 8488 | ctx.base[i] = base[i]; |
| 8489 | ctx.row_bytes[i] = row_bytes[i]; |
| 8490 | ctx.xq[i] = xq + (uint64_t)i * n_blocks; |
| 8491 | } |
| 8492 | |
| 8493 | ds4_parallel_for(out_dim0, matvec_iq2_xxs_accum_worker, &ctx); |
| 8494 | } |
| 8495 | |
| 8496 | typedef struct { |
| 8497 | uint32_t token; |
| 8498 | uint32_t slot; |
| 8499 | } ds4_expert_pair; |
| 8500 | |
| 8501 | typedef struct { |
| 8502 | float *mid; |
| 8503 | const uint8_t *gate_base[DS4_MAX_EXPERT]; |
| 8504 | const uint8_t *up_base[DS4_MAX_EXPERT]; |
| 8505 | const block_q8_K *xq; |
| 8506 | const ds4_expert_pair *pairs; |
| 8507 | const uint32_t *pair_ids; |
| 8508 | const uint32_t *expert_offset; |
| 8509 | const uint32_t *active_expert; |
| 8510 | const float *pair_weight; |
| 8511 | float clamp; |
| 8512 | uint64_t in_dim; |
| 8513 | uint64_t out_dim; |
| 8514 | uint64_t gate_row_bytes[DS4_MAX_EXPERT]; |
| 8515 | uint64_t up_row_bytes[DS4_MAX_EXPERT]; |
| 8516 | uint64_t xq_blocks; |
| 8517 | } matvec_q2_k_batch_mid_ctx; |
| 8518 | |
| 8519 | static void matvec_q2_k_batch_mid_worker(void *vctx, uint64_t task0, uint64_t task1) { |
| 8520 | matvec_q2_k_batch_mid_ctx *ctx = vctx; |
| 8521 | |
| 8522 | for (uint64_t task = task0; task < task1; task++) { |
| 8523 | const uint32_t active_idx = (uint32_t)(task / ctx->out_dim); |
| 8524 | const uint64_t row = task - (uint64_t)active_idx * ctx->out_dim; |
| 8525 | const uint32_t expert = ctx->active_expert[active_idx]; |
| 8526 | const uint32_t begin = ctx->expert_offset[expert]; |
| 8527 | const uint32_t end = ctx->expert_offset[expert + 1]; |
no test coverage detected