/* Copyright 2025 The xLLM Authors. All Rights Reserved. Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at https://github.com/jd-opensource/xllm/blob/main/LICENSE Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. ==============================================================================*/ #include "ops_api.h" #if defined(USE_MLU) #include "mlu/mlu_ops_api.h" #elif defined(USE_NPU) #include "core/kernels/npu/tilelang/tilelang_ops_api.h" #include "npu/npu_ops_api.h" #include "triton_npu/torch_api/triton_ops_api.h" #elif defined(USE_CUDA) #include "cuda/attention_runner.h" #include "cuda/cuda_ops_api.h" #elif defined(USE_ILU) #include "ilu/ilu_ops_api.h" #elif defined(USE_MUSA) #include "cuda/cuda_ops_api.h" #include "musa/musa_ops_api.h" #endif #include #include "common/macros.h" #include "layers/common/attention_metadata.h" namespace xllm::kernel { void apply_rotary(RotaryParams& params) { #if defined(USE_MLU) mlu::apply_rotary(params.q, params.k, params.sin, params.cos, params.position_ids, params.cu_query_lens, params.interleaved, params.discrete, params.dynamic_ntk, params.max_query_len); #elif defined(USE_NPU) npu::apply_rotary( params.q, params.k, params.cos_sin, params.position_ids.value()); #elif defined(USE_CUDA) || defined(USE_MUSA) bool is_neox = !params.interleaved; torch::Tensor pos_ids; torch::Tensor cos_sin; if (params.position_ids.has_value()) { // positions is already int64 on CUDA/MUSA (pre-converted in // ForwardInput::to). pos_ids = params.position_ids.value().to(torch::kInt64); } else if (params.cu_query_lens.has_value()) { auto cu = params.cu_query_lens.value().to(torch::kInt64); CHECK(cu.numel() >= 2) << "apply_rotary (CUDA): cu_query_lens must have at " "least 2 elements when " "position_ids is not provided."; int64_t seq_len = cu[1].item() - cu[0].item(); CHECK(seq_len > 0) << "apply_rotary (CUDA): invalid sequence length inferred from " "cu_query_lens when position_ids is not provided."; pos_ids = torch::arange(seq_len, torch::TensorOptions() .dtype(torch::kInt64) .device(params.q.device())) .contiguous(); } else { // When neither position_ids nor cu_query_lens is provided, // infer sequence length from q tensor and create default position IDs. // This handles cases like LongCat-Image-Edit where rotary embedding // is applied uniformly across all sequence positions. int64_t seq_len = params.q.size(0); CHECK(seq_len > 0) << "apply_rotary (CUDA): cannot infer valid sequence " "length from q tensor."; pos_ids = torch::arange(seq_len, torch::TensorOptions() .dtype(torch::kInt64) .device(params.q.device())) .contiguous(); } if (params.precomputed_cos_sin.defined()) { cos_sin = params.precomputed_cos_sin; } else if (params.cos.defined() && params.sin.defined()) { const int64_t head_dim = params.cos.size(-1); const int64_t rot_half = head_dim / 2; auto cos_sliced = params.cos.contiguous().slice(-1, 0, rot_half); auto sin_sliced = params.sin.contiguous().slice(-1, 0, rot_half); cos_sin = torch::cat({cos_sliced, sin_sliced}, -1); } else if (params.cos_sin.defined()) { auto cos_sin_vec = params.cos_sin.chunk(4, -1); auto cos = cos_sin_vec[0]; auto sin = cos_sin_vec[2]; cos_sin = torch::cat({cos, sin}, -1); } else { LOG(FATAL) << "apply_rotary (CUDA): neither cos_sin nor cos/sin " "provided; cannot infer cos_sin."; } cuda::rotary_embedding(pos_ids, params.q, params.k, cos_sin, is_neox); #elif defined(USE_ILU) torch::Tensor ilu_cos_sin; if (params.precomputed_cos_sin.defined()) { ilu_cos_sin = params.precomputed_cos_sin; } else { auto cos_sin_vec = params.cos_sin.chunk(4, -1); ilu_cos_sin = torch::cat({cos_sin_vec[0], cos_sin_vec[2]}, -1); } // positions is already int64 on ILU (pre-converted in ForwardInput::to). torch::Tensor long_position_ids = params.position_ids.value().to(at::kLong); ilu::apply_rope_pos_ids_cos_sin_cache( params.q, params.k, ilu_cos_sin, long_position_ids, params.interleaved); #else NOT_IMPLEMENTED(); #endif } void active(ActivationParams& params) { #if defined(USE_MLU) mlu::active(params.input, params.output, params.bias, params.cusum_token_count, params.act_mode, params.is_gated, params.start_expert_id, params.expert_size); #elif defined(USE_NPU) params.output = npu::active(params.input, params.act_mode); #elif defined(USE_CUDA) || defined(USE_MUSA) cuda::act_and_mul(params.output, params.input, params.act_mode); #elif defined(USE_ILU) ilu::act_and_mul(params.output, params.input, params.act_mode); #else NOT_IMPLEMENTED(); #endif } void reshape_paged_cache(ReshapePagedCacheParams& params) { #if defined(USE_MLU) mlu::reshape_paged_cache(params.key, params.value, params.k_cache, params.v_cache, params.slot_mapping, params.direction); #elif defined(USE_NPU) npu::reshape_paged_cache(params.key, params.value, params.k_cache, params.v_cache, params.slot_mapping); #elif defined(USE_CUDA) || defined(USE_MUSA) cuda::reshape_paged_cache(params.slot_mapping, params.key, params.value.value_or(torch::Tensor()), params.k_cache, params.v_cache.value_or(torch::Tensor())); #elif defined(USE_ILU) // auto v_cache = params.v_cache.value_or(torch::Tensor()); ilu::reshape_paged_cache(params.key, params.value, params.k_cache, params.v_cache, params.slot_mapping); #else NOT_IMPLEMENTED(); #endif } void reshape_from_cache(ReshapeFromCacheParams& params) { #if defined(USE_MLU) mlu::reshape_from_cache(params.key, params.value, params.key_cache, params.value_cache, params.context_lengths, params.max_context_len, params.context_seq_offset, params.block_tables, params.cache_seq_offset); #else NOT_IMPLEMENTED(); #endif } void quant_to_paged_cache(ReshapePagedCacheParams& params) { #if defined(USE_MLU) CHECK(params.k_cache_scale.has_value()) << "k_cache_scale is required for quant_to_paged_cache"; mlu::quant_to_paged_cache(params.key, params.value, params.k_cache, params.v_cache, params.k_cache_scale.value(), params.v_cache_scale, params.slot_mapping); #else NOT_IMPLEMENTED(); #endif } void dequant_from_paged_cache(ReshapeFromCacheParams& params) { #if defined(USE_MLU) CHECK(params.key_cache_quant_scale.has_value()) << "key_cache_quant_scale is required for dequant_from_paged_cache"; mlu::dequant_from_paged_cache(params.key, params.value, params.key_cache, params.value_cache, params.key_cache_quant_scale.value(), params.value_cache_quant_scale, params.context_lengths, params.max_context_len, params.context_seq_offset, params.block_tables.value(), params.quant_mode, params.quant_bit); #else NOT_IMPLEMENTED(); #endif } void fused_layernorm(FusedLayerNormParams& params) { #if defined(USE_MLU) mlu::fused_layernorm(params.input, params.output, params.residual, params.weight, params.beta, params.bias, params.quant_scale, params.residual_out, params.smooth_quant_scale, params.normed_out, params.mode, params.eps, params.store_output_before_norm, params.store_output_after_norm, params.dynamic_quant); #elif defined(USE_MUSA) musa::fused_layernorm(params.input, params.output, params.residual, params.weight, params.beta, params.bias, params.quant_scale, params.residual_out, params.smooth_quant_scale, params.normed_out, params.mode, params.eps, params.store_output_before_norm, params.store_output_after_norm, params.dynamic_quant); #elif defined(USE_NPU) if (params.residual.has_value()) { std::tie(params.output, std::ignore, params.residual_out) = npu::add_rms_norm( params.input, params.residual.value(), params.weight, params.eps); } else { params.output = npu::rms_norm(params.input, params.weight, params.eps, params.mode); } #elif defined(USE_CUDA) || defined(USE_MUSA) if (params.residual.has_value()) { cuda::fused_add_rms_norm( params.input, params.residual.value(), params.weight, params.eps); params.output = params.input; params.residual_out = params.residual; } else { cuda::rms_norm(params.output, params.input, params.weight, params.eps); } #elif defined(USE_ILU) if (params.residual.has_value()) { ilu::residual_layer_norm(params.input, params.output, params.residual, params.weight, params.bias, // residual_bias params.residual_out, params.eps); } else { ilu::rms_norm(params.output, params.input, params.weight, params.eps); } #else NOT_IMPLEMENTED(); #endif } torch::Tensor matmul(MatmulParams& params) { #if defined(USE_MLU) return mlu::matmul( params.a, params.b, params.bias, params.c, params.alpha, params.beta); #elif defined(USE_NPU) return npu::matmul(params.a, params.b, params.bias); #elif defined(USE_CUDA) || defined(USE_MUSA) return cuda::matmul(params.a, params.b, params.bias); #elif defined(USE_ILU) return ilu::matmul(params.a, params.b, params.bias); #else NOT_IMPLEMENTED(); #endif } torch::Tensor group_gemm(GroupGemmParams& params) { #if defined(USE_MLU) return mlu::group_gemm(params.a, params.b, params.token_count, params.output, params.a_scale, params.b_scale, params.quant_flag, params.max_dim, params.trans_a, params.trans_b, params.a_quant_bit); #elif defined(USE_NPU) std::vector x_list; std::vector weight_list; torch::TensorList x_ref; torch::TensorList weight_ref; if (params.x_list.has_value()) { x_ref = params.x_list.value(); } else { x_list = {params.a}; x_ref = x_list; } if (params.weight_list.has_value()) { weight_ref = params.weight_list.value(); } else { weight_list = {params.b}; weight_ref = weight_list; } std::optional group_list = params.group_list; if (!group_list.has_value()) { group_list = params.token_count; } auto outputs = npu::apply_npu_grouped_matmul(x_ref, weight_ref, params.bias_list, params.scale_list, params.offset_list, params.antiquant_scale_list, params.antiquant_offset_list, params.per_token_scale_list, group_list, params.activation_input_list, params.activation_quant_scale_list, params.activation_quant_offset_list, params.split_item, params.group_type, params.group_list_type, params.act_type, params.tuning_config, params.output_dtype); return outputs.back(); #elif defined(USE_ILU) return ilu::group_gemm(params.a, params.b, params.token_count, params.combine_idx, params.output); #else NOT_IMPLEMENTED(); #endif } std::tuple moe_active_topk( MoeFusedTopkParams& params) { #if defined(USE_MLU) return mlu::moe_active_topk(params.input, params.topk, params.num_expert_group, params.topk_group, params.normalize, params.mask, params.normed_by, params.scoring_func, params.route_scale, params.e_score_correction_bias); #elif defined(USE_NPU) CHECK_EQ(params.scoring_func, "softmax") << "Only softmax is supported for NPU"; auto [topk_weights, topk_ids, row_ids] = npu::apply_moe_gating_topk_softmax( params.input, params.finished, params.topk); (void)row_ids; return std::make_tuple(topk_weights, topk_ids); #elif defined(USE_ILU) return ilu::moe_active_topk(params.input, params.topk, params.num_expert_group, params.topk_group, params.normalize, params.mask, params.normed_by, params.scoring_func, params.route_scale, params.e_score_correction_bias); #elif defined(USE_CUDA) || defined(USE_MUSA) return cuda::moe_fused_topk(params.input, params.topk, params.normalize, params.e_score_correction_bias, params.scoring_func); #else NOT_IMPLEMENTED(); #endif } std::vector moe_gen_idx(MoeGenIdxParams& params) { #if defined(USE_MLU) return mlu::moe_gen_idx(params.expert_id, params.expert_num); #elif defined(USE_ILU) return ilu::moe_gen_idx(params.expert_id, params.expert_num); #else NOT_IMPLEMENTED(); #endif } torch::Tensor moe_expand_input(MoeExpandInputParams& params) { #if defined(USE_MLU) return mlu::moe_expand_input(params.input, params.gather_index, params.cusum_token_count, params.start_expert_id, params.expert_size); #elif defined(USE_ILU) return ilu::moe_expand_input( params.input, params.gather_index, params.combine_idx, params.topk); #else NOT_IMPLEMENTED(); #endif } torch::Tensor moe_combine_result(MoeCombineResultParams& params) { #if defined(USE_MLU) return mlu::moe_combine_result(params.input, params.reduce_weight, params.gather_ids, params.residual, params.cusum_token_count, params.start_expert_id, params.expert_size, params.bias); #elif defined(USE_NPU) std::optional probes = params.probes.has_value() ? params.probes : std::optional(params.reduce_weight); auto output = npu::apply_npu_moe_token_unpermute(params.input, params.gather_ids, probes, params.padded_mode, params.restore_shape); if (params.residual.has_value()) { output = output + params.residual.value(); } return output; #elif defined(USE_ILU) return ilu::moe_combine_result(params.input, params.reduce_weight); #else NOT_IMPLEMENTED(); #endif } torch::Tensor moe_all2all_gen_send_layout( MoeAll2AllGenSendLayoutParams& params) { #if defined(USE_MLU) return mlu::moe_all2all_gen_send_layout(params.token_count, params.nrank); #else NOT_IMPLEMENTED(); #endif } std::vector moe_all2all_gen_gather_index( MoeAll2AllGenGatherIndexParams& params) { #if defined(USE_MLU) return mlu::moe_all2all_gen_gather_index( params.token_num, params.pad_num, params.return_cusum_token_count); #else NOT_IMPLEMENTED(); #endif } std::vector moe_all2all_create(MoeAll2AllCreateParams& params) { #if defined(USE_MLU) return mlu::moe_all2all_create(params.dispatch_token_byte, params.combine_token_byte, params.max_expert_num, params.max_token_num, params.rank, params.nrank, params.device); #else NOT_IMPLEMENTED(); #endif } void moe_all2all_init(MoeAll2AllInitParams& params) { #if defined(USE_MLU) mlu::moe_all2all_init(params.handle, params.all_exchange_info, params.device); #else NOT_IMPLEMENTED(); #endif } void moe_all2all_dispatch(MoeAll2AllDispatchParams& params) { #if defined(USE_MLU) mlu::moe_all2all_dispatch(params.handle, params.token_byte, params.token_num, params.send_layout, params.send_token_num, params.recv_layout, params.recv_token_num, params.send_token, params.recv_token); #else NOT_IMPLEMENTED(); #endif } void moe_all2all_combine(MoeAll2AllCombineParams& params) { #if defined(USE_MLU) mlu::moe_all2all_combine(params.handle, params.token_byte, params.token_num, params.send_src_layout, params.send_dst_layout, params.send_token, params.recv_token); #else NOT_IMPLEMENTED(); #endif } void moe_all2all_destroy(MoeAll2AllDestroyParams& params) { #if defined(USE_MLU) mlu::moe_all2all_destroy(params.handle, params.device); #else NOT_IMPLEMENTED(); #endif } std::tuple scaled_quantize( ScaledQuantizeParams& params) { #if defined(USE_MLU) return mlu::scaled_quantize(params.x, params.smooth, params.zero, params.token_count, params.gather_index, params.gather_index_start_position, params.output, params.output_scale, params.act_mode, params.active_coef, params.is_gated, params.quant_type); #else NOT_IMPLEMENTED(); #endif } torch::Tensor scaled_matmul(ScaledMatmulParams& params) { #if defined(USE_MLU) return mlu::scaled_matmul(params.a, params.b, params.a_scale, params.b_scale, params.output_dtype, params.bias, params.c, params.act_mode, params.quant_bit_size, params.alpha, params.beta, params.use_hp_active, params.a_quant_bit_size, params.a_calib, params.b_calib, params.output); #else NOT_IMPLEMENTED(); #endif } torch::Tensor apply_top_k_top_p(TopKPParams& params) { #if defined(USE_MLU) return mlu::apply_top_k_top_p( params.logits, params.temperatures, params.top_k, params.top_p); #else NOT_IMPLEMENTED(); #endif } torch::Tensor random_sample(RandomSampleParams& params) { #if defined(USE_MLU) return mlu::random_sample(params.logits); #elif defined(USE_CUDA) return cuda::random_sample(params.logits); #else NOT_IMPLEMENTED(); #endif } torch::Tensor rejection_sample(RejectionSampleParams& params) { #if defined(USE_MLU) return mlu::rejection_sample(params.draft_token_ids, params.num_draft_tokens, params.cu_num_draft_tokens, params.draft_probs, params.target_probs, params.bonus_token_ids, params.uniform_rand, params.uniform_probs, params.max_spec_len); #else NOT_IMPLEMENTED(); #endif } void masked_indexer_select_paged_kv(MaskedIndexerSelectPagedKVParams& params) { #if defined(USE_MLU) mlu::masked_indexer_select_paged_kv(params.query, params.k_cache, params.weights, params.kv_cache_block_table, params.cu_seq_q_lens, params.cu_seq_k_lens, params.k_context_lens, params.k_cache_block_table, params.is_prefill, params.index_topk, params.kv_cache_block_size, params.softmax_scale, params.q_scale, params.k_scale_cache, params.sparse_block_table, params.sparse_context_lens); #else NOT_IMPLEMENTED(); #endif } void gather_split(GatherSplitParams& params) { #if defined(USE_MLU) mlu::gather_split(params.input, params.gather_index, params.valid_token_num, params.output_head, params.output_tail); #else NOT_IMPLEMENTED(); #endif } void fused_mla_q(FusedMlaQParams& params) { #if defined(USE_MLU) mlu::fused_mla_q(params.q, params.output, params.output_scale, params.output_norm, params.gamma, params.smooth_quant_scale, params.weight_b, params.weight_b_scale, params.weight_c, params.sin, params.cos, params.position_id, params.quant_mode, params.eps, params.interleaved); #else NOT_IMPLEMENTED(); #endif } void fused_mla_kv(FusedMlaKVParams& params) { #if defined(USE_MLU) mlu::fused_mla_kv(params.input_kv, params.sin, params.cos, params.position_id, params.gamma, params.kv_cache, params.kv_cache_scale, params.slot_mapping, params.cache_bs_id, params.cache_seq_offset, params.quant_mode, params.is_paged_cache, params.eps, params.interleaved); #else NOT_IMPLEMENTED(); #endif } void fused_indexer_q(FusedIndexerQParams& params) { #if defined(USE_MLU) mlu::fused_indexer_q(params.input_q, params.output, params.output_scale, params.w_q, params.w_q_scale, params.hadamard_matrix, params.sin, params.cos, params.position_id, params.quant_mode, params.interleaved, params.rope_at_front); #else NOT_IMPLEMENTED(); #endif } void fused_indexer_k(FusedIndexerKParams& params) { #if defined(USE_MLU) mlu::fused_indexer_k(params.x, params.wk, params.wproj, params.sin_table, params.cos_table, params.position_id, params.slot_mapping, params.head_weights, params.k_cache, params.k_cache_scale, params.hadamard_matrix, params.interleaved, params.gamma, params.beta, params.eps); #else NOT_IMPLEMENTED(); #endif } torch::Tensor l2_norm(torch::Tensor& x, double eps) { #if defined(USE_NPU) return npu::npu_l2norm_last_dim(x, eps); #else NOT_IMPLEMENTED(); #endif } std::tuple moe_init_routing_v2(MoeInitRoutingV2Params& params) { #if defined(USE_NPU) return npu::apply_npu_moe_init_routing_v2(params.x, params.expert_idx, params.scale, params.offset, params.active_num, params.expert_capacity, params.expert_num, params.drop_pad_mode, params.expert_tokens_num_type, params.expert_tokens_num_flag, params.quant_mode, params.active_expert_range, params.row_idx_type); #else NOT_IMPLEMENTED(); #endif } std::tuple fp8_scaled_quantize( Fp8ScaledQuantizeParams& params) { #if defined(USE_CUDA) return cuda::fp8_scaled_quantize(params.input, params.output, params.scale); #else NOT_IMPLEMENTED(); #endif } std::pair fused_gdn_gating( FusedGdnGatingParams& params) { #if defined(USE_NPU) return npu::tilelang::fused_gdn_gating(params.A_log, params.a, params.b, params.dt_bias, params.beta, params.threshold); // return npu::npu_fused_gdn_gating(params.A_log, // params.a, // params.b, // params.dt_bias, // params.beta, // params.threshold); #else NOT_IMPLEMENTED(); #endif } std::pair fused_recurrent_gated_delta_rule( FusedRecurrentGatedDeltaRuleParams& params) { #if defined(USE_NPU) return npu::npu_fused_recurrent_gated_delta_rule( params.q, params.k, params.v, params.g, params.beta, params.scale, params.initial_state, params.inplace_final_state, params.cu_seqlens, params.ssm_state_indices, params.num_accepted_tokens, params.use_qk_l2norm_in_kernel); #else NOT_IMPLEMENTED(); #endif } torch::Tensor fp8_scaled_matmul(Fp8ScaledMatmulParams& params) { #if defined(USE_CUDA) auto out_2d = cuda::fp8_scaled_matmul(params.a, params.b, params.a_scale, params.b_scale, params.output_dtype, params.bias, params.output); // Auto reshape output if original input shape is provided if (params.input_shape.has_value()) { auto out_shape = params.input_shape.value(); out_shape.back() = params.b.size(0); return out_2d.view(out_shape); } return out_2d; #else LOG(FATAL) << "fp8_scaled_matmul is only supported on CUDA"; return torch::Tensor(); #endif } void static_scaled_fp8_quant(StaticScaledFp8QuantParams& params) { #if defined(USE_CUDA) cuda::static_scaled_fp8_quant(params.output, params.input, params.scale); #else LOG(FATAL) << "static_scaled_fp8_quant is only supported on CUDA"; #endif } // Fused RMSNorm + Static FP8 Quantization torch::Tensor rms_norm_static_fp8_quant(RmsNormStaticFp8QuantParams& params) { #if defined(USE_CUDA) auto org_shape = params.input.sizes().vec(); auto hidden_size = params.input.size(-1); // Flatten input to 2D. Use reshape to support non-contiguous tensors. auto input_2d = params.input.reshape({-1, hidden_size}); torch::Tensor output = torch::empty({input_2d.size(0), hidden_size}, input_2d.options().dtype(torch::kFloat8_e4m3fn)); // Call fused kernel cuda::rms_norm_static_fp8_quant( output, input_2d, params.weight, params.scale, params.epsilon); return output.reshape(org_shape); #else LOG(FATAL) << "rms_norm_static_fp8_quant is only supported on CUDA"; return torch::Tensor(); #endif } std::tuple fused_add_rms_norm_static_fp8_quant( FusedAddRmsNormStaticFp8QuantParams& params) { #if defined(USE_CUDA) auto org_shape = params.input.sizes().vec(); auto hidden_size = params.input.size(-1); // Flatten tensors to 2D. Use reshape to support non-contiguous tensors. auto input_2d = params.input.reshape({-1, hidden_size}); auto residual_2d = params.residual.reshape({-1, hidden_size}); torch::Tensor output = torch::empty({input_2d.size(0), hidden_size}, input_2d.options().dtype(torch::kFloat8_e4m3fn)); // Call fused kernel (residual is updated in-place) cuda::fused_add_rms_norm_static_fp8_quant(output, input_2d, residual_2d, params.weight, params.scale, params.epsilon); // Reshape outputs auto output_reshaped = output.reshape(org_shape); auto residual_reshaped = residual_2d.reshape(org_shape); return std::make_tuple(output_reshaped, residual_reshaped); #else LOG(FATAL) << "fused_add_rms_norm_static_fp8_quant is only supported on CUDA"; return std::make_tuple(torch::Tensor(), torch::Tensor()); #endif } torch::Tensor causal_conv1d_update(CausalConv1dUpdateParams& params) { #if defined(USE_NPU) if (params.conv_state_indices.has_value()) { CHECK(params.conv_state_indices.value().is_contiguous()) << "causal_conv1d_update: conv_state_indices must be contiguous."; } return npu::npu_causal_conv1d_update_v2(params.x, params.conv_state, params.weight, params.activation, params.bias, params.conv_state_indices, params.query_start_loc, params.max_query_len, params.pad_slot_id, params.block_idx_last_scheduled_token, params.initial_state_idx, params.validate_data); #else NOT_IMPLEMENTED(); #endif } torch::Tensor gated_layer_norm(GatedLayerNormParams& params) { #if defined(USE_NPU) return npu::layer_norm_fwd(params.x, params.weight, params.bias, params.eps, params.z, params.group_size, params.norm_before_gate, params.is_rms_norm); #elif defined(USE_MLU) return mlu::gated_layer_norm(params.x, params.weight, params.bias, params.eps, params.z, params.group_size, params.norm_before_gate); #else NOT_IMPLEMENTED(); #endif } std::pair partial_rotary_embedding( PartialRotaryEmbeddingParams& params) { #if defined(USE_NPU) return npu::apply_npu_partial_rotary_embedding(params.positions, params.query, params.key, params.head_size, params.rotary_dim, params.cos_sin_cache, params.is_neox_style); #else NOT_IMPLEMENTED(); #endif } std::tuple fused_qkvzba_split_reshape_cat(FusedQkvzbaSplitReshapeParams& params) { #if defined(USE_NPU) return npu::npu_fused_qkvzba_split_reshape_cat(params.mixed_qkvz, params.mixed_ba, params.num_heads_qk, params.num_heads_v, params.head_qk, params.head_v); #else NOT_IMPLEMENTED(); #endif } void gemma_rms_norm(GemmaRMSNormParams& params) { #if defined(USE_NPU) npu::npu_gemma_rms_norm( params.x, params.gamma, params.epsilon, params.rstd_out, params.norm_out); #elif defined(USE_MLU) mlu::gemma_rms_norm(params.x, params.gamma, params.epsilon, params.norm_out); #else NOT_IMPLEMENTED(); #endif } std::tuple split_qkv_rmsnorm_mrope(SplitQkvRmsnormMropeParams& params) { #if defined(USE_NPU) return npu::tilelang::split_qkv_rmsnorm_mrope(params.qkvg, params.q_weight, params.k_weight, params.cos_sin, params.gather_pattern, params.eps, params.num_q_heads, params.num_kv_heads, params.head_size); #else NOT_IMPLEMENTED(); #endif } bool has_split_qkv_rmsnorm_mrope_specialization(int64_t num_q_heads, int64_t num_kv_heads, int64_t head_size) { #if defined(USE_NPU) return npu::tilelang::has_split_qkv_rmsnorm_mrope_specialization( num_q_heads, num_kv_heads, head_size); #else return false; #endif } torch::Tensor build_split_qkv_rmsnorm_mrope_gather_pattern( int64_t rope_dim, const std::vector& mrope_section, bool is_interleaved, const torch::Device& device) { #if defined(USE_NPU) return npu::tilelang::build_split_qkv_rmsnorm_mrope_gather_pattern( rope_dim, mrope_section, is_interleaved, device); #else NOT_IMPLEMENTED(); #endif } std::pair chunk_gated_delta_rule( ChunkGatedDeltaRuleParams& params) { #if defined(USE_NPU) return npu::npu_chunk_gated_delta_rule(params.q, params.k, params.v, params.g, params.beta, params.scale, params.initial_state, params.output_final_state, params.cu_seqlens, params.head_first, params.use_qk_l2norm_in_kernel); #else NOT_IMPLEMENTED(); #endif } torch::Tensor recurrent_gated_delta_rule( const torch::Tensor& query, const torch::Tensor& key, const torch::Tensor& value, torch::Tensor& state, const std::optional& beta, const std::optional scale, const std::optional& actual_seq_lengths, const std::optional& ssm_state_indices, const std::optional& num_accepted_tokens, const std::optional& g, const std::optional& gk) { #if defined(USE_NPU) return npu::npu_recurrent_gated_delta_rule(query, key, value, state, beta, scale, actual_seq_lengths, ssm_state_indices, num_accepted_tokens, g, gk); #else NOT_IMPLEMENTED(); #endif } } // namespace xllm::kernel