| 809 | // - Block KV cache is hydrated. |
| 810 | template <typename T> |
| 811 | void Block::_block_cpu( |
| 812 | InferenceState& s, // inference state |
| 813 | int pos, // index of the current token in the sequence |
| 814 | int kv_sink, // number of sink tokens currently in the KV cache |
| 815 | int kv_pos, // index of the current token in the kv cache, must be in [0..kv_len) since kv cache is a ring buffer |
| 816 | int kv_len // number of tokens in the kv cache that we will attend over |
| 817 | ) const { |
| 818 | const Config& c = *_config; |
| 819 | |
| 820 | // Attention pre-norm |
| 821 | switch (c.norm_type) { |
| 822 | case LayerNormType::RMSNorm: { |
| 823 | rmsnorm(s.xb(), s.x(), rms_att_weight(), c.dim, c.norm_eps); |
| 824 | break; |
| 825 | } |
| 826 | } |
| 827 | |
| 828 | // Attention output into `hb` |
| 829 | attention_impl(s, pos, kv_sink, kv_pos, kv_len); |
| 830 | |
| 831 | // Residual back into `x` |
| 832 | for (int i = 0; i < c.dim; ++i) { |
| 833 | s.x()[i] += s.hb()[i]; |
| 834 | } |
| 835 | |
| 836 | // FFN pre-norm |
| 837 | switch (c.norm_type) { |
| 838 | case LayerNormType::RMSNorm: { |
| 839 | rmsnorm(s.xb(), s.x(), rms_ffn_weight(), c.dim, c.norm_eps); |
| 840 | break; |
| 841 | } |
| 842 | } |
| 843 | |
| 844 | if (c.n_routed_experts > 0 && moegate() != std::nullopt) { |
| 845 | PROFILE_BLOCK(ffn_moe); |
| 846 | // Block is a sparse MoE FFN layer |
| 847 | PROFILE(matmul_unscaled(s.moe_weights(), s.xb(), *moegate())); |
| 848 | moe_gate( |
| 849 | s.active_experts_weights(), moegate_bias(), s.active_experts(), s.moe_weights(), |
| 850 | c.n_routed_experts, c.n_active_routed, c.norm_topk_prob, c.routed_scaling_factor, |
| 851 | c.scoring_func, c.topk_method, c.n_group, c.topk_group |
| 852 | ); |
| 853 | for (int k = 0; k < c.n_active_routed; ++k) { |
| 854 | int expert_index = s.active_experts()[k]; |
| 855 | // mix self.w2(F.silu(self.w1(x)) * self.w3(x)) |
| 856 | // Note this is a feedforward with a GLU, not a simple MLP. |
| 857 | PROFILE(matmul_expert(s.hb(), s.xb(), *w1(), expert_index, c.block_size.data(), _s1, s.aqb())); |
| 858 | PROFILE(matmul_expert(s.hb2(), s.xb(), *w3(), expert_index, c.block_size.data(), _s3, s.aqb())); |
| 859 | switch (c.act) { |
| 860 | case ActivationType::GELU: { |
| 861 | for (int i = 0; i < c.moe_intermediate_size; ++i) { |
| 862 | s.hb()[i] = gelu(s.hb()[i]) * s.hb2()[i]; |
| 863 | } |
| 864 | break; |
| 865 | } |
| 866 | case ActivationType::SILU: { |
| 867 | for (int i = 0; i < c.moe_intermediate_size; ++i) { |
| 868 | s.hb()[i] = silu(s.hb()[i]) * s.hb2()[i]; |
nothing calls this directly
no test coverage detected