char-fork/llama.cpp
git clone https://git.t4t.associates/char-fork/llama.cpp
0190529ec
char/aliceai-t5-moe
1/* 2* Copyright (c) 2023-2026 The ggml authors 3* 4* Permission is hereby granted, free of charge, to any person obtaining a copy 5* of this software and associated documentation files (the "Software"), to 6* deal in the Software without restriction, including without limitation the 7* rights to use, copy, modify, merge, publish, distribute, sublicense, and/or 8* sell copies of the Software, and to permit persons to whom the Software is 9* furnished to do so, subject to the following conditions: 10* 11* The above copyright notice and this permission notice shall be included in 12* all copies or substantial portions of the Software. 13* 14* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 17* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 19* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS 20* IN THE SOFTWARE. 21*/ 22 23#include "aclnn_ops.h" 24 25#include "ggml-impl.h" 26#include "ggml.h" 27 28 29#include <aclnnop/aclnn_add.h> 30#include <aclnnop/aclnn_add_rms_norm.h> 31#include <aclnnop/aclnn_addcdiv.h> 32#include <aclnnop/aclnn_argmax.h> 33#include <aclnnop/aclnn_avgpool2d.h> 34#include <aclnnop/aclnn_batch_matmul.h> 35#include <aclnnop/aclnn_cast.h> 36#include <aclnnop/aclnn_clamp.h> 37#include <aclnnop/aclnn_constant_pad_nd.h> 38#include <aclnnop/aclnn_convolution.h> 39#include <aclnnop/aclnn_copy.h> 40#include <aclnnop/aclnn_div.h> 41#include <aclnnop/aclnn_elu.h> 42#include <aclnnop/aclnn_embedding.h> 43#include <aclnnop/aclnn_eq_tensor.h> 44#include <aclnnop/aclnn_exp.h> 45#include <aclnnop/aclnn_fill_scalar.h> 46#include <aclnnop/aclnn_fused_infer_attention_score_v2.h> 47#include <aclnnop/aclnn_ger.h> 48#include <aclnnop/aclnn_group_norm.h> 49#include <aclnnop/aclnn_gather_v2.h> 50#include <aclnnop/aclnn_grouped_matmul_v3.h> 51#include <aclnnop/aclnn_scatter.h> 52#include <aclnnop/aclnn_gt_scalar.h> 53#include <aclnnop/aclnn_im2col.h> 54#include <aclnnop/aclnn_index_copy.h> 55#include <aclnnop/aclnn_index_fill_tensor.h> 56#include <aclnnop/aclnn_index_select.h> 57#include <aclnnop/aclnn_layer_norm.h> 58#include <aclnnop/aclnn_log.h> 59#include <aclnnop/aclnn_matmul.h> 60#include <aclnnop/aclnn_max_pool.h> 61#include <aclnnop/aclnn_mean.h> 62#include <aclnnop/aclnn_mm.h> 63#include <aclnnop/aclnn_mul.h> 64#include <aclnnop/aclnn_mv.h> 65#include <aclnnop/aclnn_permute.h> 66#include <aclnnop/aclnn_pow.h> 67#include <aclnnop/aclnn_pow_tensor_tensor.h> 68#include <aclnnop/aclnn_recurrent_gated_delta_rule.h> 69#include <aclnnop/aclnn_reduce_sum.h> 70#include <aclnnop/aclnn_reflection_pad1d.h> 71#include <aclnnop/aclnn_repeat.h> 72#include <aclnnop/aclnn_repeat_interleave.h> 73#include <aclnnop/aclnn_rms_norm.h> 74#include <aclnnop/aclnn_roll.h> 75#include <aclnnop/aclnn_softmax.h> 76#include <aclnnop/aclnn_softmax_cross_entropy_with_logits.h> 77#include <aclnnop/aclnn_sub.h> 78#include <aclnnop/aclnn_sum.h> 79#include <aclnnop/aclnn_threshold.h> 80#include <aclnnop/aclnn_tril.h> 81#include <aclnnop/aclnn_triangular_solve.h> 82#include <aclnnop/aclnn_triu.h> 83#include <aclnnop/aclnn_logical_not.h> 84#include <aclnnop/aclnn_masked_fill_scalar.h> 85#include <aclnnop/aclnn_upsample_nearest_2d.h> 86#include <aclnnop/aclnn_weight_quant_batch_matmul_v2.h> 87#include <aclnnop/aclnn_zero.h> 88#include <float.h> 89 90#include <cmath> 91#include <cstring> 92#include <exception> 93#include <vector> 94 95#define GGML_COMMON_DECL_C 96 97#include "../ggml-common.h" 98 99void bcast_shape (ggml_tensor * src0 , 100ggml_tensor * src1 , 101ggml_tensor * dst , 102acl_tensor_ptr & acl_src0 , 103acl_tensor_ptr & acl_src1 , 104acl_tensor_ptr & acl_dst ) { 105GGML_ASSERT (ggml_are_same_shape (src0 ,dst )&& ggml_can_repeat (src1 ,src0 )); 106// Need bcast 107if (!ggml_are_same_shape (src0 ,src1 )&& ggml_cann_need_bcast (src0 ,src1 )) { 108BCAST_SHAPE (src0 ,src1 ) 109acl_src0 = ggml_cann_create_tensor (src0 ,BCAST_PARAM (src0 )); 110acl_src1 = ggml_cann_create_tensor (src1 ,BCAST_PARAM (src1 )); 111acl_dst = ggml_cann_create_tensor (dst ,BCAST_PARAM (src0 )); 112 }else { 113acl_src0 = ggml_cann_create_tensor (src0 ); 114acl_src1 = ggml_cann_create_tensor (src1 ); 115acl_dst = ggml_cann_create_tensor (dst ); 116 } 117} 118 119void ggml_cann_op_unary (std::function < void (ggml_backend_cann_context & ,aclTensor * ,aclTensor * )> unary_op , 120ggml_backend_cann_context & ctx , 121ggml_tensor * dst ) { 122ggml_tensor * src = dst -> src [0 ]; 123 124acl_tensor_ptr acl_src = ggml_cann_create_tensor (src ); 125acl_tensor_ptr acl_dst = ggml_cann_create_tensor (dst ); 126 127unary_op (ctx ,acl_src .get (),acl_dst .get ()); 128} 129 130void ggml_cann_op_unary_gated (std::function < void (ggml_backend_cann_context & ,aclTensor * ,aclTensor * )> unary_op , 131ggml_backend_cann_context & ctx , 132ggml_tensor * dst ) { 133ggml_tensor * src0 = dst -> src [0 ]; 134ggml_tensor * src1 = dst -> src [1 ]; 135 136GGML_ASSERT (ggml_is_contiguous_1 (src0 )); 137GGML_ASSERT (ggml_is_contiguous_1 (dst )); 138const int32_t swapped = ggml_get_op_params_i32 (dst ,1 ); 139 140acl_tensor_ptr acl_dst = ggml_cann_create_tensor (dst ); 141acl_tensor_ptr acl_src0 ,acl_src1 ; 142if (src1 ) { 143GGML_ASSERT (ggml_is_contiguous_1 (src1 )); 144GGML_ASSERT (src0 -> type == src1 -> type ); 145 146acl_src0 = ggml_cann_create_tensor (src0 ); 147acl_src1 = ggml_cann_create_tensor (src1 ); 148 }else { 149int64_t ne []= {src0 -> ne [0 ] /2 ,src0 -> ne [1 ],src0 -> ne [2 ],src0 -> ne [3 ] }; 150size_t nb []= {src0 -> nb [0 ],src0 -> nb [1 ],src0 -> nb [2 ],src0 -> nb [3 ] }; 151acl_src0 = ggml_cann_create_tensor (src0 ,ne ,nb ,GGML_MAX_DIMS ,ACL_FORMAT_ND ,0 ); 152acl_src1 = ggml_cann_create_tensor (src0 ,ne ,nb ,GGML_MAX_DIMS ,ACL_FORMAT_ND ,ne [0 ]* ggml_element_size (src0 )); 153if (swapped ) { 154 std::swap (acl_src0 ,acl_src1 ); 155 } 156 } 157 158unary_op (ctx ,acl_src0 .get (),acl_dst .get ()); 159GGML_CANN_CALL_ACLNN_OP (ctx ,InplaceMul ,acl_dst .get (),acl_src1 .get ()); 160} 161 162// Fused SwiGLU using aclnnSwiGlu: splits input along innermost dim, applies 163// SiLU to left half, multiplies by right half. 164// 165// Falls back to the generic two-kernel path when src[1] != nullptr (two 166// independent halves) or swapped != 0 (reversed activation order), as 167// aclnnSwiGlu only handles the single interleaved tensor in standard order. 168// 169// CANN tiling for SwiGlu requires (storageShapeDim + viewDims) to be even. 170// aclCreateTensor always uses storageShapeDim=1, so viewDims must be odd. 171// We use a 3D view (1+3=4, even) to satisfy this constraint while preserving 172// correct split semantics along the innermost (ne[0]) dimension. 173void ggml_cann_swiglu (ggml_backend_cann_context & ctx ,ggml_tensor * dst ) { 174auto silu_fn = [](ggml_backend_cann_context & ctx ,aclTensor * acl_src ,aclTensor * acl_dst ) { 175GGML_CANN_CALL_ACLNN_OP (ctx ,Silu ,acl_src ,acl_dst ); 176 }; 177 178const int32_t swapped = ggml_get_op_params_i32 (dst ,1 ); 179if (dst -> src [1 ]!= nullptr || swapped != 0 ) { 180ggml_cann_op_unary_gated (silu_fn ,ctx ,dst ); 181return ; 182 } 183 184// aclnnSwiGlu requires the split dim (src->ne[0]) to be even; fall back otherwise. 185if (dst -> src [0 ]-> ne [0 ] %2 != 0 ) { 186ggml_cann_op_unary_gated (silu_fn ,ctx ,dst ); 187return ; 188 } 189 190ggml_tensor * src0 = dst -> src [0 ]; 191size_t elem_size = ggml_element_size (src0 ); 192 193// src0 GGML: [2*ne0, ne1, ne2, ne3] → 3D view [2*ne0, ne1, ne2*ne3] 194// CANN reversed: [ne2*ne3, ne1, 2*ne0], split along CANN dim 2 (last). 195int64_t ne0_x2 = src0 -> ne [0 ]; 196int64_t ne1 = src0 -> ne [1 ]; 197int64_t ne23 = src0 -> ne [2 ]* src0 -> ne [3 ]; 198int64_t src3d_ne []= {ne0_x2 ,ne1 ,ne23 }; 199size_t src3d_nb []= { (size_t )src0 -> nb [0 ], (size_t )src0 -> nb [1 ], (size_t )src0 -> nb [2 ] }; 200acl_tensor_ptr acl_src = ggml_cann_create_tensor (src0 -> data ,ggml_cann_type_mapping (src0 -> type ), 201elem_size ,src3d_ne ,src3d_nb ,3 ); 202 203// dst GGML: [ne0, ne1, ne2, ne3] → 3D view [ne0, ne1, ne2*ne3] 204int64_t ne0 = dst -> ne [0 ]; 205int64_t dst3d_ne []= {ne0 ,ne1 ,ne23 }; 206size_t dst3d_nb []= { (size_t )dst -> nb [0 ], (size_t )dst -> nb [1 ], (size_t )dst -> nb [2 ] }; 207acl_tensor_ptr acl_dst = ggml_cann_create_tensor (dst -> data ,ggml_cann_type_mapping (dst -> type ), 208elem_size ,dst3d_ne ,dst3d_nb ,3 ); 209 210// CANN tensor [ne23, ne1, 2*ne0]: split along CANN dim 2 (last) = 2*ne0. 211GGML_CANN_CALL_ACLNN_OP (ctx ,SwiGlu ,acl_src .get (), (int64_t )2 ,acl_dst .get ()); 212} 213 214void ggml_cann_swiglu_clamp (ggml_backend_cann_context & ctx ,ggml_tensor * dst ) { 215ggml_tensor * src0 = dst -> src [0 ]; 216ggml_tensor * src1 = dst -> src [1 ]; 217 218GGML_ASSERT (ggml_is_contiguous_1 (src0 )); 219GGML_ASSERT (ggml_is_contiguous_1 (dst )); 220 221const int32_t swapped = ggml_get_op_params_i32 (dst ,1 ); 222acl_tensor_ptr acl_gate ; 223acl_tensor_ptr acl_up ; 224if (src1 ) { 225GGML_ASSERT (ggml_is_contiguous_1 (src1 )); 226GGML_ASSERT (src0 -> type == src1 -> type ); 227acl_gate = ggml_cann_create_tensor (src0 ); 228acl_up = ggml_cann_create_tensor (src1 ); 229 }else { 230int64_t ne []= {src0 -> ne [0 ] /2 ,src0 -> ne [1 ],src0 -> ne [2 ],src0 -> ne [3 ] }; 231size_t nb []= {src0 -> nb [0 ],src0 -> nb [1 ],src0 -> nb [2 ],src0 -> nb [3 ] }; 232acl_gate = ggml_cann_create_tensor (src0 ,ne ,nb ,GGML_MAX_DIMS ,ACL_FORMAT_ND ,0 ); 233acl_up = ggml_cann_create_tensor (src0 ,ne ,nb ,GGML_MAX_DIMS ,ACL_FORMAT_ND ,ne [0 ]* ggml_element_size (src0 )); 234if (swapped ) { 235 std::swap (acl_gate ,acl_up ); 236 } 237 } 238 239ggml_cann_pool_alloc temp_alloc (ctx .pool (),ggml_nbytes (dst )); 240acl_tensor_ptr acl_temp = ggml_cann_create_tensor (temp_alloc .get (),ggml_cann_type_mapping (dst -> type ), 241ggml_element_size (dst ),dst -> ne ,dst -> nb ,GGML_MAX_DIMS ); 242acl_tensor_ptr acl_dst = ggml_cann_create_tensor (dst ); 243 244const float limit = ggml_get_op_params_f32 (dst ,3 ); 245float min_gate = - INFINITY ; 246float min_up = - limit ; 247float max_value = limit ; 248acl_scalar_ptr acl_min_gate = ggml_cann_create_scalar (& min_gate ,ACL_FLOAT ); 249acl_scalar_ptr acl_min_up = ggml_cann_create_scalar (& min_up ,ACL_FLOAT ); 250acl_scalar_ptr acl_limit = ggml_cann_create_scalar (& max_value ,ACL_FLOAT ); 251 252GGML_CANN_CALL_ACLNN_OP (ctx ,Clamp ,acl_gate .get (),acl_min_gate .get (),acl_limit .get (),acl_temp .get ()); 253GGML_CANN_CALL_ACLNN_OP (ctx ,Silu ,acl_temp .get (),acl_dst .get ()); 254GGML_CANN_CALL_ACLNN_OP (ctx ,Clamp ,acl_up .get (),acl_min_up .get (),acl_limit .get (),acl_temp .get ()); 255GGML_CANN_CALL_ACLNN_OP (ctx ,InplaceMul ,acl_dst .get (),acl_temp .get ()); 256} 257 258// Fused GeGLU using aclnnGeGluV3: splits input along ne[0] (CANN last dim), 259// activates the LEFT half with GELU, multiplies by right half. 260// approximate: 0=tanh, 1=none(erf). activateLeft=true matches GGML convention. 261// outGelu is a required-but-discard output buffer. 262// 263// Falls back to the generic two-kernel path when src[1] != nullptr (two 264// independent halves) or swapped != 0 (reversed activation order), as 265// aclnnGeGluV3 only handles the single interleaved tensor in standard order. 266void ggml_cann_geglu (ggml_backend_cann_context & ctx ,ggml_tensor * dst ,int64_t approximate ) { 267auto gelu_fn = [](ggml_backend_cann_context & ctx ,aclTensor * acl_src ,aclTensor * acl_dst ) { 268GGML_CANN_CALL_ACLNN_OP (ctx ,Gelu ,acl_src ,acl_dst ); 269 }; 270 271const int32_t swapped = ggml_get_op_params_i32 (dst ,1 ); 272if (dst -> src [1 ]!= nullptr || swapped != 0 ) { 273ggml_cann_op_unary_gated (gelu_fn ,ctx ,dst ); 274return ; 275 } 276 277// aclnnGeGluV3 requires the split dim (src->ne[0]) to be even; fall back otherwise. 278if (dst -> src [0 ]-> ne [0 ] %2 != 0 ) { 279ggml_cann_op_unary_gated (gelu_fn ,ctx ,dst ); 280return ; 281 } 282 283ggml_tensor * src0 = dst -> src [0 ]; 284acl_tensor_ptr acl_src = ggml_cann_create_tensor (src0 ); 285acl_tensor_ptr acl_dst = ggml_cann_create_tensor (dst ); 286 287// Allocate a temporary buffer for the required outGelu output (same shape as dst). 288// Build contiguous strides since the pool allocation is a fresh buffer. 289size_t elem_size = ggml_element_size (dst ); 290int64_t ne [GGML_MAX_DIMS ]= {dst -> ne [0 ],dst -> ne [1 ],dst -> ne [2 ],dst -> ne [3 ] }; 291size_t nb [GGML_MAX_DIMS ]; 292nb [0 ]= elem_size ; 293for (int i = 1 ;i < GGML_MAX_DIMS ;i ++ ) { 294nb [i ]= nb [i - 1 ]* ne [i - 1 ]; 295 } 296size_t gelu_out_size = nb [GGML_MAX_DIMS - 1 ]* ne [GGML_MAX_DIMS - 1 ]; 297ggml_cann_pool_alloc gelu_out_alloc (ctx .pool (),gelu_out_size ); 298 299acl_tensor_ptr acl_gelu_out = ggml_cann_create_tensor ( 300gelu_out_alloc .get (),ggml_cann_type_mapping (dst -> type ),elem_size ,ne ,nb ,GGML_MAX_DIMS ); 301// V3 adds activateLeft param; true → Gelu(left)*right, matching GGML convention. 302// GGML dim 0 → CANN last dim (index GGML_MAX_DIMS-1 = 3 for 4D tensor). 303GGML_CANN_CALL_ACLNN_OP (ctx ,GeGluV3 ,acl_src .get (), (int64_t )(GGML_MAX_DIMS - 1 ),approximate , true, 304acl_dst .get (),acl_gelu_out .get ()); 305} 306 307/** 308* @brief Repeats elements of a tensor along each dimension according to the 309* specified repeat array. 310* 311* @param ctx The context for the CANN backend operations. 312* @param acl_src The source tensor to be repeated. 313* @param acl_dst The destination tensor after repeating. 314* @param repeat_array The array specifying the number of repetitions along each 315* dimension. 316*/ 317static void aclnn_repeat (ggml_backend_cann_context & ctx , 318aclTensor * acl_src , 319aclTensor * acl_dst , 320int64_t * repeat_array ) { 321// repeat tensor along each dim with repeat_array 322acl_int_array_ptr repeats = ggml_cann_create_int_array (repeat_array ,GGML_MAX_DIMS ); 323 324GGML_CANN_CALL_ACLNN_OP (ctx ,Repeat ,acl_src ,repeats .get (),acl_dst ); 325} 326 327/** 328* @brief Casts the data type of a source tensor to a destination tensor. 329* 330* This function casts the data type of the source tensor `acl_src` to the 331* specified data type `cast_data_type` and stores the result in the destination 332* tensor `acl_dst`. 333* 334* @param ctx The context for the CANN backend operations. 335* @param acl_src The source tensor whose data type will be casted. 336* @param acl_dst The destination tensor where the casted result will be stored. 337* @param cast_data_type The target data type to which the source tensor will be 338* casted. 339*/ 340static void aclnn_cast (ggml_backend_cann_context & ctx , 341aclTensor * acl_src , 342aclTensor * acl_dst , 343aclDataType cast_data_type ) { 344GGML_CANN_CALL_ACLNN_OP (ctx ,Cast ,acl_src ,cast_data_type ,acl_dst ); 345} 346 347void ggml_cann_repeat (ggml_backend_cann_context & ctx ,ggml_tensor * dst ) { 348ggml_tensor * src = dst -> src [0 ]; 349GGML_ASSERT (ggml_can_repeat (src ,dst )); 350 351acl_tensor_ptr acl_src = ggml_cann_create_tensor (src ); 352acl_tensor_ptr acl_dst = ggml_cann_create_tensor (dst ); 353 354int64_t repeatsArray []= {dst -> ne [3 ] /src -> ne [3 ],dst -> ne [2 ] /src -> ne [2 ],dst -> ne [1 ] /src -> ne [1 ], 355dst -> ne [0 ] /src -> ne [0 ] }; 356 357aclnn_repeat (ctx ,acl_src .get (),acl_dst .get (),repeatsArray ); 358} 359 360void aclnn_add (ggml_backend_cann_context & ctx ,aclTensor * acl_src0 ,aclTensor * acl_src1 ,aclTensor * acl_dst ) { 361float alphaValue = 1.0f ; 362acl_scalar_ptr alpha = ggml_cann_create_scalar (& alphaValue , aclDataType::ACL_FLOAT ); 363if (acl_dst != nullptr ) { 364GGML_CANN_CALL_ACLNN_OP (ctx ,Add ,acl_src0 ,acl_src1 ,alpha .get (),acl_dst ); 365 }else { 366GGML_CANN_CALL_ACLNN_OP (ctx ,InplaceAdd ,acl_src0 ,acl_src1 ,alpha .get ()); 367 } 368} 369 370void aclnn_sub (ggml_backend_cann_context & ctx ,aclTensor * acl_src0 ,aclTensor * acl_src1 ,aclTensor * acl_dst ) { 371float alphaValue = 1.0f ; 372acl_scalar_ptr alpha = ggml_cann_create_scalar (& alphaValue , aclDataType::ACL_FLOAT ); 373if (acl_dst != nullptr ) { 374GGML_CANN_CALL_ACLNN_OP (ctx ,Sub ,acl_src0 ,acl_src1 ,alpha .get (),acl_dst ); 375 }else { 376GGML_CANN_CALL_ACLNN_OP (ctx ,InplaceSub ,acl_src0 ,acl_src1 ,alpha .get ()); 377 } 378} 379 380void aclnn_mul (ggml_backend_cann_context & ctx ,aclTensor * acl_src ,aclTensor * acl_other ,aclTensor * acl_dst ) { 381if (acl_dst != nullptr ) { 382GGML_CANN_CALL_ACLNN_OP (ctx ,Mul ,acl_src ,acl_other ,acl_dst ); 383 }else { 384GGML_CANN_CALL_ACLNN_OP (ctx ,InplaceMul ,acl_src ,acl_other ); 385 } 386} 387 388void aclnn_div (ggml_backend_cann_context & ctx ,aclTensor * acl_src ,aclTensor * acl_other ,aclTensor * acl_dst ) { 389if (acl_dst != nullptr ) { 390GGML_CANN_CALL_ACLNN_OP (ctx ,Div ,acl_src ,acl_other ,acl_dst ); 391 }else { 392GGML_CANN_CALL_ACLNN_OP (ctx ,InplaceDiv ,acl_src ,acl_other ); 393 } 394} 395 396/** 397* @brief Multiplies elements of a tensor by a scalar value, optionally 398* in-place. 399* 400* This function multiplies each element of the source tensor `acl_src` by the 401* scalar `scale` and stores the result in the destination tensor `acl_dst`. If 402* `inplace` is true, `acl_dst` will not be used and the operation is performed 403* in-place on `acl_src`. 404* The operation is defined as: 405* \f[ 406* \text {acl_dst }_i=\text {acl_src }_i \times \text {scale} 407* \f] 408* 409* @param ctx The context for the CANN backend operations. 410* @param acl_src The source tensor whose elements will be multiplied. 411* @param scale The scalar value by which each element of `acl_src` will be 412* multiplied. 413* @param acl_dst The destination tensor where the result will be stored if 414* `inplace` is false. 415* @param inplace Flag indicating whether to perform the operation in-place on 416* `acl_src`. 417*/ 418static void aclnn_muls (ggml_backend_cann_context & ctx , 419aclTensor * acl_src , 420float scale , 421aclTensor * acl_dst , 422bool inplace ) { 423acl_scalar_ptr acl_scale = ggml_cann_create_scalar (& scale , aclDataType::ACL_FLOAT ); 424if (inplace ) { 425GGML_CANN_CALL_ACLNN_OP (ctx ,InplaceMuls ,acl_src ,acl_scale .get ()); 426 }else { 427GGML_CANN_CALL_ACLNN_OP (ctx ,Muls ,acl_src ,acl_scale .get (),acl_dst ); 428 } 429} 430 431void ggml_cann_leaky_relu (ggml_backend_cann_context & ctx ,ggml_tensor * dst ) { 432ggml_tensor * src = dst -> src [0 ]; 433 434acl_tensor_ptr acl_src = ggml_cann_create_tensor (src ); 435acl_tensor_ptr acl_dst = ggml_cann_create_tensor (dst ); 436 437float negative_slope ; 438memcpy (& negative_slope ,dst -> op_params ,sizeof (float )); 439acl_scalar_ptr acl_negative_slope = ggml_cann_create_scalar (& negative_slope , aclDataType::ACL_FLOAT ); 440 441GGML_CANN_CALL_ACLNN_OP (ctx ,LeakyRelu ,acl_src .get (),acl_negative_slope .get (),acl_dst .get ()); 442} 443 444/** 445* @brief Concatenates a list of tensors along a specified dimension and stores 446* the result in a destination tensor. 447* 448* @param ctx The context for the CANN backend operations. 449* @param tensorList The list of tensors to be concatenated. 450* @param acl_dst The destination tensor where the concatenated result will be 451* stored. 452* @param concat_dim The dimension along which the tensors will be concatenated. 453*/ 454static void aclnn_concat (ggml_backend_cann_context & ctx , 455aclTensorList * tensorList , 456aclTensor * acl_dst , 457int64_t concat_dim ) { 458GGML_CANN_CALL_ACLNN_OP (ctx ,Cat ,tensorList ,concat_dim ,acl_dst ); 459} 460 461void ggml_cann_concat (ggml_backend_cann_context & ctx ,ggml_tensor * dst ) { 462ggml_tensor * src0 = dst -> src [0 ]; 463ggml_tensor * src1 = dst -> src [1 ]; 464acl_tensor_ptr acl_src0 = ggml_cann_create_tensor (src0 ); 465acl_tensor_ptr acl_src1 = ggml_cann_create_tensor (src1 ); 466acl_tensor_ptr acl_dst = ggml_cann_create_tensor (dst ); 467 468const int32_t dim = ggml_get_op_params_i32 (dst ,0 ); 469 470GGML_ASSERT (dim >=0 && dim < 4 ); 471int32_t acl_dim = 3 - dim ; 472 473acl_tensor_list_ptr tensor_list = ggml_cann_create_tensor_list (acl_src0 ,acl_src1 ); 474aclnn_concat (ctx ,tensor_list .get (),acl_dst .get (),acl_dim ); 475} 476 477/** 478* @brief Creates a tensor with values starting from `start`, incremented by 479* `step`, and ending before `stop`. 480* 481* This function performs the operation: 482* \f[ 483* \text {out }_{i+1}=\text {out }_i+\text {step} 484* \f] 485* the range is [start, stop). 486* 487* @param ctx The context for the CANN backend operations. 488* @param acl_dst The destination tensor where the values will be stored. 489* @param start The starting value of the range. 490* @param stop The ending value of the range (exclusive). 491* @param step The step size between consecutive values. 492* @param n_elements The number of elements in the destination tensor. 493*/ 494static void aclnn_arange (ggml_backend_cann_context & ctx , 495aclTensor * acl_dst , 496float start , 497float stop , 498float step , 499int64_t n_elements ) { 500int64_t steps = (int64_t ) std::ceil ((stop - start ) /step ); 501GGML_ASSERT (n_elements == steps ); 502 503acl_scalar_ptr acl_start = ggml_cann_create_scalar (& start , aclDataType::ACL_FLOAT ); 504acl_scalar_ptr acl_end = ggml_cann_create_scalar (& stop , aclDataType::ACL_FLOAT ); 505acl_scalar_ptr acl_step = ggml_cann_create_scalar (& step , aclDataType::ACL_FLOAT ); 506 507GGML_CANN_CALL_ACLNN_OP (ctx ,Arange ,acl_start .get (),acl_end .get (),acl_step .get (),acl_dst ); 508} 509 510void ggml_cann_arange (ggml_backend_cann_context & ctx ,ggml_tensor * dst ) { 511GGML_ASSERT (dst -> type == GGML_TYPE_F32 ); 512 513acl_tensor_ptr acl_dst = ggml_cann_create_tensor (dst ); 514 515int64_t n_elements = ggml_nelements (dst ); 516float start ; 517float stop ; 518float step ; 519memcpy (& start , (float * )dst -> op_params + 0 ,sizeof (float )); 520memcpy (& stop , (float * )dst -> op_params + 1 ,sizeof (float )); 521memcpy (& step , (float * )dst -> op_params + 2 ,sizeof (float )); 522 523aclnn_arange (ctx ,acl_dst .get (),start ,stop ,step ,n_elements ); 524} 525 526void ggml_cann_clamp (ggml_backend_cann_context & ctx ,ggml_tensor * dst ) { 527ggml_tensor * src = dst -> src [0 ]; 528 529float min ; 530float max ; 531memcpy (& min ,dst -> op_params ,sizeof (float )); 532memcpy (& max , (float * )dst -> op_params + 1 ,sizeof (float )); 533 534acl_tensor_ptr acl_src = ggml_cann_create_tensor (src ); 535acl_tensor_ptr acl_dst = ggml_cann_create_tensor (dst ); 536 537acl_scalar_ptr acl_min = ggml_cann_create_scalar (& min , aclDataType::ACL_FLOAT ); 538acl_scalar_ptr acl_max = ggml_cann_create_scalar (& max , aclDataType::ACL_FLOAT ); 539 540GGML_CANN_CALL_ACLNN_OP (ctx ,Clamp ,acl_src .get (),acl_min .get (),acl_max .get (),acl_dst .get ()); 541} 542 543void ggml_cann_scale (ggml_backend_cann_context & ctx ,ggml_tensor * dst ) { 544ggml_tensor * src = dst -> src [0 ]; 545 546// scale factor 547float v ; 548memcpy (& v ,dst -> op_params ,sizeof (float )); 549 550acl_scalar_ptr scale = ggml_cann_create_scalar (& v , aclDataType::ACL_FLOAT ); 551acl_tensor_ptr acl_src = ggml_cann_create_tensor (src ); 552acl_tensor_ptr acl_dst = ggml_cann_create_tensor (dst ); 553 554GGML_CANN_CALL_ACLNN_OP (ctx ,Muls ,acl_src .get (),scale .get (),acl_dst .get ()); 555} 556 557void ggml_cann_argsort (ggml_backend_cann_context & ctx ,ggml_tensor * dst ) { 558ggml_tensor * src = dst -> src [0 ]; 559enum ggml_sort_order order = (enum ggml_sort_order )dst -> op_params [0 ]; 560 561acl_tensor_ptr acl_src = ggml_cann_create_tensor (src ); 562acl_tensor_ptr acl_dst = ggml_cann_create_tensor (dst ); 563ggml_cann_pool_alloc temp_buffer_allocator (ctx .pool (),ggml_nelements (dst )* sizeof (int64_t )); 564void * buffer = temp_buffer_allocator .get (); 565acl_tensor_ptr tmp_tensor = 566ggml_cann_create_tensor (buffer ,ACL_INT64 ,ggml_type_size (dst -> type ),dst -> ne ,dst -> nb ,GGML_MAX_DIMS ); 567GGML_CANN_CALL_ACLNN_OP (ctx ,Argsort ,acl_src .get (),-1 , (order == GGML_SORT_ORDER_DESC ? true : false), 568tmp_tensor .get ()); 569GGML_CANN_CALL_ACLNN_OP (ctx ,Cast ,tmp_tensor .get (),ggml_cann_type_mapping (dst -> type ),acl_dst .get ()); 570} 571 572void ggml_cann_norm (ggml_backend_cann_context & ctx ,ggml_tensor * dst ) { 573ggml_tensor * src = dst -> src [0 ]; 574 575acl_tensor_ptr acl_src = ggml_cann_create_tensor (src ); 576acl_tensor_ptr acl_dst = ggml_cann_create_tensor (dst ); 577 578float eps ; 579memcpy (& eps ,dst -> op_params ,sizeof (float )); 580 581 std::vector < int64_t > normData = {dst -> ne [0 ] }; 582acl_int_array_ptr norm = ggml_cann_create_int_array (normData .data (),normData .size ()); 583GGML_CANN_CALL_ACLNN_OP (ctx ,LayerNorm ,acl_src .get (),norm .get (),nullptr ,nullptr ,eps ,acl_dst .get (),nullptr , 584nullptr ); 585} 586 587void ggml_cann_l2_norm (ggml_backend_cann_context & ctx ,ggml_tensor * dst ) { 588ggml_tensor * src = dst -> src [0 ]; 589 590float eps ; 591memcpy (& eps ,dst -> op_params ,sizeof (float )); 592 593acl_tensor_ptr acl_src = ggml_cann_create_tensor (src ); 594acl_tensor_ptr acl_dst = ggml_cann_create_tensor (dst ); 595 596size_t type_size = ggml_type_size (src -> type ); 597int64_t n_bytes = src -> ne [3 ]* src -> ne [2 ]* src -> ne [1 ]* type_size ; 598ggml_cann_pool_alloc temp_buffer_allocator (ctx .pool (),n_bytes ); 599void * buffer = temp_buffer_allocator .get (); 600 601int64_t norm_ne []= {1 ,src -> ne [1 ],src -> ne [2 ],src -> ne [3 ] }; 602size_t norm_nb [GGML_MAX_DIMS ]; 603norm_nb [0 ]= sizeof (float ); 604for (int i = 1 ;i < GGML_MAX_DIMS ;++ i ) { 605norm_nb [i ]= norm_nb [i - 1 ]* norm_ne [i - 1 ]; 606 } 607acl_tensor_ptr acl_norm = ggml_cann_create_tensor (buffer ,ACL_FLOAT ,sizeof (float ),norm_ne ,norm_nb ,GGML_MAX_DIMS ); 608 609 std::vector < int64_t > norm_dims = {3 }; 610acl_int_array_ptr dims_array = ggml_cann_create_int_array (norm_dims .data (),norm_dims .size ()); 611 612float p_value = 2.0f ; 613acl_scalar_ptr p_scalar = ggml_cann_create_scalar (& p_value , aclDataType::ACL_FLOAT ); 614GGML_CANN_CALL_ACLNN_OP (ctx ,Norm ,acl_src .get (),p_scalar .get (),dims_array .get (), true,acl_norm .get ()); 615 616ggml_cann_pool_alloc clamp_buffer_allocator (ctx .pool ()); 617acl_tensor_ptr acl_clamped ; 618 619if (eps > 0.0f ) { 620void * clamp_buf = clamp_buffer_allocator .alloc (n_bytes ); 621acl_clamped = ggml_cann_create_tensor (clamp_buf ,ACL_FLOAT ,sizeof (float ),norm_ne ,norm_nb ,GGML_MAX_DIMS ); 622acl_scalar_ptr eps_scalar = ggml_cann_create_scalar (& eps , aclDataType::ACL_FLOAT ); 623GGML_CANN_CALL_ACLNN_OP (ctx ,ClampMin ,acl_norm .get (),eps_scalar .get (),acl_clamped .get ()); 624 } 625 626aclTensor * acl_div_input = acl_clamped ?acl_clamped .get () :acl_norm .get (); 627GGML_CANN_CALL_ACLNN_OP (ctx ,Div ,acl_src .get (),acl_div_input ,acl_dst .get ()); 628} 629 630void ggml_cann_cross_entropy_loss (ggml_backend_cann_context & ctx ,ggml_tensor * dst ) { 631ggml_tensor * src0 = dst -> src [0 ]; 632ggml_tensor * src1 = dst -> src [1 ]; 633 634const int64_t nc = src0 -> ne [0 ]; 635const int64_t nr = ggml_nrows (src0 ); 636 637int64_t logits_ne []= {nc ,nr }; 638size_t logits_nb [2 ]; 639logits_nb [0 ]= ggml_type_size (src0 -> type ); 640logits_nb [1 ]= logits_nb [0 ]* logits_ne [0 ]; 641acl_tensor_ptr acl_logits = ggml_cann_create_tensor (src0 -> data ,ACL_FLOAT ,sizeof (float ),logits_ne ,logits_nb ,2 ); 642 643int64_t labels_ne []= {nc ,nr }; 644size_t labels_nb [2 ]; 645labels_nb [0 ]= ggml_type_size (src1 -> type ); 646labels_nb [1 ]= labels_nb [0 ]* labels_ne [0 ]; 647acl_tensor_ptr acl_labels = ggml_cann_create_tensor (src1 -> data ,ACL_FLOAT ,sizeof (float ),labels_ne ,labels_nb ,2 ); 648 649size_t loss_per_sample_type_size = sizeof (float ); 650int64_t loss_per_sample_n_bytes = nr * loss_per_sample_type_size ; 651ggml_cann_pool_alloc loss_per_sample_allocator (ctx .pool (),loss_per_sample_n_bytes ); 652void * loss_per_sample_buffer = loss_per_sample_allocator .get (); 653 654int64_t loss_per_sample_ne []= {nr }; 655size_t loss_per_sample_nb [1 ]; 656loss_per_sample_nb [0 ]= loss_per_sample_type_size ; 657acl_tensor_ptr acl_loss_per_sample = ggml_cann_create_tensor ( 658loss_per_sample_buffer ,ACL_FLOAT ,loss_per_sample_type_size ,loss_per_sample_ne ,loss_per_sample_nb ,1 ); 659 660size_t backprop_n_bytes = nr * nc * sizeof (float ); 661ggml_cann_pool_alloc backprop_allocator (ctx .pool (),backprop_n_bytes ); 662void * backprop_buffer = backprop_allocator .get (); 663acl_tensor_ptr acl_backprop = ggml_cann_create_tensor (backprop_buffer ,ACL_FLOAT ,sizeof (float ),logits_ne ,logits_nb ,2 ); 664 665GGML_CANN_CALL_ACLNN_OP (ctx ,SoftmaxCrossEntropyWithLogits ,acl_logits .get (),acl_labels .get (), 666acl_loss_per_sample .get (),acl_backprop .get ()); 667 668size_t total_sum_type_size = sizeof (float ); 669int64_t total_sum_n_bytes = 1 * total_sum_type_size ; 670ggml_cann_pool_alloc total_sum_allocator (ctx .pool (),total_sum_n_bytes ); 671void * total_sum_buffer = total_sum_allocator .get (); 672 673int64_t total_sum_ne []= {1 }; 674size_t total_sum_nb [1 ]; 675total_sum_nb [0 ]= total_sum_type_size ; 676 677acl_tensor_ptr acl_total_sum = 678ggml_cann_create_tensor (total_sum_buffer ,ACL_FLOAT ,total_sum_type_size ,total_sum_ne ,total_sum_nb ,1 ); 679 680 std::vector < int64_t > total_sum_dims = {0 }; 681acl_int_array_ptr total_sum_dims_array = ggml_cann_create_int_array (total_sum_dims .data (),total_sum_dims .size ()); 682bool keep_dims = false; 683 684GGML_CANN_CALL_ACLNN_OP (ctx ,ReduceSum ,acl_loss_per_sample .get (),total_sum_dims_array .get (),keep_dims ,ACL_FLOAT , 685acl_total_sum .get ()); 686 687float value = 1.0f /static_cast < float > (nr ); 688acl_scalar_ptr scale_factor = ggml_cann_create_scalar (& value , aclDataType::ACL_FLOAT ); 689acl_tensor_ptr acl_dst = 690ggml_cann_create_tensor (dst -> data ,ACL_FLOAT ,sizeof (float ),total_sum_ne ,total_sum_nb ,1 ); 691 692GGML_CANN_CALL_ACLNN_OP (ctx ,Muls ,acl_total_sum .get (),scale_factor .get (),acl_dst .get ()); 693} 694 695void ggml_cann_group_norm (ggml_backend_cann_context & ctx ,ggml_tensor * dst ) { 696ggml_tensor * src = dst -> src [0 ]; 697 698acl_tensor_ptr acl_src = ggml_cann_create_tensor (src ); 699acl_tensor_ptr acl_dst = ggml_cann_create_tensor (dst ); 700 701int n_groups = dst -> op_params [0 ]; 702 703float eps ; 704memcpy (& eps ,dst -> op_params + 1 ,sizeof (float )); 705 706int64_t N = src -> ne [3 ]; 707int64_t C = src -> ne [2 ]; 708int64_t HxW = src -> ne [1 ]* src -> ne [0 ]; 709 710size_t type_size = ggml_type_size (src -> type ); 711int64_t ne []= {n_groups ,N }; 712size_t nb []= {type_size ,type_size * n_groups }; 713size_t n_bytes = N * n_groups ; 714 715ggml_cann_pool_alloc temp_buffer_allocator (ctx .pool (),n_bytes * 2 ); 716void * buffer = temp_buffer_allocator .get (); 717acl_tensor_ptr acl_mean_out = ggml_cann_create_tensor (buffer ,ACL_FLOAT ,type_size ,ne ,nb ,ACL_FORMAT_ND ); 718acl_tensor_ptr acl_rstd_out = 719ggml_cann_create_tensor ((char * )buffer + n_bytes ,ACL_FLOAT ,type_size ,ne ,nb ,ACL_FORMAT_ND ); 720 721GGML_CANN_CALL_ACLNN_OP (ctx ,GroupNorm ,acl_src .get (),nullptr ,nullptr ,N ,C ,HxW ,n_groups ,eps ,acl_dst .get (), 722acl_mean_out .get (),acl_rstd_out .get ()); 723} 724 725void ggml_cann_set (ggml_backend_cann_context & ctx ,ggml_tensor * dst ) { 726ggml_tensor * src0 = dst -> src [0 ]; 727ggml_tensor * src1 = dst -> src [1 ]; 728 729size_t nb1 = ((int32_t * )dst -> op_params )[0 ]; 730size_t nb2 = ((int32_t * )dst -> op_params )[1 ]; 731size_t nb3 = ((int32_t * )dst -> op_params )[2 ]; 732size_t offset = ((int32_t * )dst -> op_params )[3 ]; 733bool inplace = (bool ) ((int32_t * )dst -> op_params )[4 ]; 734 735size_t param_nb []= {ggml_element_size (src0 ),nb1 ,nb2 ,nb3 }; 736 737// Create a view of dst at the target offset with src1's dimensions 738acl_tensor_ptr acl_dst = ggml_cann_create_tensor (dst ,src1 -> ne ,param_nb ,GGML_MAX_DIMS ,ACL_FORMAT_ND ,offset ); 739acl_tensor_ptr acl_src1 = ggml_cann_create_tensor (src1 ); 740 741if (!inplace ) { 742// First copy src0 to dst entirely 743size_t cpy_size = ggml_nbytes (dst ); 744ACL_CHECK ( 745aclrtMemcpyAsync (dst -> data ,cpy_size ,src0 -> data ,cpy_size ,ACL_MEMCPY_DEVICE_TO_DEVICE ,ctx .stream ())); 746 } 747 748// Copy src1 into the target region of dst 749GGML_CANN_CALL_ACLNN_OP (ctx ,InplaceCopy ,acl_dst .get (),acl_src1 .get ()); 750} 751 752void ggml_cann_acc (ggml_backend_cann_context & ctx ,ggml_tensor * dst ) { 753ggml_tensor * src0 = dst -> src [0 ]; 754ggml_tensor * src1 = dst -> src [1 ]; 755 756size_t nb1 = ((int32_t * )dst -> op_params )[0 ]; 757size_t nb2 = ((int32_t * )dst -> op_params )[1 ]; 758size_t nb3 = ((int32_t * )dst -> op_params )[2 ]; 759size_t offset = ((int32_t * )dst -> op_params )[3 ]; 760bool inplace = (bool ) ((int32_t * )dst -> op_params )[4 ]; 761 762size_t param_nb []= {ggml_element_size (src0 ),nb1 ,nb2 ,nb3 }; 763 764acl_tensor_ptr acl_dst = ggml_cann_create_tensor (dst ,src1 -> ne ,param_nb ,GGML_MAX_DIMS ,ACL_FORMAT_ND ,offset ); 765acl_tensor_ptr acl_src1 = ggml_cann_create_tensor (src1 ); 766 767acl_scalar_ptr alpha = nullptr ; 768float alphaValue = 1.0f ; 769alpha = ggml_cann_create_scalar (& alphaValue , aclDataType::ACL_FLOAT ); 770 771if (!inplace ) { 772size_t cpy_size = ggml_nbytes (dst ); 773ACL_CHECK ( 774aclrtMemcpyAsync (dst -> data ,cpy_size ,src0 -> data ,cpy_size ,ACL_MEMCPY_DEVICE_TO_DEVICE ,ctx .stream ())); 775acl_tensor_ptr acl_src0 = 776ggml_cann_create_tensor (src0 ,src1 -> ne ,src0 -> nb ,GGML_MAX_DIMS ,ACL_FORMAT_ND ,offset ); 777 778GGML_CANN_CALL_ACLNN_OP (ctx ,Add ,acl_src0 .get (),acl_src1 .get (),alpha .get (),acl_dst .get ()); 779 }else { 780GGML_CANN_CALL_ACLNN_OP (ctx ,InplaceAdd ,acl_dst .get (),acl_src1 .get (),alpha .get ()); 781 } 782} 783 784/** 785* @brief Performs sum reduction on a given tensor along specified dimensions. 786* 787* This function reduces the input tensor by summing along the specified dimensions. 788* 789* @param ctx The context for the CANN backend operations. 790* @param dst The destination tensor where the reduced result will be stored. 791* @param dim An array of dimension indices. 792* @param dim_size The number of dimensions. 793*/ 794static void aclnn_reduce_sum (ggml_backend_cann_context & ctx ,ggml_tensor * dst ,int64_t * dim ,size_t dim_size ) { 795GGML_ASSERT (dst -> ne [0 ]== 1 ); 796ggml_tensor * src = dst -> src [0 ]; 797acl_tensor_ptr acl_src = ggml_cann_create_tensor (src ); 798acl_tensor_ptr acl_dst = ggml_cann_create_tensor (dst ); 799acl_int_array_ptr reduce_dims = ggml_cann_create_int_array (dim ,dim_size ); 800 801GGML_CANN_CALL_ACLNN_OP (ctx ,ReduceSum ,acl_src .get (),reduce_dims .get (), true,ggml_cann_type_mapping (dst -> type ), 802acl_dst .get ()); 803} 804 805void ggml_cann_sum_rows (ggml_backend_cann_context & ctx ,ggml_tensor * dst ) { 806int64_t reduce_dims []= {3 }; 807aclnn_reduce_sum (ctx ,dst ,reduce_dims ,1 ); 808} 809 810void ggml_cann_sum (ggml_backend_cann_context & ctx ,ggml_tensor * dst ) { 811int64_t reduce_dims []= {0 ,1 ,2 ,3 }; 812aclnn_reduce_sum (ctx ,dst ,reduce_dims ,4 ); 813} 814 815void ggml_cann_cumsum (ggml_backend_cann_context & ctx ,ggml_tensor * dst ) { 816ggml_tensor * src = dst -> src [0 ]; 817acl_tensor_ptr acl_src = ggml_cann_create_tensor (src ); 818acl_tensor_ptr acl_dst = ggml_cann_create_tensor (dst ); 819// GGML cumsum operates along dim 0 (innermost / ne[0]). 820// ggml_cann_create_tensor reverses dimensions to [ne3,ne2,ne1,ne0], 821// so GGML dim 0 maps to CANN dim 3 (the last dim of the 4-D tensor). 822GGML_CANN_CALL_ACLNN_OP (ctx ,Cumsum ,acl_src .get (), (int64_t )3 , 823ggml_cann_type_mapping (dst -> type ),acl_dst .get ()); 824} 825 826void ggml_cann_solve_tri (ggml_backend_cann_context & ctx ,ggml_tensor * dst ) { 827ggml_tensor * src0 = dst -> src [0 ];// A: [N, N, B2, B3] lower triangular 828ggml_tensor * src1 = dst -> src [1 ];// B: [K, N, B2, B3] 829 830acl_tensor_ptr acl_a = ggml_cann_create_tensor (src0 ); 831acl_tensor_ptr acl_b = ggml_cann_create_tensor (src1 ); 832acl_tensor_ptr acl_x = ggml_cann_create_tensor (dst ); 833 834// mOut: triangular copy of A (required output), same shape as A. 835const size_t a_bytes = ggml_nbytes (src0 ); 836ggml_cann_pool_alloc m_alloc (ctx .pool (),a_bytes ); 837acl_tensor_ptr acl_m = ggml_cann_create_tensor ( 838m_alloc .get (),ggml_cann_type_mapping (src0 -> type ), 839ggml_type_size (src0 -> type ),src0 -> ne ,src0 -> nb ,GGML_MAX_DIMS ); 840 841// Solve AX = B: upper=false (lower tri), transpose=false, unitriangular=false. 842GGML_CANN_CALL_ACLNN_OP (ctx ,TriangularSolve , 843acl_b .get (),acl_a .get (), false, false, false, 844acl_x .get (),acl_m .get ()); 845} 846 847void ggml_cann_diag (ggml_backend_cann_context & ctx ,ggml_tensor * dst ) { 848ggml_tensor * src = dst -> src [0 ]; 849 850GGML_ASSERT (src -> ne [1 ]== 1 ); 851 852const int64_t N = src -> ne [0 ]; 853const int64_t n_batch = src -> ne [2 ]* src -> ne [3 ]; 854const size_t nb_f32 = sizeof (float ); 855 856// Fill dst with zeros. 857acl_tensor_ptr acl_dst = ggml_cann_create_tensor (dst ); 858 { 859float zero = 0.0f ; 860acl_scalar_ptr acl_zero = ggml_cann_create_scalar (& zero ,ACL_FLOAT ); 861GGML_CANN_CALL_ACLNN_OP (ctx ,InplaceFillScalar ,acl_dst .get (),acl_zero .get ()); 862 } 863 864// Copy src vector onto the diagonal of dst via strided views. 865// src viewed as [N, n_batch], contiguous strides. 866int64_t ne_vec [2 ]= {N ,n_batch }; 867size_t nb_src_vec [2 ]= {nb_f32 ,N * nb_f32 }; 868// dst diagonal view: stride (N+1)*4 steps along the diagonal. 869size_t nb_dst_diag [2 ]= { (N + 1 )* nb_f32 ,N * N * nb_f32 }; 870 871acl_tensor_ptr acl_src_vec = ggml_cann_create_tensor (src -> data ,ACL_FLOAT ,nb_f32 ,ne_vec ,nb_src_vec ,2 ); 872acl_tensor_ptr acl_dst_diag = ggml_cann_create_tensor (dst -> data ,ACL_FLOAT ,nb_f32 ,ne_vec ,nb_dst_diag ,2 ); 873 874GGML_CANN_CALL_ACLNN_OP (ctx ,InplaceCopy ,acl_dst_diag .get (),acl_src_vec .get ()); 875} 876 877void ggml_cann_fill (ggml_backend_cann_context & ctx ,ggml_tensor * dst ) { 878float c = ggml_get_op_params_f32 (dst ,0 ); 879 880acl_tensor_ptr acl_dst = ggml_cann_create_tensor (dst ); 881acl_scalar_ptr acl_c = ggml_cann_create_scalar (& c ,ACL_FLOAT ); 882GGML_CANN_CALL_ACLNN_OP (ctx ,InplaceFillScalar ,acl_dst .get (),acl_c .get ()); 883} 884 885void ggml_cann_tri (ggml_backend_cann_context & ctx ,ggml_tensor * dst ) { 886ggml_tensor * src = dst -> src [0 ]; 887 888const int64_t S = src -> ne [0 ]; 889const int64_t n_batch = src -> ne [2 ]* src -> ne [3 ]; 890const size_t nb_f32 = sizeof (float ); 891 892int64_t ne3d [3 ]= {S ,S ,n_batch }; 893size_t nb3d [3 ]= {nb_f32 ,S * nb_f32 ,S * S * nb_f32 }; 894 895const ggml_tri_type ttype = (ggml_tri_type )ggml_get_op_params_i32 (dst ,0 ); 896 897acl_tensor_ptr acl_src = ggml_cann_create_tensor (src -> data ,ACL_FLOAT ,nb_f32 ,ne3d ,nb3d ,3 ); 898acl_tensor_ptr acl_dst = ggml_cann_create_tensor (dst -> data ,ACL_FLOAT ,nb_f32 ,ne3d ,nb3d ,3 ); 899 900switch (ttype ) { 901case GGML_TRI_TYPE_LOWER : 902// Tril(-1): preserve row > col (strict lower), zero upper + diagonal. 903GGML_CANN_CALL_ACLNN_OP (ctx ,Tril ,acl_src .get (), (int64_t )-1 ,acl_dst .get ()); 904break ; 905case GGML_TRI_TYPE_UPPER_DIAG : 906// Triu(0): preserve row <= col (upper + diagonal), zero strict lower. 907GGML_CANN_CALL_ACLNN_OP (ctx ,Triu ,acl_src .get (), (int64_t )0 ,acl_dst .get ()); 908break ; 909case GGML_TRI_TYPE_UPPER : 910// Triu(1): preserve row < col (strict upper), zero lower + diagonal. 911GGML_CANN_CALL_ACLNN_OP (ctx ,Triu ,acl_src .get (), (int64_t )1 ,acl_dst .get ()); 912break ; 913case GGML_TRI_TYPE_LOWER_DIAG : 914// Tril(0): preserve row >= col (lower + diagonal), zero strict upper. 915GGML_CANN_CALL_ACLNN_OP (ctx ,Tril ,acl_src .get (), (int64_t )0 ,acl_dst .get ()); 916break ; 917default : 918GGML_ABORT ("unsupported tri type" ); 919 } 920} 921 922void ggml_cann_upsample_nearest2d (ggml_backend_cann_context & ctx ,ggml_tensor * dst ) { 923ggml_tensor * src = dst -> src [0 ]; 924acl_tensor_ptr acl_src = ggml_cann_create_tensor (src ,nullptr ,nullptr ,0 ,ACL_FORMAT_NCHW ); 925acl_tensor_ptr acl_dst = ggml_cann_create_tensor (dst ,nullptr ,nullptr ,0 ,ACL_FORMAT_NCHW ); 926 927 std::vector < int64_t > output_size {dst -> ne [1 ],dst -> ne [0 ] }; 928acl_int_array_ptr output_size_array = ggml_cann_create_int_array (output_size .data (),2 ); 929 930GGML_CANN_CALL_ACLNN_OP (ctx ,UpsampleNearest2d ,acl_src .get (),output_size_array .get (),acl_dst .get ()); 931} 932 933/** 934* @brief Pads a tensor with a specified value along each dimension. 935* 936* This function performs padding of the source tensor `acl_src` and stores the 937* result in the destination tensor `acl_dst`. The padding values for each 938* dimension are specified in the `paddings` array. 939* 940* @param ctx The context for the CANN backend operations. 941* @param acl_src The source tensor to be padded. 942* @param acl_dst The destination tensor where the padded result will be stored. 943* @param paddings An array specifying the padding values for each dimension. 944* The size of the array should be twice the number of dimensions of the tensor. 945* @param value The value to be used for padding. The default value is 0.0. 946*/ 947static void aclnn_pad (ggml_backend_cann_context & ctx , 948aclTensor * acl_src , 949aclTensor * acl_dst , 950int64_t * paddings , 951float value = 0.0f ) { 952acl_int_array_ptr acl_pad = ggml_cann_create_int_array (paddings ,GGML_MAX_DIMS * 2 ); 953acl_scalar_ptr acl_value = ggml_cann_create_scalar (& value , aclDataType::ACL_FLOAT ); 954 955GGML_CANN_CALL_ACLNN_OP (ctx ,ConstantPadNd ,acl_src ,acl_pad .get (),acl_value .get (),acl_dst ); 956} 957 958void ggml_cann_pad (ggml_backend_cann_context & ctx ,ggml_tensor * dst ) { 959ggml_tensor * src = dst -> src [0 ]; 960acl_tensor_ptr acl_src = ggml_cann_create_tensor (src ); 961acl_tensor_ptr acl_dst = ggml_cann_create_tensor (dst ); 962 963// padding: value in the array means how much distance will be padding. 964// the position of elements in the array means which dirction to padding, 965// each position means: [dim0.front, dim0.behind, dim1.front, dim1.behind, 966// dim2.front, dim2.behind, dim3.front, dim3.behind] 967const int32_t lp0 = ggml_get_op_params_i32 (dst ,0 ); 968const int32_t rp0 = ggml_get_op_params_i32 (dst ,1 ); 969const int32_t lp1 = ggml_get_op_params_i32 (dst ,2 ); 970const int32_t rp1 = ggml_get_op_params_i32 (dst ,3 ); 971const int32_t lp2 = ggml_get_op_params_i32 (dst ,4 ); 972const int32_t rp2 = ggml_get_op_params_i32 (dst ,5 ); 973const int32_t lp3 = ggml_get_op_params_i32 (dst ,6 ); 974const int32_t rp3 = ggml_get_op_params_i32 (dst ,7 ); 975 976int64_t paddings []= {lp0 ,rp0 ,lp1 ,rp1 ,lp2 ,rp2 ,lp3 ,rp3 }; 977aclnn_pad (ctx ,acl_src .get (),acl_dst .get (),paddings ); 978} 979 980/** 981* @brief Performs 2D average pooling on the input tensor and stores the result 982* in the destination tensor. 983* 984* This function performs average pooling on the source tensor and stores the 985* result in the destination tensor. The pooling parameters (kernel size, 986* strides, padding) are specified in the `op_params` of the destination tensor. 987* 988* @param ctx The context for the CANN backend operations. 989* @param dst The destination tensor where the result will be stored. The source 990* tensor is referenced by `dst->src[0]`. 991*/ 992static void ggml_cann_avg_pool2d (ggml_backend_cann_context & ctx ,ggml_tensor * dst ) { 993ggml_tensor * src = dst -> src [0 ]; 994GGML_ASSERT (src -> type == GGML_TYPE_F32 ); 995GGML_ASSERT (dst -> type == GGML_TYPE_F32 ); 996 997acl_tensor_ptr acl_src = ggml_cann_create_tensor (src ,nullptr ,nullptr ,0 ,ACL_FORMAT_NCHW ); 998acl_tensor_ptr acl_dst = ggml_cann_create_tensor (dst ,nullptr ,nullptr ,0 ,ACL_FORMAT_NCHW ); 999 1000const int32_t * opts = (const int32_t * )dst -> op_params ; 1001const int k0 = opts [1 ]; 1002const int k1 = opts [2 ]; 1003const int s0 = opts [3 ]; 1004const int s1 = opts [4 ]; 1005const int p0 = opts [5 ]; 1006const int p1 = opts [6 ]; 1007 1008 std::vector < int64_t > kernel_dims = {k1 ,k0 }; 1009 std::vector < int64_t > stride_dims = {s1 ,s0 }; 1010 std::vector < int64_t > padding_avg_dims = {p1 ,p0 };// (padH, padW) 1011 1012acl_int_array_ptr kernel_size = ggml_cann_create_int_array (kernel_dims .data (),2 ); 1013acl_int_array_ptr strides = ggml_cann_create_int_array (stride_dims .data (),2 ); 1014acl_int_array_ptr paddings_avg = ggml_cann_create_int_array (padding_avg_dims .data (),2 ); 1015 1016bool ceil_mode = false; 1017bool count_include_pad = true; 1018int64_t divisor_override = 0 ; 1019int8_t cube_math_type = 0 ; 1020#ifdef ASCEND_310P 1021cube_math_type = 1 ; 1022#endif 1023 1024GGML_CANN_CALL_ACLNN_OP (ctx ,AvgPool2d ,acl_src .get (),kernel_size .get (),strides .get (),paddings_avg .get (), 1025ceil_mode ,count_include_pad ,divisor_override ,cube_math_type ,acl_dst .get ()); 1026} 1027 1028/** 1029* @brief Performs 2D max pooling on the input tensor and stores the result in 1030* the destination tensor. 1031* 1032* This function performs max pooling on the source tensor and stores the result 1033* in the destination tensor. The pooling parameters (kernel size, strides, 1034* padding) are specified in the `op_params` of the destination tensor. 1035* 1036* @param ctx The context for the CANN backend operations. 1037* @param dst The destination tensor where the result will be stored. The source 1038* tensor is referenced by `dst->src[0]`. 1039*/ 1040static void ggml_cann_max_pool2d (ggml_backend_cann_context & ctx ,ggml_tensor * dst ) { 1041ggml_tensor * src = dst -> src [0 ]; 1042GGML_ASSERT (src -> type == GGML_TYPE_F32 ); 1043GGML_ASSERT (dst -> type == GGML_TYPE_F32 ); 1044 1045acl_tensor_ptr acl_src = ggml_cann_create_tensor (src ,nullptr ,nullptr ,0 ,ACL_FORMAT_NCHW ); 1046acl_tensor_ptr acl_dst = ggml_cann_create_tensor (dst ,nullptr ,nullptr ,0 ,ACL_FORMAT_NCHW ); 1047 1048const int32_t * opts = (const int32_t * )dst -> op_params ; 1049const int k0 = opts [1 ]; 1050const int k1 = opts [2 ]; 1051const int s0 = opts [3 ]; 1052const int s1 = opts [4 ]; 1053const int p0 = opts [5 ]; 1054const int p1 = opts [6 ]; 1055 1056int64_t temp_ne []= {src -> ne [0 ]+ p0 * 2 ,src -> ne [1 ]+ p1 * 2 ,src -> ne [2 ],src -> ne [3 ] }; 1057size_t temp_nb [GGML_MAX_DIMS ]; 1058 1059temp_nb [0 ]= ggml_element_size (src ); 1060for (int i = 1 ;i < GGML_MAX_DIMS ;i ++ ) { 1061temp_nb [i ]= temp_nb [i - 1 ]* temp_ne [i - 1 ]; 1062 } 1063 1064ggml_cann_pool_alloc temp_buffer_allocator (ctx .pool (),ggml_nbytes (src )+ p0 * 2 + p1 * 2 * src -> nb [1 ]); 1065void * buffer = temp_buffer_allocator .get (); 1066acl_tensor_ptr tmp_tensor = ggml_cann_create_tensor (buffer ,ACL_FLOAT ,ggml_element_size (src ),temp_ne ,temp_nb , 1067GGML_MAX_DIMS ,ACL_FORMAT_NCHW ); 1068 1069// pad: see padding in ggml_cann_pad() 1070int64_t paddings []= {p0 ,p0 ,p1 ,p1 ,0 ,0 ,0 ,0 }; 1071float value = - FLT_MAX ; 1072aclnn_pad (ctx ,acl_src .get (),tmp_tensor .get (),paddings ,value ); 1073 1074// max_pool 1075 std::vector < int64_t > kernel_dims = {k1 ,k0 }; 1076 std::vector < int64_t > stride_dims = {s1 ,s0 }; 1077// padding_max_dims: [dim0_start, dim0_end, dim1_start, dim1_end] 1078 std::vector < int64_t > padding_max_dims = {0 ,0 ,0 ,0 }; 1079 std::vector < int64_t > dilation_size = {1 ,1 }; 1080acl_int_array_ptr kernel_size = ggml_cann_create_int_array (kernel_dims .data (),2 ); 1081acl_int_array_ptr strides = ggml_cann_create_int_array (stride_dims .data (),2 ); 1082acl_int_array_ptr paddings_max = ggml_cann_create_int_array (padding_max_dims .data (),4 ); 1083acl_int_array_ptr dilations = ggml_cann_create_int_array (dilation_size .data (),2 ); 1084 1085bool ceil_mode = false; 1086int64_t auto_pads = 0 ; 1087GGML_CANN_CALL_ACLNN_OP (ctx ,MaxPool ,tmp_tensor .get (),kernel_size .get (),strides .get (),auto_pads , 1088paddings_max .get (),dilations .get (),ceil_mode ,acl_dst .get ()); 1089} 1090 1091void ggml_cann_pool2d (ggml_backend_cann_context & ctx ,ggml_tensor * dst ) { 1092const int32_t * opts = (const int32_t * )dst -> op_params ; 1093enum ggml_op_pool op = static_cast < ggml_op_pool > (opts [0 ]); 1094switch (op ) { 1095case GGML_OP_POOL_AVG : 1096ggml_cann_avg_pool2d (ctx ,dst ); 1097break ; 1098case GGML_OP_POOL_MAX : 1099ggml_cann_max_pool2d (ctx ,dst ); 1100break ; 1101case GGML_OP_POOL_COUNT : 1102GGML_ABORT ("fatal error" ); 1103break ; 1104 } 1105} 1106 1107/** 1108* @brief Copies data from the source tensor to the destination tensor. 1109* 1110* This function copies data from the source tensor `acl_src` to the destination 1111* tensor `acl_dst`. 1112* 1113* @param ctx The context for the CANN backend operations. 1114* @param acl_src The source tensor from which data will be copied. 1115* @param acl_dst The destination tensor where the data will be copied to. 1116*/ 1117static void cann_copy (ggml_backend_cann_context & ctx ,aclTensor * acl_src ,aclTensor * acl_dst ) { 1118GGML_CANN_CALL_ACLNN_OP (ctx ,InplaceCopy ,acl_dst ,acl_src ); 1119} 1120 1121void ggml_cann_dup (ggml_backend_cann_context & ctx ,ggml_tensor * dst ) { 1122ggml_tensor * src0 = dst -> src [0 ]; 1123 1124if (ggml_are_same_shape (src0 ,dst )) { 1125acl_tensor_ptr acl_src = ggml_cann_create_tensor (src0 ); 1126acl_tensor_ptr acl_dst = ggml_cann_create_tensor (dst ); 1127if (dst -> type == src0 -> type ) { 1128cann_copy (ctx ,acl_src .get (),acl_dst .get ()); 1129 }else { 1130aclnn_cast (ctx ,acl_src .get (),acl_dst .get (),ggml_cann_type_mapping (dst -> type )); 1131 } 1132 }else { 1133void * src_trans_buffer = src0 -> data ; 1134ggml_cann_pool_alloc src_buffer_allocator ; 1135if (!ggml_is_contiguous (src0 )) { 1136acl_tensor_ptr acl_src = ggml_cann_create_tensor (src0 ); 1137src_buffer_allocator .alloc (ctx .pool (),ggml_nelements (src0 )* ggml_type_size (src0 -> type )); 1138src_trans_buffer = src_buffer_allocator .get (); 1139size_t src_trans_nb [GGML_MAX_DIMS ]; 1140src_trans_nb [0 ]= ggml_type_size (src0 -> type ); 1141for (int i = 1 ;i < GGML_MAX_DIMS ;i ++ ) { 1142src_trans_nb [i ]= src_trans_nb [i - 1 ]* src0 -> ne [i - 1 ]; 1143 } 1144acl_tensor_ptr src_trans_tensor = 1145ggml_cann_create_tensor (src_trans_buffer ,ggml_cann_type_mapping (src0 -> type ), 1146ggml_type_size (src0 -> type ),src0 -> ne ,src_trans_nb ,GGML_MAX_DIMS ); 1147cann_copy (ctx ,acl_src .get (),src_trans_tensor .get ()); 1148 } 1149 1150size_t src_reshape_nb [GGML_MAX_DIMS ]; 1151src_reshape_nb [0 ]= ggml_type_size (src0 -> type ); 1152for (int i = 1 ;i < GGML_MAX_DIMS ;i ++ ) { 1153src_reshape_nb [i ]= src_reshape_nb [i - 1 ]* dst -> ne [i - 1 ]; 1154 } 1155 1156acl_tensor_ptr trans_acl_src = 1157ggml_cann_create_tensor (src_trans_buffer ,ggml_cann_type_mapping (src0 -> type ),ggml_type_size (src0 -> type ), 1158dst -> ne ,src_reshape_nb ,GGML_MAX_DIMS ,ACL_FORMAT_ND ); 1159acl_tensor_ptr acl_dst = ggml_cann_create_tensor (dst ); 1160 1161if (dst -> type == src0 -> type ) { 1162cann_copy (ctx ,trans_acl_src .get (),acl_dst .get ()); 1163 }else { 1164aclnn_cast (ctx ,trans_acl_src .get (),acl_dst .get (),ggml_cann_type_mapping (dst -> type )); 1165 } 1166 } 1167} 1168 1169/** 1170* @brief Creates an ACL tensor initialized with zeros using a provided buffer. 1171* 1172* This function initializes a tensor with zeros using the specified buffer and 1173* tensor parameters. 1174* 1175* @param ctx The context for the CANN backend operations. 1176* @param buffer The buffer to be used for the tensor data. 1177* @param n_bytes The size of the buffer in bytes. 1178* @param ne An array specifying the extents (sizes) of each dimension of the 1179* tensor. 1180* @param dims The number of dimensions of the tensor. 1181* @param type The data type of the tensor. 1182* @param type_size The size of each element in the tensor data type. 1183* @return A tensor smart pointer initialized with zeros. 1184*/ 1185static acl_tensor_ptr aclnn_zero (ggml_backend_cann_context & ctx , 1186void * buffer , 1187size_t n_bytes , 1188int64_t * ne , 1189int64_t dims , 1190aclDataType type , 1191size_t type_size ) { 1192size_t nb [GGML_MAX_DIMS ]; 1193nb [0 ]= type_size ; 1194for (int i = 1 ;i < dims ;i ++ ) { 1195nb [i ]= nb [i - 1 ]* ne [i - 1 ]; 1196 } 1197 1198acl_tensor_ptr zero = ggml_cann_create_tensor (buffer ,type ,type_size ,ne ,nb ,dims ); 1199GGML_CANN_CALL_ACLNN_OP (ctx ,InplaceZero ,zero .get ()); 1200return zero ; 1201GGML_UNUSED (n_bytes ); 1202} 1203 1204/** 1205* @brief Creates an ACL tensor initialized with value using a provided buffer. 1206* 1207* This function initializes a tensor with value using the specified buffer and 1208* tensor parameters. 1209* 1210* @param ctx The context for the CANN backend operations. 1211* @param buffer The buffer to be used for the tensor data. 1212* @param n_bytes The size of the buffer in bytes. 1213* @param ne An array specifying the extents (sizes) of each dimension of the 1214* tensor. 1215* @param dims The number of dimensions of the tensor. 1216* @param type The data type of the tensor. 1217* @param type_size The size of each element in the tensor data type. 1218* @param value The value to be used for initializing the tensor (default 1219* is 1.0). 1220* @return A tensor smart pointer initialized with value. 1221*/ 1222static acl_tensor_ptr aclnn_values (ggml_backend_cann_context & ctx , 1223void * buffer , 1224size_t n_bytes , 1225int64_t * ne , 1226int64_t dims , 1227aclDataType type , 1228size_t type_size , 1229float value = 1.0f ) { 1230acl_tensor_ptr acl_tensor = aclnn_zero (ctx ,buffer ,n_bytes ,ne ,dims ,type ,type_size ); 1231float alpha_host = 1.0f ; 1232acl_scalar_ptr alpha = ggml_cann_create_scalar (& alpha_host , aclDataType::ACL_FLOAT ); 1233acl_scalar_ptr other = ggml_cann_create_scalar (& value , aclDataType::ACL_FLOAT ); 1234GGML_CANN_CALL_ACLNN_OP (ctx ,InplaceAdds ,acl_tensor .get (),other .get (),alpha .get ()); 1235return acl_tensor ; 1236} 1237 1238/** 1239* @brief Fills a tensor with a scalar value. 1240* 1241* This function fills the destination tensor `acl_dst` with the scalar value 1242* `scalar`. 1243* 1244* @param ctx The context for the CANN backend operations. 1245* @param scalar The scalar value used to fill the tensor. 1246* @param acl_dst The destination tensor to be filled with the scalar value. 1247*/ 1248static void aclnn_fill_scalar (ggml_backend_cann_context & ctx ,float scalar ,aclTensor * acl_dst ) { 1249acl_scalar_ptr acl_scalar = ggml_cann_create_scalar (& scalar , aclDataType::ACL_FLOAT ); 1250GGML_CANN_CALL_ACLNN_OP (ctx ,InplaceFillScalar ,acl_dst ,acl_scalar .get ()); 1251} 1252 1253/** 1254* @brief Get or expand a cached tensor filled with a scalar value. 1255* 1256* This function manages cached device memory for tensors. If the current 1257* cache size is insufficient for the requested tensor shape, the old memory will 1258* be released and new memory will be allocated. The allocated buffer is 1259* initialized with the given scalar value using CANN operations. 1260* Finally, an aclTensor object is created from the cached memory and returned. 1261* 1262* @param ctx The CANN backend context that manages device memory. 1263* @param buffer A pointer to the cached device buffer (will be allocated 1264* or reallocated if necessary). 1265* @param cache_element The current number of cached elements. This will be 1266* updated when the cache is expanded. 1267* @param ne The tensor shape array (number of elements in each dimension). 1268* @param nb The stride size for each dimension. 1269* @param dtype Data type of cached tensor. 1270* @param dims The number of tensor dimensions. 1271* @param value The scalar value used to fill the tensor (supports zero 1272* initialization via memset or arbitrary values via fill_scalar). 1273* @return A tensor smart pointer created from the cached buffer. 1274*/ 1275static acl_tensor_ptr get_cache_acl_tensor (ggml_backend_cann_context & ctx , 1276void ** buffer , 1277int64_t & cache_element , 1278int64_t * ne , 1279size_t * nb , 1280ggml_type dtype , 1281int64_t dims , 1282float value ) { 1283// Calculate total number of elements 1284int64_t n_element = 1 ; 1285for (int i = 0 ;i < dims ;i ++ ) { 1286n_element *=ne [i ]; 1287 } 1288size_t size = n_element * ggml_type_size (dtype ); 1289 1290// Allocate or expand cache if needed 1291if (cache_element < n_element ) { 1292if (* buffer != nullptr ) { 1293aclrtFree (* buffer ); 1294* buffer = nullptr ; 1295 } 1296 1297ACL_CHECK (aclrtMalloc (buffer ,size ,ACL_MEM_MALLOC_HUGE_FIRST )); 1298cache_element = n_element ; 1299 1300// Initialize cache 1301int64_t pool_ne [1 ]= {n_element }; 1302size_t pool_nb [1 ]= {ggml_type_size (dtype ) }; 1303acl_tensor_ptr acl_value = 1304ggml_cann_create_tensor (* buffer ,ggml_cann_type_mapping (dtype ),ggml_type_size (dtype ),pool_ne ,pool_nb ,1 ); 1305aclnn_fill_scalar (ctx ,value ,acl_value .get ()); 1306 } 1307 1308return ggml_cann_create_tensor (* buffer ,ggml_cann_type_mapping (dtype ),ggml_type_size (dtype ),ne ,nb ,dims ); 1309} 1310 1311void ggml_cann_rms_norm (ggml_backend_cann_context & ctx ,ggml_tensor * dst ) { 1312ggml_tensor * src = dst -> src [0 ]; 1313 1314acl_tensor_ptr acl_src = ggml_cann_create_tensor (src ); 1315acl_tensor_ptr acl_dst = ggml_cann_create_tensor (dst ); 1316 1317float eps ; 1318memcpy (& eps ,dst -> op_params ,sizeof (float )); 1319 1320// build gamma. 1321size_t acl_gamma_nb [GGML_MAX_DIMS ]; 1322// gamma's type is the same with dst. 1323acl_gamma_nb [0 ]= ggml_type_size (dst -> type ); 1324for (int i = 1 ;i < GGML_MAX_DIMS ;i ++ ) { 1325acl_gamma_nb [i ]= acl_gamma_nb [i - 1 ]* src -> ne [i - 1 ]; 1326 } 1327acl_tensor_ptr acl_gamma = get_cache_acl_tensor ( 1328ctx ,& ctx .rms_norm_one_tensor_cache .cache ,ctx .rms_norm_one_tensor_cache .size ,src -> ne ,acl_gamma_nb ,dst -> type , 13291 ,// dims 13301.0f // value 1331 ); 1332 1333// build rstd. 1334int64_t acl_rstd_ne []= {src -> ne [1 ],src -> ne [2 ],src -> ne [3 ] }; 1335size_t acl_rstd_nb [GGML_MAX_DIMS - 1 ]; 1336// rstd will always be F32. 1337acl_rstd_nb [0 ]= sizeof (float ); 1338for (int i = 1 ;i < GGML_MAX_DIMS - 1 ;i ++ ) { 1339acl_rstd_nb [i ]= acl_rstd_nb [i - 1 ]* acl_rstd_ne [i - 1 ]; 1340 } 1341acl_tensor_ptr acl_rstd = 1342get_cache_acl_tensor (ctx ,& ctx .rms_norm_zero_tensor_cache .cache ,ctx .rms_norm_zero_tensor_cache .size , 1343acl_rstd_ne ,acl_rstd_nb ,GGML_TYPE_F32 ,GGML_MAX_DIMS - 1 , 13440.0f // value 1345 ); 1346 1347GGML_CANN_CALL_ACLNN_OP (ctx ,RmsNorm ,acl_src .get (),acl_gamma .get (),eps ,acl_dst .get (),acl_rstd .get ()); 1348} 1349 1350// TODO: performace is low. 1351void ggml_cann_diag_mask (ggml_backend_cann_context & ctx ,ggml_tensor * dst ,float value ) { 1352ggml_tensor * src = dst -> src [0 ]; 1353 1354acl_tensor_ptr acl_src = ggml_cann_create_tensor (src ); 1355acl_tensor_ptr acl_dst = ggml_cann_create_tensor (dst ); 1356 1357const int n_past = ((int32_t * )dst -> op_params )[0 ]; 1358 1359ggml_cann_pool_alloc one_tensor_allocator (ctx .pool (),ggml_nbytes (src )); 1360void * buffer = one_tensor_allocator .get (); 1361 1362acl_tensor_ptr mask_tensor = ggml_cann_create_tensor (buffer ,ggml_cann_type_mapping (src -> type ), 1363ggml_type_size (src -> type ),src -> ne ,src -> nb ,GGML_MAX_DIMS ); 1364 1365aclnn_fill_scalar (ctx ,value ,mask_tensor .get ()); 1366 1367float alphaValue = 1.0f ; 1368acl_scalar_ptr alpha = ggml_cann_create_scalar (& alphaValue , aclDataType::ACL_FLOAT ); 1369 1370GGML_CANN_CALL_ACLNN_OP (ctx ,InplaceTriu ,mask_tensor .get (),n_past + 1 ); 1371GGML_CANN_CALL_ACLNN_OP (ctx ,Tril ,acl_src .get (),n_past + 1 ,acl_dst .get ()); 1372GGML_CANN_CALL_ACLNN_OP (ctx ,InplaceAdd ,acl_dst .get (),mask_tensor .get (),alpha .get ()); 1373} 1374 1375/** 1376* @brief Permutes the dimensions of a tensor according to a specified order. 1377* 1378* This function permutes the dimensions of the source tensor `acl_src` 1379* according to the order specified in the `new_dim` array and stores the result 1380* in the destination tensor `acl_dst`. 1381* 1382* @param ctx The context for the CANN backend operations. 1383* @param acl_src The source tensor whose dimensions will be permuted. 1384* @param acl_dst The destination tensor where the permuted result will be 1385* stored. 1386* @param new_dim An array specifying the new order of dimensions for the 1387* tensor. 1388* @param dims The number of dimensions in the tensor. 1389*/ 1390static void aclnn_permute (ggml_backend_cann_context & ctx , 1391aclTensor * acl_src , 1392aclTensor * acl_dst , 1393int64_t * new_dim , 1394uint64_t dims ) { 1395acl_int_array_ptr acl_dims = ggml_cann_create_int_array (new_dim ,dims ); 1396GGML_CANN_CALL_ACLNN_OP (ctx ,Permute ,acl_src ,acl_dims .get (),acl_dst ); 1397} 1398 1399static void ggml_cann_im2col_2d_post_process (ggml_backend_cann_context & ctx , 1400ggml_tensor * dst , 1401ggml_tensor * src1 , 1402aclTensor * tmp_cast_tensor , 1403aclTensor * tmp_im2col_tensor ) { 1404// Permute: [N, IC * KH * KW, OW * OH] -> [N, OW * OH, IC * KH * KW] 1405int64_t dst_ne []= {dst -> ne [0 ],dst -> ne [1 ]* dst -> ne [2 ],dst -> ne [3 ] }; 1406size_t dst_nb []= {dst -> nb [0 ],dst -> nb [1 ],dst -> nb [3 ] }; 1407acl_tensor_ptr acl_dst = ggml_cann_create_tensor (dst ,dst_ne ,dst_nb ,GGML_MAX_DIMS - 1 ); 1408 1409int64_t permute_dim []= {0 ,2 ,1 }; 1410if (src1 -> type != dst -> type ) { 1411aclnn_permute (ctx ,tmp_cast_tensor ,acl_dst .get (),permute_dim ,3 ); 1412 }else { 1413aclnn_permute (ctx ,tmp_im2col_tensor ,acl_dst .get (),permute_dim ,3 ); 1414 } 1415} 1416 1417static void ggml_cann_im2col_1d_post_process (ggml_backend_cann_context & ctx , 1418ggml_tensor * dst , 1419ggml_tensor * src1 , 1420aclTensor * tmp_cast_tensor , 1421aclTensor * tmp_im2col_tensor , 1422const std::vector < int64_t > & im2col_op_params ) { 1423// get params 1424const int64_t KH = im2col_op_params [0 ]; 1425const int64_t KW = im2col_op_params [1 ]; 1426const int64_t IW = im2col_op_params [2 ]; 1427const int64_t IC = im2col_op_params [3 ]; 1428const int64_t N = im2col_op_params [4 ]; 1429const int64_t OH = im2col_op_params [5 ]; 1430const int64_t OW = im2col_op_params [6 ]; 1431const int64_t s0 = im2col_op_params [7 ]; 1432const int64_t p0 = im2col_op_params [8 ]; 1433const int64_t d0 = im2col_op_params [9 ]; 1434const int64_t n_bytes_factor = im2col_op_params [10 ]; 1435 1436// Permute: [N, IC * KH * KW, OW * OH] -> 1437// [N, OW * OH * n_bytes_factor, IC * KH * KW] 1438ggml_cann_pool_alloc tmp_permute_allocator (ctx .pool ()); 1439tmp_permute_allocator .alloc (ggml_nbytes (dst )* n_bytes_factor ); 1440void * tmp_permute_buffer = tmp_permute_allocator .get (); 1441 1442int64_t tmp_permute_ne []= {IC * KH * KW ,OW * OH * n_bytes_factor ,N }; 1443size_t tmp_permute_nb [GGML_MAX_DIMS - 1 ]; 1444tmp_permute_nb [0 ]= ggml_type_size (dst -> type ); 1445for (int i = 1 ;i < GGML_MAX_DIMS - 1 ;i ++ ) { 1446tmp_permute_nb [i ]= tmp_permute_nb [i - 1 ]* tmp_permute_ne [i - 1 ]; 1447 } 1448 1449acl_tensor_ptr tmp_permute_tensor = 1450ggml_cann_create_tensor (tmp_permute_buffer ,ggml_cann_type_mapping (dst -> type ),ggml_type_size (dst -> type ), 1451tmp_permute_ne ,tmp_permute_nb ,GGML_MAX_DIMS - 1 ,ACL_FORMAT_ND ); 1452 1453int64_t permute_dim []= {0 ,2 ,1 }; 1454if (src1 -> type != dst -> type ) { 1455aclnn_permute (ctx ,tmp_cast_tensor ,tmp_permute_tensor .get (),permute_dim ,3 ); 1456 }else { 1457aclnn_permute (ctx ,tmp_im2col_tensor ,tmp_permute_tensor .get (),permute_dim ,3 ); 1458 } 1459 1460// number of times the kernel moves in W dimension 1461const int n_step_w = (IW + 2 * p0 - d0 * (KW - 1 )- 1 ) /s0 + 1 ; 1462size_t offset ; 1463void * cur_dst_buffer = dst -> data ,* cur_permute_buffer = tmp_permute_buffer ; 1464 1465// memory copy with offset to restore 1D im2col from 2d 1466if (IC > 1 ) { 1467offset = IC * KH * KW * n_step_w * ggml_type_size (dst -> type ); 1468size_t cpy_size = KH * KW * ggml_type_size (dst -> type ); 1469 1470for (int c = 0 ;c < IC ;c ++ ) { 1471cur_permute_buffer = (char * )tmp_permute_buffer + offset + KH * KW * c * ggml_type_size (dst -> type ); 1472cur_dst_buffer = (char * )dst -> data + c * KH * KW * n_step_w * ggml_type_size (dst -> type ); 1473 1474for (int i = 0 ;i < n_step_w ;i ++ ) { 1475ACL_CHECK (aclrtMemcpyAsync (cur_dst_buffer ,cpy_size ,cur_permute_buffer ,cpy_size , 1476ACL_MEMCPY_DEVICE_TO_DEVICE ,ctx .stream ())); 1477cur_dst_buffer = (char * )cur_dst_buffer + KH * KW * ggml_type_size (dst -> type ); 1478cur_permute_buffer = (char * )cur_permute_buffer + KH * KW * IC * ggml_type_size (dst -> type ); 1479 } 1480 } 1481 }else { 1482offset = KH * KW * n_step_w * ggml_type_size (dst -> type );// equal to ggml_nbytes(dst) 1483ACL_CHECK (aclrtMemcpyAsync (dst -> data ,offset , (char * )tmp_permute_buffer + offset ,offset , 1484ACL_MEMCPY_DEVICE_TO_DEVICE ,ctx .stream ())); 1485 } 1486} 1487 1488void ggml_cann_im2col (ggml_backend_cann_context & ctx ,ggml_tensor * dst ) { 1489ggml_tensor * src0 = dst -> src [0 ];// kernel 1490ggml_tensor * src1 = dst -> src [1 ];// input 1491 1492GGML_TENSOR_BINARY_OP_LOCALS ; 1493 1494// aclnnIm2col only works on 2D. set s1, p1, d1 to 1 to perform 2D 1495// im2col and do post-processing to restore it to 1D. 1496const bool is_2D = ((const int32_t * ) (dst -> op_params ))[6 ]== 1 ; 1497const int32_t s0 = ((const int32_t * ) (dst -> op_params ))[0 ]; 1498const int32_t s1 = is_2D ? ((const int32_t * ) (dst -> op_params ))[1 ] :1 ; 1499const int32_t p0 = ((const int32_t * ) (dst -> op_params ))[2 ]; 1500const int32_t p1 = is_2D ? ((const int32_t * ) (dst -> op_params ))[3 ] :1 ; 1501const int32_t d0 = ((const int32_t * ) (dst -> op_params ))[4 ]; 1502const int32_t d1 = is_2D ? ((const int32_t * ) (dst -> op_params ))[5 ] :1 ; 1503 1504const int64_t N = ne13 ; 1505const int64_t IC = ne12 ; 1506const int64_t KH = ne01 ; 1507const int64_t KW = ne00 ; 1508const int64_t IW = ne10 ; 1509 1510const int64_t OH = is_2D ?ne2 :1 ; 1511const int64_t OW = ne1 ; 1512 1513// memory allocated increased to 3x when is_2D == false 1514const int64_t n_bytes_factor = is_2D ?1 :3 ; 1515 1516// im2col: [N,C,H,W] -> [N, IC * KH * KW, OW * OH * n_bytes_factor] 1517acl_tensor_ptr acl_src1 = ggml_cann_create_tensor (src1 ); 1518int64_t tmp_im2col_ne []= {OW * OH * n_bytes_factor ,IC * KH * KW ,N }; 1519size_t tmp_im2col_nb [GGML_MAX_DIMS - 1 ]; 1520 1521tmp_im2col_nb [0 ]= ggml_type_size (src1 -> type ); 1522for (int i = 1 ;i < GGML_MAX_DIMS - 1 ;i ++ ) { 1523tmp_im2col_nb [i ]= tmp_im2col_nb [i - 1 ]* tmp_im2col_ne [i - 1 ]; 1524 } 1525 1526// Calculate im2col. 1527// If dst is f16, tmp_buffer is f32, we need alloc src.typesize * 1528// dst.elemcount. 1529ggml_cann_pool_alloc im2col_allocator (ctx .pool (),ggml_nelements (dst )* ggml_element_size (src1 )* n_bytes_factor ); 1530void * tmp_im2col_buffer = im2col_allocator .get (); 1531 1532acl_tensor_ptr tmp_im2col_tensor = 1533ggml_cann_create_tensor (tmp_im2col_buffer ,ggml_cann_type_mapping (src1 -> type ),ggml_type_size (src1 -> type ), 1534tmp_im2col_ne ,tmp_im2col_nb ,GGML_MAX_DIMS - 1 ,ACL_FORMAT_ND ); 1535 1536 std::vector < int64_t > kernel_dims = {KH ,KW }; 1537 std::vector < int64_t > dilation_size = {d1 ,d0 }; 1538 std::vector < int64_t > padding_dims = {p1 ,p0 }; 1539 std::vector < int64_t > stride_dims = {s1 ,s0 }; 1540acl_int_array_ptr kernel_size = ggml_cann_create_int_array (kernel_dims .data (),2 ); 1541acl_int_array_ptr dilations = ggml_cann_create_int_array (dilation_size .data (),2 ); 1542acl_int_array_ptr paddings = ggml_cann_create_int_array (padding_dims .data (),2 ); 1543acl_int_array_ptr strides = ggml_cann_create_int_array (stride_dims .data (),2 ); 1544GGML_CANN_CALL_ACLNN_OP (ctx ,Im2col ,acl_src1 .get (),kernel_size .get (),dilations .get (),paddings .get (), 1545strides .get (),tmp_im2col_tensor .get ()); 1546 1547// Cast if dst is f16. 1548acl_tensor_ptr tmp_cast_tensor ; 1549ggml_cann_pool_alloc tmp_cast_allocator (ctx .pool ()); 1550void * tmp_cast_buffer = nullptr ; 1551if (src1 -> type != dst -> type ) { 1552tmp_cast_allocator .alloc (ggml_nbytes (dst )* n_bytes_factor ); 1553tmp_cast_buffer = tmp_cast_allocator .get (); 1554size_t temp_cast_nb [GGML_MAX_DIMS - 1 ]; 1555temp_cast_nb [0 ]= ggml_type_size (dst -> type ); 1556for (int i = 1 ;i < GGML_MAX_DIMS - 1 ;i ++ ) { 1557temp_cast_nb [i ]= temp_cast_nb [i - 1 ]* tmp_im2col_ne [i - 1 ]; 1558 } 1559 1560tmp_cast_tensor = 1561ggml_cann_create_tensor (tmp_cast_buffer ,ggml_cann_type_mapping (dst -> type ),ggml_type_size (dst -> type ), 1562tmp_im2col_ne ,temp_cast_nb ,GGML_MAX_DIMS - 1 ,ACL_FORMAT_ND ); 1563aclnn_cast (ctx ,tmp_im2col_tensor .get (),tmp_cast_tensor .get (),ggml_cann_type_mapping (dst -> type )); 1564 } 1565 1566// post-processing 1567if (is_2D ) { 1568ggml_cann_im2col_2d_post_process (ctx ,dst ,src1 ,tmp_cast_tensor .get (),tmp_im2col_tensor .get ()); 1569 }else { 1570 std::vector < int64_t > im2col_op_params = {KH ,KW ,IW ,IC ,N ,OH ,OW ,s0 ,p0 ,d0 ,n_bytes_factor }; 1571ggml_cann_im2col_1d_post_process (ctx ,dst ,src1 ,tmp_cast_tensor .get (),tmp_im2col_tensor .get (), 1572im2col_op_params ); 1573 } 1574} 1575 1576/** 1577* @brief Applies element-wise exponential function to the elements of a tensor. 1578* 1579* This function computes the exponential of each element in the source tensor 1580* `acl_src` and stores the result back into the same tensor. 1581* The operation is defined as: 1582* \f[ 1583* \text {acl_src }_i=e^{acl\_src_i} 1584* \f] 1585* 1586* @param ctx The context for the CANN backend operations. 1587* @param acl_src The tensor on which the exponential function will be applied. 1588*/ 1589static void aclnn_exp (ggml_backend_cann_context & ctx ,aclTensor * acl_src ) { 1590GGML_CANN_CALL_ACLNN_OP (ctx ,InplaceExp ,acl_src ); 1591} 1592 1593void aclnn_cos (ggml_backend_cann_context & ctx ,aclTensor * acl_src ,aclTensor * acl_dst ) { 1594if (acl_dst == nullptr ) { 1595GGML_CANN_CALL_ACLNN_OP (ctx ,InplaceCos ,acl_src ); 1596 }else { 1597GGML_CANN_CALL_ACLNN_OP (ctx ,Cos ,acl_src ,acl_dst ); 1598 } 1599} 1600 1601void aclnn_sin (ggml_backend_cann_context & ctx ,aclTensor * acl_src ,aclTensor * acl_dst ) { 1602if (acl_dst == nullptr ) { 1603GGML_CANN_CALL_ACLNN_OP (ctx ,InplaceSin ,acl_src ); 1604 }else { 1605GGML_CANN_CALL_ACLNN_OP (ctx ,Sin ,acl_src ,acl_dst ); 1606 } 1607} 1608 1609void ggml_cann_timestep_embedding (ggml_backend_cann_context & ctx ,ggml_tensor * dst ) { 1610const ggml_tensor * src = dst -> src [0 ]; 1611 1612GGML_ASSERT (src -> type == GGML_TYPE_F32 ); 1613GGML_ASSERT (dst -> type == GGML_TYPE_F32 ); 1614 1615const int dim = dst -> op_params [0 ]; 1616const int max_period = dst -> op_params [1 ]; 1617int half = dim /2 ; 1618 1619acl_tensor_ptr acl_src = ggml_cann_create_tensor (src ); 1620 1621// arange: [0, ..., half) 1622float start = 0 ; 1623float stop = half ; 1624float step = 1 ; 1625int64_t n_elements_arange = half ; 1626int64_t tmp_arange_ne []= {half }; 1627size_t tmp_arange_nb []= {sizeof (dst -> type ) }; 1628 1629ggml_cann_pool_alloc arange_allocator (ctx .pool (),half * sizeof (dst -> type )); 1630void * tmp_arange_buffer = arange_allocator .get (); 1631acl_tensor_ptr tmp_arange_tensor = 1632ggml_cann_create_tensor (tmp_arange_buffer ,ggml_cann_type_mapping (dst -> type ),ggml_type_size (dst -> type ), 1633tmp_arange_ne ,tmp_arange_nb ,GGML_MAX_DIMS - 3 ,ACL_FORMAT_ND ); 1634 1635aclnn_arange (ctx ,tmp_arange_tensor .get (),start ,stop ,step ,n_elements_arange ); 1636 1637// freq 1638float freq_param = - logf (max_period ) /half ; 1639bool inplace = true; 1640aclnn_muls (ctx ,tmp_arange_tensor .get (),freq_param ,nullptr ,inplace ); 1641aclnn_exp (ctx ,tmp_arange_tensor .get ()); 1642 1643// permute: src [0,1,2,3]->[0,1,3,2] 1644int64_t tmp_permute_ne []= {src -> ne [1 ],src -> ne [0 ],src -> ne [2 ],src -> ne [3 ] }; 1645size_t tmp_permute_nb [GGML_MAX_DIMS ]; 1646tmp_permute_nb [0 ]= ggml_type_size (src -> type ); 1647for (int i = 1 ;i < GGML_MAX_DIMS ;i ++ ) { 1648tmp_permute_nb [i ]= tmp_permute_nb [i - 1 ]* tmp_permute_ne [i - 1 ]; 1649 } 1650 1651ggml_cann_pool_alloc permute_allocator (ctx .pool (),ggml_nbytes (src )); 1652void * tmp_permute_buffer = permute_allocator .get (); 1653acl_tensor_ptr tmp_permute_tensor = 1654ggml_cann_create_tensor (tmp_permute_buffer ,ggml_cann_type_mapping (src -> type ),ggml_type_size (src -> type ), 1655tmp_permute_ne ,tmp_permute_nb ,GGML_MAX_DIMS ,ACL_FORMAT_ND ); 1656int64_t permute_dim []= {0 ,1 ,3 ,2 }; 1657int64_t num_dims = 4 ; 1658aclnn_permute (ctx ,acl_src .get (),tmp_permute_tensor .get (),permute_dim ,num_dims ); 1659 1660// timestep * freq 1661int64_t tmp_mul_ne []= {src -> ne [1 ]* half ,src -> ne [0 ],src -> ne [2 ],src -> ne [3 ] }; 1662size_t tmp_mul_nb [GGML_MAX_DIMS ]; 1663tmp_mul_nb [0 ]= ggml_type_size (src -> type ); 1664for (int i = 1 ;i < GGML_MAX_DIMS ;i ++ ) { 1665tmp_mul_nb [i ]= tmp_mul_nb [i - 1 ]* tmp_mul_ne [i - 1 ]; 1666 } 1667 1668int mul_nelements = src -> ne [1 ]* half * src -> ne [0 ]* src -> ne [2 ]* src -> ne [3 ]; 1669 1670ggml_cann_pool_alloc mul_allocator (ctx .pool (),mul_nelements * ggml_type_size (src -> type )); 1671void * tmp_mul_buffer = mul_allocator .get (); 1672acl_tensor_ptr tmp_mul_tensor = 1673ggml_cann_create_tensor (tmp_mul_buffer ,ggml_cann_type_mapping (src -> type ),ggml_type_size (src -> type ), 1674tmp_mul_ne ,tmp_mul_nb ,GGML_MAX_DIMS ,ACL_FORMAT_ND ); 1675aclnn_mul (ctx ,tmp_permute_tensor .get (),tmp_arange_tensor .get (),tmp_mul_tensor .get ()); 1676 1677// cos 1678ggml_cann_pool_alloc cos_allocator (ctx .pool (),mul_nelements * ggml_type_size (src -> type )); 1679void * tmp_cos_buffer = cos_allocator .get (); 1680acl_tensor_ptr tmp_cos_tensor = 1681ggml_cann_create_tensor (tmp_cos_buffer ,ggml_cann_type_mapping (dst -> type ),ggml_type_size (dst -> type ), 1682tmp_mul_ne ,tmp_mul_nb ,GGML_MAX_DIMS ,ACL_FORMAT_ND ); 1683 1684aclnn_cos (ctx ,tmp_mul_tensor .get (),tmp_cos_tensor .get ()); 1685 1686// sin 1687ggml_cann_pool_alloc sin_allocator (ctx .pool (),mul_nelements * ggml_type_size (src -> type )); 1688void * tmp_sin_buffer = sin_allocator .get (); 1689acl_tensor_ptr tmp_sin_tensor = 1690ggml_cann_create_tensor (tmp_sin_buffer ,ggml_cann_type_mapping (dst -> type ),ggml_type_size (dst -> type ), 1691tmp_mul_ne ,tmp_mul_nb ,GGML_MAX_DIMS ,ACL_FORMAT_ND ); 1692 1693aclnn_sin (ctx ,tmp_mul_tensor .get (),tmp_sin_tensor .get ()); 1694 1695// concat 1696int64_t concat_dim = 3 ; 1697acl_tensor_ptr acl_dst = ggml_cann_create_tensor (dst ); 1698acl_tensor_list_ptr tensor_list = ggml_cann_create_tensor_list (tmp_cos_tensor ,tmp_sin_tensor ); 1699aclnn_concat (ctx ,tensor_list .get (),acl_dst .get (),concat_dim ); 1700} 1701 1702/** 1703* @brief Raises each element of a tensor to the power of the corresponding 1704* element in another tensor. 1705* 1706* This function computes the element-wise power of the destination tensor 1707* `acl_dst` raised to the power of the exponent tensor `acl_exp`. 1708* The operation is defined as: 1709* \f[ 1710* \text {acl_dst }_i=acl\_dst_i^{\text {acl_exp }_i} 1711* \f] 1712* 1713* @param ctx The context for the CANN backend operations. 1714* @param acl_dst The destination tensor, which also serves as the base tensor. 1715* @param acl_exp The exponent tensor, each element of which is used to raise 1716* the corresponding element in the destination tensor. 1717*/ 1718static void aclnn_pow_tensor_tensor (ggml_backend_cann_context & ctx ,aclTensor * acl_dst ,aclTensor * acl_exp ) { 1719GGML_CANN_CALL_ACLNN_OP (ctx ,InplacePowTensorTensor ,acl_dst ,acl_exp ); 1720} 1721 1722/** 1723* @brief Generate a range of values and apply a scalar base exponentiation. 1724* 1725* This function creates an evenly spaced sequence from `start` to `stop` (exclusive), 1726* with step size `step`, stores it in a temporary buffer, and then computes: 1727* 1728* @f[ 1729* slope[i] = m^{\left( start + i \cdot step \right)}, \quad 0 \le i < size 1730* @f] 1731* 1732* The results are written to the provided @p slope_buffer. 1733* 1734* @param ctx CANN backend context for memory allocation and operator execution. 1735* @param slope_buffer Pointer to the output buffer (float array) for the computed slope values. 1736* @param m Scalar base for the exponentiation. 1737* @param size Number of elements in the generated sequence. 1738* @param start Starting exponent offset. 1739* @param stop Stopping exponent offset (exclusive). 1740* @param step Step size for the exponent increment. 1741* @param dtype Data type for slope tensor. 1742*/ 1743static void aclnn_get_slope_inner (ggml_backend_cann_context & ctx , 1744void * slope_buffer , 1745float m , 1746int64_t size , 1747float start , 1748float stop , 1749float step , 1750ggml_type dtype ) { 1751aclDataType acl_type = ggml_cann_type_mapping (dtype ); 1752size_t type_size = ggml_type_size (dtype ); 1753 1754int64_t ne []= {size }; 1755size_t nb []= {type_size }; 1756 1757ggml_cann_pool_alloc arange_allocator (ctx .pool (),size * type_size ); 1758void * arange_buffer = arange_allocator .get (); 1759 1760acl_tensor_ptr arange_tensor = ggml_cann_create_tensor (arange_buffer ,acl_type ,type_size ,ne ,nb ,1 ); 1761aclnn_arange (ctx ,arange_tensor .get (),start ,stop ,step ,size ); 1762 1763acl_tensor_ptr slope_tensor = ggml_cann_create_tensor (slope_buffer ,acl_type ,type_size ,ne ,nb ,1 ); 1764 1765acl_scalar_ptr sc = ggml_cann_create_scalar (& m , aclDataType::ACL_FLOAT ); 1766 1767GGML_CANN_CALL_ACLNN_OP (ctx ,PowScalarTensor ,sc .get (),arange_tensor .get (),slope_tensor .get ()); 1768} 1769 1770/** 1771* @brief Compute slope values for multiple attention heads based on ALiBi bias parameters. 1772* 1773* This function generates slope values for each attention head according to the ALiBi 1774* (Attention with Linear Biases) method. It splits the computation into two ranges depending 1775* on whether the head index is less than @p n_head_log2 or not, and uses different base values 1776* (`m0` and `m1`) for the exponentiation. 1777* 1778* @f[ 1779* slope[h] = 1780* \begin{cases} 1781* m_0^{(h + 1)}, & h < n\_head\_log2 \\ 1782* m_1^{\left( 2 \cdot (h - n\_head\_log2) + 1 \right)}, & h \geq n\_head\_log2 1783* \end{cases} 1784* \quad , \quad \text{if } max\_bias > 0 1785* @f] 1786* 1787* If @p max_bias <= 0, all slope values are set to 1.0. 1788* 1789* @param ctx CANN backend context for memory allocation and operator execution. 1790* @param n_head Total number of attention heads. 1791* @param slope_buffer Pointer to the output buffer (float array) for storing slopes. 1792* @param max_bias Maximum bias value for slope computation. 1793* @param dtype Data type for slope tensor. 1794* 1795*/ 1796static void aclnn_get_slope (ggml_backend_cann_context & ctx , 1797int64_t n_head , 1798void * slope_buffer , 1799float max_bias , 1800ggml_type dtype ) { 1801const int n_head_log2 = 1u << (uint32_t )floor (log2 (n_head )); 1802 1803float m0 = powf (2.0f ,- (max_bias ) /n_head_log2 ); 1804float m1 = powf (2.0f ,- (max_bias /2.0f ) /n_head_log2 ); 1805 1806// const float slope = (max_bias > 0.0f) ? 1807// h < n_head_log2 ? 1808// powf(m0, h + 1) : 1809// powf(m1, 2*(h - n_head_log2) + 1) : 1810// 1.0f; 1811// arange1 1812float start = 0 + 1 ; 1813float end = (n_head_log2 - 1 )+ 1 ; 1814float step = 1 ; 1815float count = n_head_log2 ; 1816// end needs to be +1 because aclnn uses a left-closed, right-open interval. 1817aclnn_get_slope_inner (ctx ,slope_buffer ,m0 ,count ,start ,end + 1 ,step ,dtype ); 1818if (n_head_log2 < n_head ) { 1819// arange2 1820start = 2 * (n_head_log2 - n_head_log2 )+ 1 ; 1821end = 2 * ((n_head - 1 )- n_head_log2 )+ 1 ; 1822step = 2 ; 1823count = n_head - n_head_log2 ; 1824aclnn_get_slope_inner (ctx , (char * )slope_buffer + n_head_log2 * ggml_type_size (dtype ),m1 ,count ,start ,end + 1 , 1825step ,dtype ); 1826 } 1827} 1828 1829/** 1830* @brief Add ALiBi (Attention with Linear Biases) positional biases to the attention mask. 1831* 1832* This function computes the ALiBi slopes for each attention head (if max_bias > 0), 1833* multiplies them with the attention mask to produce bias tensors, and adds these biases 1834* to the destination tensor (@p dst). 1835* 1836* The function performs necessary broadcasting of the mask and slope tensors to match 1837* the shape of the destination tensor, then applies element-wise multiplication and addition 1838* using CANN operators. 1839* 1840* @param ctx CANN backend context for memory management and operator execution. 1841* @param mask Input attention mask tensor, assumed to be contiguous. 1842* @param dst Destination tensor to which ALiBi biases will be added. 1843* @param dst_ptr Pointer to the memory of the destination tensor. 1844* @param max_bias Maximum bias value controlling the slope scaling. 1845* 1846* @note 1847* - Write data into dst_ptr using only the shape information of the dst tensor. 1848* - `GGML_MAX_DIMS + 2` is used to extend tensor dimensions for broadcasting. 1849*/ 1850static void aclnn_add_alibi (ggml_backend_cann_context & ctx , 1851ggml_tensor * mask , 1852ggml_tensor * dst , 1853void * dst_ptr , 1854float max_bias ) { 1855void * slope_buffer = nullptr ; 1856void * bias_buffer = nullptr ; 1857 1858if (max_bias > 0.0f ) { 1859int64_t n_heads = dst -> ne [2 ]; 1860ggml_cann_pool_alloc slope_allocator (ctx .pool (),n_heads * sizeof (float )); 1861slope_buffer = slope_allocator .get (); 1862ggml_cann_pool_alloc bias_allocator (ctx .pool (),ggml_nelements (dst )* ggml_element_size (dst )); 1863bias_buffer = bias_allocator .get (); 1864aclnn_get_slope (ctx ,n_heads ,slope_buffer ,max_bias ,GGML_TYPE_F32 ); 1865 } 1866 1867// broadcast for mask, slop and dst; 1868int64_t nr2 = dst -> ne [2 ] /mask -> ne [2 ]; 1869int64_t nr3 = dst -> ne [3 ] /mask -> ne [3 ]; 1870 1871// broadcast the mask across rows 1872int64_t mask_ne []= {mask -> ne [0 ],dst -> ne [1 ],mask -> ne [2 ],1 ,mask -> ne [3 ],1 }; 1873size_t mask_nb []= {mask_nb [0 ]= mask -> nb [0 ],mask_nb [1 ]= mask -> nb [1 ],mask_nb [2 ]= mask -> nb [2 ], 1874mask_nb [3 ]= mask -> nb [2 ],mask_nb [4 ]= mask -> nb [3 ],mask_nb [5 ]= mask -> nb [3 ] }; 1875 1876int64_t dst_ne []= {dst -> ne [0 ],dst -> ne [1 ],mask -> ne [2 ],nr2 ,mask -> ne [3 ],nr3 }; 1877size_t dst_nb []= {dst_nb [0 ]= dst -> nb [0 ],dst_nb [1 ]= dst -> nb [1 ],dst_nb [2 ]= dst -> nb [2 ], 1878dst_nb [3 ]= dst -> nb [2 ],dst_nb [4 ]= dst -> nb [3 ],dst_nb [5 ]= dst -> nb [3 ] }; 1879 1880// slope is a 1 dim tensor, slope.ne2 == dst.ne2 1881int64_t slope_ne []= {1 ,1 ,mask -> ne [2 ],nr2 ,1 ,1 }; 1882size_t slope_nb [GGML_MAX_DIMS + 2 ]; 1883slope_nb [0 ]= sizeof (float ); 1884for (int i = 1 ;i < GGML_MAX_DIMS + 2 ;i ++ ) { 1885slope_nb [i ]= slope_nb [i - 1 ]* slope_ne [i - 1 ]; 1886 } 1887 1888acl_tensor_ptr acl_slope = 1889ggml_cann_create_tensor (slope_buffer ,ACL_FLOAT ,sizeof (float ),slope_ne ,slope_nb ,GGML_MAX_DIMS + 2 ); 1890acl_tensor_ptr acl_mask = ggml_cann_create_tensor (mask ,mask_ne ,mask_nb ,GGML_MAX_DIMS + 2 ); 1891 1892// write data into dst_ptr using only the shape information of the dst tensor. 1893acl_tensor_ptr acl_dst = ggml_cann_create_tensor (dst_ptr ,ggml_cann_type_mapping (dst -> type ), 1894ggml_type_size (dst -> type ),dst_ne ,dst_nb ,GGML_MAX_DIMS + 2 ); 1895 1896if (max_bias > 0.0f ) { 1897int64_t bias_ne []= {mask -> ne [0 ],dst -> ne [1 ],mask -> ne [2 ],nr2 ,mask -> ne [3 ],1 }; 1898size_t bias_nb [GGML_MAX_DIMS + 2 ]; 1899bias_nb [0 ]= sizeof (float ); 1900for (int i = 1 ;i < GGML_MAX_DIMS + 2 ;i ++ ) { 1901bias_nb [i ]= bias_nb [i - 1 ]* bias_ne [i - 1 ]; 1902 } 1903acl_tensor_ptr bias_tensor = 1904ggml_cann_create_tensor (bias_buffer ,ACL_FLOAT ,sizeof (float ),bias_ne ,bias_nb ,GGML_MAX_DIMS + 2 ); 1905 1906aclnn_mul (ctx ,acl_slope .get (),acl_mask .get (),bias_tensor .get ()); 1907aclnn_add (ctx ,acl_dst .get (),bias_tensor .get ()); 1908 }else { 1909aclnn_add (ctx ,acl_dst .get (),acl_mask .get ()); 1910 } 1911} 1912 1913void ggml_cann_cpy (ggml_backend_cann_context & ctx ,ggml_tensor * dst ) { 1914ggml_cann_dup (ctx ,dst ); 1915} 1916 1917/** 1918* @brief Applies the softmax function to a tensor along a specified dimension. 1919* 1920* This function computes the softmax of the source tensor `acl_src` along the 1921* specified dimension `dim` and stores the result in the destination tensor 1922* `acl_dst`. 1923* 1924* @param ctx The context for the CANN backend operations. 1925* @param acl_src The source tensor on which the softmax function will be 1926* applied. 1927* @param dim The dimension along which the softmax function will be computed. 1928* @param acl_dst The destination tensor where the softmax results will be 1929* stored. 1930*/ 1931static void aclnn_softmax (ggml_backend_cann_context & ctx ,aclTensor * acl_src ,int64_t dim ,aclTensor * acl_dst ) { 1932GGML_CANN_CALL_ACLNN_OP (ctx ,Softmax ,acl_src ,dim ,acl_dst ); 1933} 1934 1935void ggml_cann_softmax (ggml_backend_cann_context & ctx ,ggml_tensor * dst ) { 1936ggml_tensor * src0 = dst -> src [0 ]; 1937ggml_tensor * src1 = dst -> src [1 ];// mask 1938 1939acl_tensor_ptr acl_src0 = ggml_cann_create_tensor (src0 ); 1940acl_tensor_ptr acl_dst = ggml_cann_create_tensor (dst ); 1941 1942float scale = 1.0f ; 1943float max_bias = 0.0f ; 1944 1945memcpy (& scale , (float * )dst -> op_params + 0 ,sizeof (float )); 1946memcpy (& max_bias , (float * )dst -> op_params + 1 ,sizeof (float )); 1947 1948// input mul scale 1949acl_scalar_ptr acl_scale = ggml_cann_create_scalar (& scale , aclDataType::ACL_FLOAT ); 1950ggml_cann_pool_alloc src_tensor_allocator (ctx .pool (),ggml_nbytes (src0 )); 1951void * src_tensor_buffer = src_tensor_allocator .get (); 1952acl_tensor_ptr softmax_tensor = ggml_cann_create_tensor (src_tensor_buffer ,ggml_cann_type_mapping (src0 -> type ), 1953ggml_element_size (src0 ),src0 -> ne ,src0 -> nb ,GGML_MAX_DIMS ); 1954 1955aclnn_muls (ctx ,acl_src0 .get (),scale ,softmax_tensor .get (), false); 1956 1957// mask 1958if (src1 ) { 1959aclnn_add_alibi (ctx ,src1 ,src0 ,src_tensor_buffer ,max_bias ); 1960 } 1961// softmax 1962aclnn_softmax (ctx ,softmax_tensor .get (),3 ,acl_dst .get ()); 1963} 1964 1965 1966void ggml_cann_get_rows (ggml_backend_cann_context & ctx ,ggml_tensor * dst ) { 1967ggml_tensor * src0 = dst -> src [0 ];// weight 1968ggml_tensor * src1 = dst -> src [1 ];// index 1969 1970GGML_ASSERT (dst -> type == GGML_TYPE_F32 || dst -> type == GGML_TYPE_F16 1971|| dst -> type == GGML_TYPE_BF16 ); 1972 1973// n_idx: number of row indices per (i2, i3) batch slice. 1974// ggml guarantees: src0->ne[2] == src1->ne[1], src0->ne[3] == src1->ne[2], src1->ne[3] == 1. 1975const int64_t n_idx = src1 -> ne [0 ]; 1976 1977// Gather all (i2, i3) batch slices from src into dst. 1978// ggml_cann_create_tensor reverses dims, so ACL sees [ne1, ne0]. 1979// GatherV2 with dim=0 gathers along ACL dim-0 == ggml ne[1] (the vocabulary / row axis). 1980// nb: the 4 strides of the source buffer (nb[0..1] for the 2D slice shape, 1981// nb[2..3] for computing per-batch-slice base pointer offsets). 1982auto gather_batched = [& ](void * src_base ,aclDataType acl_type ,size_t type_size , 1983const size_t * nb ) { 1984int64_t src_ne [2 ]= {src0 -> ne [0 ],src0 -> ne [1 ] }; 1985size_t src_nb_2d [2 ]= {nb [0 ],nb [1 ] }; 1986int64_t dst_ne [2 ]= {src0 -> ne [0 ],n_idx }; 1987size_t dst_nb_2d [2 ]= {dst -> nb [0 ],dst -> nb [1 ] }; 1988int64_t idx_ne [1 ]= {n_idx }; 1989size_t idx_nb [1 ]= { (size_t )ggml_element_size (src1 ) }; 1990 1991for (int64_t i3 = 0 ;i3 < src0 -> ne [3 ];i3 ++ ) { 1992for (int64_t i2 = 0 ;i2 < src0 -> ne [2 ];i2 ++ ) { 1993acl_tensor_ptr acl_src = ggml_cann_create_tensor ( 1994 (char * )src_base + i3 * nb [3 ]+ i2 * nb [2 ], 1995acl_type ,type_size ,src_ne ,src_nb_2d ,2 ); 1996acl_tensor_ptr acl_idx = ggml_cann_create_tensor ( 1997 (char * )src1 -> data + i3 * src1 -> nb [2 ]+ i2 * src1 -> nb [1 ], 1998ggml_cann_type_mapping (src1 -> type ), (size_t )ggml_element_size (src1 ), 1999idx_ne ,idx_nb ,1 ); 2000acl_tensor_ptr acl_dst = ggml_cann_create_tensor ( 2001 (char * )dst -> data + i3 * dst -> nb [3 ]+ i2 * dst -> nb [2 ], 2002acl_type ,type_size ,dst_ne ,dst_nb_2d ,2 ); 2003GGML_CANN_CALL_ACLNN_OP (ctx ,GatherV2 ,acl_src .get (),0 ,acl_idx .get (),acl_dst .get ()); 2004 } 2005 } 2006 }; 2007 2008switch (src0 -> type ) { 2009case GGML_TYPE_BF16 : 2010case GGML_TYPE_F16 : 2011case GGML_TYPE_F32 : 2012if (src0 -> type == dst -> type ) { 2013gather_batched (src0 -> data , 2014ggml_cann_type_mapping (src0 -> type ),ggml_type_size (src0 -> type ), 2015src0 -> nb ); 2016 }else { 2017// Cast src0 to dst type, then gather. 2018ggml_cann_pool_alloc src_cast_allocator (ctx .pool (), 2019ggml_nelements (src0 )* ggml_element_size (dst )); 2020size_t src_cast_nb [GGML_MAX_DIMS ]; 2021src_cast_nb [0 ]= ggml_type_size (dst -> type ); 2022for (int i = 1 ;i < GGML_MAX_DIMS ;i ++ ) { 2023src_cast_nb [i ]= src_cast_nb [i - 1 ]* src0 -> ne [i - 1 ]; 2024 } 2025acl_tensor_ptr acl_src0 = ggml_cann_create_tensor (src0 ); 2026acl_tensor_ptr acl_src_cast = ggml_cann_create_tensor ( 2027src_cast_allocator .get (),ggml_cann_type_mapping (dst -> type ),ggml_type_size (dst -> type ), 2028src0 -> ne ,src_cast_nb ,GGML_MAX_DIMS ); 2029aclnn_cast (ctx ,acl_src0 .get (),acl_src_cast .get (),ggml_cann_type_mapping (dst -> type )); 2030 2031gather_batched (src_cast_allocator .get (), 2032ggml_cann_type_mapping (dst -> type ),ggml_type_size (dst -> type ), 2033src_cast_nb ); 2034 } 2035break ; 2036case GGML_TYPE_Q8_0 : 2037 { 2038// Dequantize Q8_0 to dst type, then gather. 2039size_t weight_nb [GGML_MAX_DIMS + 1 ],scale_nb [GGML_MAX_DIMS + 1 ],dequant_nb [GGML_MAX_DIMS + 1 ]; 2040int64_t weight_ne [GGML_MAX_DIMS + 1 ],scale_ne [GGML_MAX_DIMS + 1 ],* dequant_ne ; 2041weight_ne [0 ]= QK8_0 ; 2042weight_ne [1 ]= src0 -> ne [0 ] /QK8_0 ; 2043weight_nb [0 ]= sizeof (int8_t ); 2044weight_nb [1 ]= weight_nb [0 ]* weight_ne [0 ]; 2045for (int i = 2 ;i < GGML_MAX_DIMS + 1 ;i ++ ) { 2046weight_ne [i ]= src0 -> ne [i - 1 ]; 2047weight_nb [i ]= weight_nb [i - 1 ]* weight_ne [i - 1 ]; 2048 } 2049scale_ne [0 ]= 1 ; 2050scale_ne [1 ]= src0 -> ne [0 ] /QK8_0 ; 2051scale_nb [0 ]= sizeof (uint16_t ); 2052scale_nb [1 ]= scale_nb [0 ]* scale_ne [0 ]; 2053for (int i = 2 ;i < GGML_MAX_DIMS + 1 ;i ++ ) { 2054scale_ne [i ]= src0 -> ne [i - 1 ]; 2055scale_nb [i ]= scale_nb [i - 1 ]* scale_ne [i - 1 ]; 2056 } 2057dequant_ne = weight_ne ; 2058dequant_nb [0 ]= ggml_type_size (dst -> type ); 2059for (int i = 1 ;i < GGML_MAX_DIMS + 1 ;i ++ ) { 2060dequant_nb [i ]= dequant_nb [i - 1 ]* dequant_ne [i - 1 ]; 2061 } 2062const int64_t scale_offset = ggml_nelements (src0 )* sizeof (int8_t ); 2063ggml_cann_pool_alloc dequant_allocator (ctx .pool (), 2064ggml_nelements (src0 )* ggml_type_size (dst -> type )); 2065acl_tensor_ptr acl_weight = ggml_cann_create_tensor (src0 -> data ,ACL_INT8 ,sizeof (int8_t ), 2066weight_ne ,weight_nb ,GGML_MAX_DIMS + 1 ); 2067acl_tensor_ptr acl_scale = ggml_cann_create_tensor ( 2068src0 -> data ,ACL_FLOAT16 ,sizeof (uint16_t ),scale_ne ,scale_nb , 2069GGML_MAX_DIMS + 1 ,ACL_FORMAT_ND ,scale_offset ); 2070acl_tensor_ptr acl_dequant = ggml_cann_create_tensor ( 2071dequant_allocator .get (),ggml_cann_type_mapping (dst -> type ), 2072ggml_type_size (dst -> type ),dequant_ne ,dequant_nb ,GGML_MAX_DIMS + 1 ); 2073aclnn_mul (ctx ,acl_weight .get (),acl_scale .get (),acl_dequant .get ()); 2074 2075// Reinterpret dequant buffer as 4D [src0->ne] with contiguous strides. 2076dequant_ne = src0 -> ne ; 2077dequant_nb [0 ]= ggml_type_size (dst -> type ); 2078for (int i = 1 ;i < GGML_MAX_DIMS ;i ++ ) { 2079dequant_nb [i ]= dequant_nb [i - 1 ]* src0 -> ne [i - 1 ]; 2080 } 2081gather_batched (dequant_allocator .get (), 2082ggml_cann_type_mapping (dst -> type ),ggml_type_size (dst -> type ), 2083dequant_nb ); 2084break ; 2085 } 2086default : 2087GGML_ABORT ("Unsupported tensor type for GGML_OP_GET_ROWS" ); 2088break ; 2089 } 2090} 2091 2092void ggml_cann_set_rows (ggml_backend_cann_context & ctx ,ggml_tensor * dst ) { 2093ggml_tensor * src0 = dst -> src [0 ];// source values 2094ggml_tensor * src1 = dst -> src [1 ];// row indices 2095 2096// n_idx: number of source rows to scatter per batch slice. 2097// ggml guarantees: src0->ne[1] == src1->ne[0]. 2098const int64_t n_idx = src1 -> ne [0 ]; 2099 2100// Copy n_idx rows of src [ne0, n_idx] into dst [ne0, ne1] at positions given by a 1D index. 2101// ggml_cann_create_tensor reverses dims, so ACL sees [ne1, ne0] for dst. 2102// InplaceIndexCopy with dim=0 copies along ACL dim-0 == ggml ne[1] (the row axis). 2103// src_nb: the 4 strides of the source buffer (nb[0..1] for the 2D slice shape, 2104// nb[2..3] for computing per-batch-slice base pointer offsets). 2105auto scatter_batched = [& ](void * src_base ,aclDataType acl_type ,size_t type_size , 2106const size_t * src_nb ) { 2107int64_t d_ne [2 ]= {dst -> ne [0 ],dst -> ne [1 ] }; 2108size_t d_nb [2 ]= {dst -> nb [0 ],dst -> nb [1 ] }; 2109int64_t s_ne [2 ]= {dst -> ne [0 ],n_idx }; 2110size_t s_nb_2d [2 ]= {src_nb [0 ],src_nb [1 ] }; 2111int64_t i_ne [1 ]= {n_idx }; 2112size_t i_nb [1 ]= { (size_t )ggml_element_size (src1 ) }; 2113 2114for (int64_t i3 = 0 ;i3 < dst -> ne [3 ];i3 ++ ) { 2115for (int64_t i2 = 0 ;i2 < dst -> ne [2 ];i2 ++ ) { 2116acl_tensor_ptr acl_dst = ggml_cann_create_tensor ( 2117 (char * )dst -> data + i3 * dst -> nb [3 ]+ i2 * dst -> nb [2 ], 2118acl_type ,type_size ,d_ne ,d_nb ,2 ); 2119acl_tensor_ptr acl_idx = ggml_cann_create_tensor ( 2120 (char * )src1 -> data + (i3 %src1 -> ne [2 ])* src1 -> nb [2 ]+ (i2 %src1 -> ne [1 ])* src1 -> nb [1 ], 2121ggml_cann_type_mapping (src1 -> type ), (size_t )ggml_element_size (src1 ), 2122i_ne ,i_nb ,1 ); 2123acl_tensor_ptr acl_src = ggml_cann_create_tensor ( 2124 (char * )src_base + i3 * src_nb [3 ]+ i2 * src_nb [2 ], 2125acl_type ,type_size ,s_ne ,s_nb_2d ,2 ); 2126GGML_CANN_CALL_ACLNN_OP (ctx ,InplaceIndexCopy ,acl_dst .get (),0 ,acl_idx .get (),acl_src .get ()); 2127 } 2128 } 2129 }; 2130 2131switch (dst -> type ) { 2132case GGML_TYPE_F32 : 2133scatter_batched (src0 -> data , 2134ggml_cann_type_mapping (dst -> type ),ggml_type_size (dst -> type ), 2135src0 -> nb ); 2136break ; 2137case GGML_TYPE_F16 : 2138case GGML_TYPE_BF16 : 2139 { 2140// Cast src0 (F32) to dst type first. 2141ggml_cann_pool_alloc src_cast_allocator (ctx .pool (), 2142ggml_nelements (src0 )* ggml_type_size (dst -> type )); 2143size_t src_cast_nb [GGML_MAX_DIMS ]; 2144src_cast_nb [0 ]= ggml_type_size (dst -> type ); 2145for (int i = 1 ;i < GGML_MAX_DIMS ;i ++ ) { 2146src_cast_nb [i ]= src_cast_nb [i - 1 ]* src0 -> ne [i - 1 ]; 2147 } 2148acl_tensor_ptr acl_src0 = ggml_cann_create_tensor (src0 ); 2149acl_tensor_ptr acl_src_cast = ggml_cann_create_tensor ( 2150src_cast_allocator .get (),ggml_cann_type_mapping (dst -> type ),ggml_type_size (dst -> type ), 2151src0 -> ne ,src_cast_nb ,GGML_MAX_DIMS ); 2152aclnn_cast (ctx ,acl_src0 .get (),acl_src_cast .get (),ggml_cann_type_mapping (dst -> type )); 2153 2154scatter_batched (src_cast_allocator .get (), 2155ggml_cann_type_mapping (dst -> type ),ggml_type_size (dst -> type ), 2156src_cast_nb ); 2157break ; 2158 } 2159default : 2160GGML_ABORT ("Unsupported tensor type for GGML_OP_SET_ROWS" ); 2161break ; 2162 } 2163} 2164 2165/** 2166* @brief Repeats elements of a tensor along a specified dimension. 2167* 2168* This function repeats each element of the source tensor `acl_src` a specified 2169* number of times (`repeats`) along the specified dimension `dim` and stores 2170* the result in the destination tensor `acl_dst`. 2171* 2172* @param ctx The context for the CANN backend operations. 2173* @param acl_src The source tensor whose elements will be repeated. 2174* @param acl_dst The destination tensor where the repeated elements will be 2175* stored. 2176* @param dim The dimension along which the elements will be repeated. 2177* @param repeats The number of times each element will be repeated. 2178* @param output_size The size of the output tensor. 2179*/ 2180static void aclnn_repeat_interleave (ggml_backend_cann_context & ctx , 2181aclTensor * acl_src , 2182aclTensor * acl_dst , 2183int64_t dim , 2184int64_t repeats , 2185int64_t output_size ) { 2186GGML_CANN_CALL_ACLNN_OP (ctx ,RepeatInterleaveIntWithDim ,acl_src ,repeats ,dim ,output_size ,acl_dst ); 2187} 2188 2189/** 2190* @brief Performs matrix multiplication with floating-point precision on 2191* tensors using the CANN backend. 2192* 2193* This function performs matrix multiplication of the input tensor and the 2194* weight tensor, handling broadcasting and transposing as needed, and stores 2195* the result in the destination tensor `dst`. 2196* 2197* @param ctx The context for the CANN backend operations. 2198* @param dst The destination tensor where the result of the matrix 2199* multiplication will be stored. 2200*/ 2201static void ggml_cann_mat_mul_fp (ggml_backend_cann_context & ctx ,ggml_tensor * dst ) { 2202ggml_tensor * weight = dst -> src [0 ];// weight 2203ggml_tensor * input = dst -> src [1 ];// input 2204 2205// when weight ne2 or ne3 is 1, aclnnMatmulGetWorkspaceSize will auto 2206// broadcast, when weight ne2 or ne3 is not 1, weight need repeat. 2207BCAST_MUL_MAT_SHAPE (input ,weight ,dst ); 2208 2209int64_t n_dims = bcast_dims ; 2210if (bcast_input_ne [3 ]== bcast_weight_ne [3 ]&& bcast_input_ne [3 ]== 1 ) { 2211if (bcast_input_ne [2 ]== 1 && bcast_weight_ne [2 ]== 1 ) { 2212n_dims = 2 ; 2213 }else if (bcast_input_ne [2 ]== 1 ) { 2214n_dims = 3 ; 2215 } 2216 } 2217 2218acl_tensor_ptr acl_input_tensor = ggml_cann_create_tensor (input ,bcast_input_ne ,bcast_input_nb ,n_dims ); 2219int64_t transpose_ne []= {bcast_weight_ne [1 ],bcast_weight_ne [0 ],bcast_weight_ne [2 ], 2220bcast_weight_ne [3 ],bcast_weight_ne [4 ],bcast_weight_ne [5 ] }; 2221size_t transpose_nb []= {bcast_weight_nb [1 ],bcast_weight_nb [0 ],bcast_weight_nb [2 ], 2222bcast_weight_nb [3 ],bcast_weight_nb [4 ],bcast_weight_nb [5 ] }; 2223acl_tensor_ptr acl_weight_tensor ; 2224 2225// Only check env once. 2226static bool weight_to_nz = parse_bool (get_env_as_lowercase ("GGML_CANN_WEIGHT_NZ" ).value_or ("on" )); 2227if (weight_to_nz && weight -> type != GGML_TYPE_BF16 && is_matmul_weight (weight )) { 2228acl_weight_tensor = ggml_cann_create_tensor (weight ,transpose_ne ,transpose_nb ,n_dims ,ACL_FORMAT_FRACTAL_NZ ); 2229 }else { 2230acl_weight_tensor = ggml_cann_create_tensor (weight ,transpose_ne ,transpose_nb ,n_dims ,ACL_FORMAT_ND ); 2231 } 2232acl_tensor_ptr acl_dst = ggml_cann_create_tensor (dst ,bcast_dst_ne ,bcast_dst_nb ,n_dims ); 2233 2234switch (n_dims ) { 2235case 2 : 2236GGML_CANN_CALL_ACLNN_OP (ctx ,Mm ,acl_input_tensor .get (),acl_weight_tensor .get (),acl_dst .get (),2 ); 2237break ; 2238case 3 : 2239GGML_CANN_CALL_ACLNN_OP (ctx ,BatchMatMul ,acl_input_tensor .get (),acl_weight_tensor .get (),acl_dst .get (), 22402 ); 2241break ; 2242default : 2243// ALLOW_FP32_DOWN_PRECISION, when input is 2244// fp32, atlas a2 will transpose it to HFLOAT32. 2245GGML_CANN_CALL_ACLNN_OP (ctx ,Matmul ,acl_input_tensor .get (),acl_weight_tensor .get (),acl_dst .get (),1 ); 2246break ; 2247 } 2248} 2249 2250/** 2251* @brief Performs matrix multiplication with quantized weights and 2252* floating-point inputs using the CANN backend. 2253* 2254* This function performs matrix multiplication of the input tensor `src1` and 2255* the weight tensor `src0`, handling broadcasting, transposing, and 2256* quantization as needed, and stores the result in the destination tensor 2257* `dst`. 2258* 2259* @param ctx The context for the CANN backend operations. 2260* @param dst The destination tensor where the result of the matrix 2261* multiplication will be stored. 2262*/ 2263static void ggml_cann_mul_mat_quant (ggml_backend_cann_context & ctx ,ggml_tensor * dst ,const enum ggml_type type ) { 2264ggml_tensor * src0 = dst -> src [0 ];// weight 2265ggml_tensor * src1 = dst -> src [1 ];// input 2266 2267// The shape of the weight is NCHW. 2268// Matrix multiplication uses HW dims. 2269// HC is regarded as batch. 2270// weight need transpose. 2271float weight_elem_size ; 2272if (type == GGML_TYPE_Q4_0 ) { 2273weight_elem_size = float (sizeof (uint8_t )) /2 ; 2274 }else if (type == GGML_TYPE_Q8_0 ) { 2275weight_elem_size = float (sizeof (uint8_t )); 2276 }else { 2277GGML_ABORT ("Only support Q4_0 and Q8_0 MUL_MAT" ); 2278 } 2279float weight_nb []= {src0 -> ne [0 ]* weight_elem_size ,weight_elem_size }; 2280size_t weight_stride = src0 -> ne [1 ]* src0 -> ne [0 ]* weight_elem_size ; 2281size_t weight_size = weight_stride * src0 -> ne [2 ]* src0 -> ne [3 ]; 2282 2283// scale stored at the end of weight. Also need transpose. 2284size_t scale_elem_size = sizeof (uint16_t ); 2285size_t scale_nb []= {src0 -> ne [0 ] /QK8_0 * scale_elem_size ,scale_elem_size }; 2286size_t scale_stride = src0 -> ne [1 ]* src0 -> ne [0 ] /QK8_0 * scale_elem_size ; 2287char * scale_offset = (char * )src0 -> data + weight_size ; 2288 2289// input 2290size_t input_elem_size = sizeof (uint16_t ); 2291int64_t input_ne []= {src1 -> ne [0 ],src1 -> ne [1 ] }; 2292size_t input_nb []= {input_elem_size ,input_ne [0 ]* input_elem_size }; 2293size_t input_stride = input_ne [0 ]* input_ne [1 ]* input_elem_size ; 2294ggml_cann_pool_alloc input_alloctor (ctx .pool ()); 2295void * input_buffer = src1 -> data ; 2296 2297// case in 2298if (src1 -> type != GGML_TYPE_F16 ) { 2299acl_tensor_ptr acl_src1_tensor = ggml_cann_create_tensor (src1 ); 2300input_buffer = input_alloctor .alloc (ggml_nelements (src1 )* input_elem_size ); 2301 2302int64_t * input_cast_ne = src1 -> ne ; 2303size_t input_cast_nb [GGML_MAX_DIMS ]; 2304input_cast_nb [0 ]= sizeof (uint16_t ); 2305for (int i = 1 ;i < GGML_MAX_DIMS ;i ++ ) { 2306input_cast_nb [i ]= input_cast_nb [i - 1 ]* input_cast_ne [i - 1 ]; 2307 } 2308 2309acl_tensor_ptr acl_input_tensor = ggml_cann_create_tensor (input_buffer ,ACL_FLOAT16 ,input_elem_size , 2310input_cast_ne ,input_cast_nb ,GGML_MAX_DIMS ); 2311aclnn_cast (ctx ,acl_src1_tensor .get (),acl_input_tensor .get (),ACL_FLOAT16 ); 2312 } 2313 2314// output 2315size_t output_elem_size = sizeof (uint16_t ); 2316size_t output_nb []= {output_elem_size ,dst -> ne [0 ]* output_elem_size }; 2317ggml_cann_pool_alloc output_allocator (ctx .pool ()); 2318void * output_buffer = output_allocator .alloc (ggml_nelements (dst )* output_elem_size ); 2319size_t output_stride = dst -> ne [0 ]* dst -> ne [1 ]* output_elem_size ; 2320 2321// aclnn 2322int64_t max_elem_size = 65535 ; 2323int64_t split_size = (src0 -> ne [1 ] /max_elem_size )+ 1 ; 2324ggml_cann_pool_alloc workspace_allocator (ctx .pool ()); 2325for (int64_t n1 = 0 ;n1 < src1 -> ne [3 ];n1 ++ ) { 2326for (int64_t c1 = 0 ;c1 < src1 -> ne [2 ];c1 ++ ) { 2327int64_t n0 = n1 / (src1 -> ne [3 ] /src0 -> ne [3 ]); 2328int64_t c0 = c1 / (src1 -> ne [2 ] /src0 -> ne [2 ]); 2329 2330int64_t batch1 = (n1 * src1 -> ne [2 ])+ c1 ; 2331int64_t batch0 = (n0 * src0 -> ne [2 ])+ c0 ; 2332 2333acl_tensor_ptr acl_input_tensor = ggml_cann_create_tensor ( 2334 (char * )input_buffer + batch1 * input_stride ,ACL_FLOAT16 ,input_elem_size ,input_ne ,input_nb ,2 ); 2335 2336// first split 2337int64_t weight_ne_offset = 0 ; 2338int64_t weight_ne [2 ]= {max_elem_size > src0 -> ne [1 ] ?src0 -> ne [1 ] :max_elem_size ,src0 -> ne [0 ] }; 2339int64_t scale_ne_offset = 0 ; 2340int64_t scale_ne [2 ]= {weight_ne [0 ],weight_ne [1 ] /QK8_0 }; 2341int64_t output_ne_offset = 0 ; 2342int64_t output_ne [2 ]= {weight_ne [0 ],dst -> ne [1 ] }; 2343 2344acl_tensor_ptr acl_weight_tensor = 2345ggml_cann_create_tensor ((char * )src0 -> data + batch0 * weight_stride ,ggml_cann_type_mapping (type ), 2346weight_elem_size ,weight_ne ,weight_nb ,2 ,ACL_FORMAT_ND ,weight_ne_offset ); 2347acl_tensor_ptr acl_scale_tensor = 2348ggml_cann_create_tensor (scale_offset + batch0 * scale_stride ,ACL_FLOAT16 ,scale_elem_size ,scale_ne , 2349scale_nb ,2 ,ACL_FORMAT_ND ,scale_ne_offset ); 2350acl_tensor_ptr acl_output_tensor = 2351ggml_cann_create_tensor ((char * )output_buffer + batch1 * output_stride ,ACL_FLOAT16 ,output_elem_size , 2352output_ne ,output_nb ,2 ,ACL_FORMAT_ND ,output_ne_offset ); 2353int64_t antiquantGroupSize = 0 ; 2354if (src0 -> ne [0 ]> QK8_0 ) { 2355antiquantGroupSize = QK8_0 ; 2356 } 2357GGML_CANN_CALL_ACLNN_OP (ctx ,WeightQuantBatchMatmulV2 ,acl_input_tensor .get (),acl_weight_tensor .get (), 2358acl_scale_tensor .get (),nullptr ,nullptr ,nullptr ,nullptr ,antiquantGroupSize , 2359acl_output_tensor .get ()); 2360 2361// other splits 2362for (int64_t split = 1 ;split < split_size ;split ++ ) { 2363weight_ne_offset += weight_elem_size * weight_ne [0 ]* weight_ne [1 ]; 2364weight_ne [0 ]= 2365max_elem_size * (split + 1 )> src0 -> ne [1 ] ?src0 -> ne [1 ]- (max_elem_size * split ) :max_elem_size ; 2366scale_ne_offset += scale_elem_size * scale_ne [0 ]* scale_ne [1 ]; 2367scale_ne [0 ]= weight_ne [0 ]; 2368output_ne_offset += output_elem_size * output_ne [0 ]* output_ne [1 ]; 2369output_ne [0 ]= weight_ne [0 ]; 2370 2371acl_weight_tensor = 2372ggml_cann_create_tensor ((char * )src0 -> data + batch0 * weight_stride ,ggml_cann_type_mapping (type ), 2373weight_elem_size ,weight_ne ,weight_nb ,2 ,ACL_FORMAT_ND ,weight_ne_offset ); 2374acl_scale_tensor = 2375ggml_cann_create_tensor (scale_offset + batch0 * scale_stride ,ACL_FLOAT16 ,scale_elem_size , 2376scale_ne ,scale_nb ,2 ,ACL_FORMAT_ND ,scale_ne_offset ); 2377acl_output_tensor = 2378ggml_cann_create_tensor ((char * )output_buffer + batch1 * output_stride ,ACL_FLOAT16 , 2379output_elem_size ,output_ne ,output_nb ,2 ,ACL_FORMAT_ND ,output_ne_offset ); 2380GGML_CANN_CALL_ACLNN_OP (ctx ,WeightQuantBatchMatmulV2 ,acl_input_tensor .get (),acl_weight_tensor .get (), 2381acl_scale_tensor .get (),nullptr ,nullptr ,nullptr ,nullptr ,antiquantGroupSize , 2382acl_output_tensor .get ()); 2383 } 2384 } 2385 } 2386 2387// cast out 2388if (dst -> type != GGML_TYPE_F16 ) { 2389int64_t * output_cast_ne = dst -> ne ; 2390size_t output_cast_nb [GGML_MAX_DIMS ]; 2391output_cast_nb [0 ]= sizeof (uint16_t ); 2392for (int i = 1 ;i < GGML_MAX_DIMS ;i ++ ) { 2393output_cast_nb [i ]= output_cast_nb [i - 1 ]* output_cast_ne [i - 1 ]; 2394 } 2395 2396acl_tensor_ptr acl_output_tensor = ggml_cann_create_tensor (output_buffer ,ACL_FLOAT16 ,output_elem_size , 2397output_cast_ne ,output_cast_nb ,GGML_MAX_DIMS ); 2398acl_tensor_ptr acl_dst_tensor = ggml_cann_create_tensor (dst ); 2399aclnn_cast (ctx ,acl_output_tensor .get (),acl_dst_tensor .get (),ggml_cann_type_mapping (dst -> type )); 2400 } 2401} 2402 2403void ggml_cann_mul_mat (ggml_backend_cann_context & ctx ,ggml_tensor * dst ) { 2404const enum ggml_type type = dst -> src [0 ]-> type ; 2405switch (type ) { 2406case GGML_TYPE_F32 : 2407case GGML_TYPE_F16 : 2408#ifndef ASCEND_310P 2409case GGML_TYPE_BF16 : 2410#endif 2411ggml_cann_mat_mul_fp (ctx ,dst ); 2412break ; 2413case GGML_TYPE_Q4_0 : 2414case GGML_TYPE_Q8_0 : 2415ggml_cann_mul_mat_quant (ctx ,dst ,type ); 2416break ; 2417default : 2418GGML_ABORT ("Unsupported type for mul_mat" ); 2419break ; 2420 } 2421} 2422 2423/** 2424* @brief Rolls the elements of a tensor along a specified dimension. 2425* 2426* This function rolls the elements of the source tensor `acl_src` by the 2427* specified shifts `shifts` along the specified dimensions `dims`, and stores 2428* the result in the destination tensor `acl_dst`. 2429* 2430* @param ctx The context for the CANN backend operations. 2431* @param acl_src The source tensor whose elements will be rolled. 2432* @param acl_dst The destination tensor where the rolled elements will be 2433* stored. 2434* @param shifts An array specifying the number of positions by which elements 2435* are shifted. 2436* @param dims An array specifying the dimensions along which elements are 2437* shifted. 2438*/ 2439static void aclnn_roll (ggml_backend_cann_context & ctx , 2440aclTensor * acl_src , 2441aclTensor * acl_dst , 2442int64_t * shifts , 2443int64_t * dims ) { 2444acl_int_array_ptr acl_shifts = ggml_cann_create_int_array (shifts ,1 ); 2445acl_int_array_ptr acl_dims = ggml_cann_create_int_array (dims ,1 ); 2446GGML_CANN_CALL_ACLNN_OP (ctx ,Roll ,acl_src ,acl_shifts .get (),acl_dims .get (),acl_dst ); 2447} 2448 2449/** 2450* @brief Fills specified positions of a tensor with a scalar value. 2451* 2452* This function fills the positions in the source tensor `acl_src` specified by 2453* `index` along the dimension `dim` with the scalar value `value`. 2454* 2455* @param ctx The context for the CANN backend operations. 2456* @param acl_src The source tensor where the positions will be filled. 2457* @param dim The dimension along which the positions are specified. 2458* @param index An array specifying the positions to be filled. 2459* @param index_num The number of positions specified in the index array. 2460* @param value The scalar value used to fill the specified positions. 2461*/ 2462static void aclnn_index_fill_tensor (ggml_backend_cann_context & ctx , 2463aclTensor * acl_src , 2464int64_t dim , 2465int64_t * index , 2466int64_t index_num , 2467float value ) { 2468acl_int_array_ptr acl_index = ggml_cann_create_int_array (index ,index_num ); 2469acl_scalar_ptr acl_value = ggml_cann_create_scalar (& value , aclDataType::ACL_FLOAT ); 2470GGML_CANN_CALL_ACLNN_OP (ctx ,InplaceIndexFillTensor ,acl_src ,dim ,acl_index .get (),acl_value .get ()); 2471} 2472 2473/** 2474* @brief Initializes and caches all intermediate tensors required for RoPE 2475* (Rotary Position Embedding), including support for Yarn, mRoPE, 2476* i-mRoPE, Neox repeat strategy, independent sectors, frequency factors, 2477* and multi-section rotary groups. 2478* 2479* This function computes and caches the per-dimension θ coefficients used for 2480* Q/K rotary embedding. The cache is shared across layers, and recomputed only 2481* when any dependent parameter changes. 2482* 2483* The function now supports: 2484* - Yarn RoPE extrapolation (via @param corr_dims and @param ext_factor) 2485* - Per-dimension independent sector exponent rules (indep_sects + sections[]) 2486* - Multi-section RoPE (mRoPE) index mapping (mrope_used + is_imrope) 2487* - Frequency factor division (src2) 2488* - Neox / normal repeat expansion modes 2489* 2490* @param ctx CANN backend context, containing memory pool, 2491* cached buffers, and runtime stream. 2492* @param dst Destination ggml_tensor whose computation 2493* depends on RoPE (typically Qcur or Kcur). 2494* @param corr_dims [low, high] Yarn correction range. 2495* @param ext_factor Yarn extrapolation strength. 0 = disabled. 2496* @param theta_scale Base multiplier for per-dimension θ exponent. 2497* @param freq_scale Global frequency scaling factor. 2498* @param attn_factor Optional scaling applied to sin/cos (if needed). 2499* @param is_neox Whether to use Neox-style dimension interleave. 2500* @param sections 4-way sector sizes for independent-section RoPE 2501* and multi-section mRoPE (t/h/w/e). 2502* @param mrope_used Whether to enable multi-section rotary embedding. 2503* @param is_imrope Whether to apply interleaved mRoPE rules. 2504* @param indep_sects Whether each dimension runs independent exponent 2505* resets based on @p sections. 2506*/ 2507static void aclnn_rope_cache_init (ggml_backend_cann_context & ctx , 2508ggml_tensor * dst , 2509float * corr_dims , 2510float ext_factor , 2511float theta_scale , 2512float freq_scale , 2513float attn_factor , 2514bool is_neox , 2515int sections [4 ], 2516bool mrope_used , 2517bool is_imrope , 2518bool indep_sects , 2519int64_t rope_dims ) { 2520ggml_tensor * src1 = dst -> src [1 ];// position 2521ggml_tensor * src2 = dst -> src [2 ];// freq_factors 2522 2523int64_t theta_scale_length = rope_dims /2 ; 2524int64_t position_length = dst -> ne [2 ]; 2525 2526// TODO: check theta_scale_length and position_length. 2527if (src2 == nullptr && ctx .rope_cache .cached && 2528ctx .rope_cache .equal (theta_scale_length ,position_length ,ext_factor ,theta_scale ,freq_scale ,attn_factor , 2529is_neox ,indep_sects ,mrope_used ,is_imrope ,sections )) { 2530// use cache. 2531return ; 2532 } 2533 2534// Step0: calculate tensor shape. 2535int64_t theta_scale_ne []= {theta_scale_length ,1 ,1 ,1 }; 2536size_t theta_scale_nb []= {sizeof (float ),theta_scale_length * sizeof (float ),theta_scale_length * sizeof (float ), 2537theta_scale_length * sizeof (float ) }; 2538 2539GGML_ASSERT (src1 -> type == GGML_TYPE_I32 ); 2540int64_t position_ne []= {1 ,1 ,position_length ,1 }; 2541size_t position_nb []= {sizeof (int32_t ),sizeof (int32_t ),sizeof (int32_t ),sizeof (int32_t )* position_length }; 2542 2543int64_t cache_ne []= {theta_scale_length ,1 ,position_length ,1 }; 2544size_t cache_nb [GGML_MAX_DIMS ]; 2545cache_nb [0 ]= sizeof (float ); 2546for (int i = 1 ;i < GGML_MAX_DIMS ;i ++ ) { 2547cache_nb [i ]= cache_nb [i - 1 ]* cache_ne [i - 1 ]; 2548 } 2549 2550// Step1: Compute the coefficient of theta. During the cache_init process, aside from 2551// (1) multiplying by the position, 2552// (2) dividing by freq_factors, 2553// (3) computing the sine and cosine, 2554// the other parameters used in the computation generally do not change in most scenarios. 2555// Therefore, we can first compute this part of the result and then cache it. 2556 2557// Step1.1: prepare theta_scale exponent. if this exponent updated, should update theta_scale_tensor. 2558acl_tensor_ptr acl_theta_scale_tensor ; 2559bool theta_scale_updated = false; 2560if (ctx .rope_cache .theta_scale_length != theta_scale_length || ctx .rope_cache .theta_scale != theta_scale || 2561ctx .rope_cache .indep_sects != indep_sects ) { 2562theta_scale_updated = true; 2563if (ctx .rope_cache .theta_scale_exp_host != nullptr ) { 2564free (ctx .rope_cache .theta_scale_exp_host ); 2565 } 2566ctx .rope_cache .theta_scale_exp_host = (float * )malloc (theta_scale_length * sizeof (float )); 2567GGML_ASSERT (ctx .rope_cache .theta_scale_exp_host != nullptr ); 2568if (!indep_sects ) { 2569ctx .rope_cache .theta_scale_exp_host [0 ]= 1 ; 2570for (int i = 1 ;i < theta_scale_length ;i ++ ) { 2571ctx .rope_cache .theta_scale_exp_host [i ]= ctx .rope_cache .theta_scale_exp_host [i - 1 ]* theta_scale ; 2572 } 2573 }else { 2574int sect_dims = sections [0 ]+ sections [1 ]+ sections [2 ]+ sections [3 ]; 2575int sec_w = sections [1 ]+ sections [0 ]; 2576int sec_e = sections [2 ]+ sec_w ; 2577 2578ctx .rope_cache .theta_scale_exp_host [0 ]= 1 ; 2579for (int i = 1 ;i < theta_scale_length ;i ++ ) { 2580int sector = i %sect_dims ; 2581if (sector == 0 || sector == sections [0 ]|| sector == sec_w || sector == sec_e ) { 2582ctx .rope_cache .theta_scale_exp_host [i ]= 1 ; 2583continue ; 2584 } 2585ctx .rope_cache .theta_scale_exp_host [i ]= ctx .rope_cache .theta_scale_exp_host [i - 1 ]* theta_scale ; 2586 } 2587 } 2588 2589if (ctx .rope_cache .theta_scale_cache != nullptr ) { 2590ACL_CHECK (aclrtFree (ctx .rope_cache .theta_scale_cache )); 2591 } 2592ACL_CHECK (aclrtMalloc (& ctx .rope_cache .theta_scale_cache ,theta_scale_length * sizeof (float ), 2593ACL_MEM_MALLOC_HUGE_FIRST )); 2594 2595ACL_CHECK (aclrtMemcpyAsync (ctx .rope_cache .theta_scale_cache ,theta_scale_length * sizeof (float ), 2596ctx .rope_cache .theta_scale_exp_host ,theta_scale_length * sizeof (float ), 2597ACL_MEMCPY_HOST_TO_DEVICE ,ctx .stream ())); 2598 } 2599acl_theta_scale_tensor = ggml_cann_create_tensor (ctx .rope_cache .theta_scale_cache ,ACL_FLOAT ,sizeof (float ), 2600theta_scale_ne ,theta_scale_nb ,1 ); 2601 2602// Step1.2: prepare rope_yarn_ramp, if this part updated, should update theta_scale_tensor. 2603// TODO: acl_yarn_ramp_tensor use rope cache. 2604bool yarn_ramp_tensor_updated = false; 2605acl_tensor_ptr acl_yarn_ramp_tensor ; 2606if (ext_factor != 0 && (theta_scale_updated || ctx .rope_cache .theta_scale_length != theta_scale_length || 2607ctx .rope_cache .freq_scale != freq_scale )) { 2608yarn_ramp_tensor_updated = true; 2609if (ctx .rope_cache .yarn_ramp_cache != nullptr ) { 2610ACL_CHECK (aclrtFree (ctx .rope_cache .yarn_ramp_cache )); 2611 } 2612ACL_CHECK (aclrtMalloc (& ctx .rope_cache .yarn_ramp_cache ,theta_scale_length * sizeof (float ), 2613ACL_MEM_MALLOC_HUGE_FIRST )); 2614// -rope_yarn_ramp 2615// const float y = (i0 / 2 - low) / MAX(0.001f, high - low); 2616// return MIN(1, MAX(0, y)) - 1; 2617acl_yarn_ramp_tensor = ggml_cann_create_tensor (ctx .rope_cache .yarn_ramp_cache ,ACL_FLOAT ,sizeof (float ), 2618theta_scale_ne ,theta_scale_nb ,1 ); 2619float zero_value = 0 ,one_value = 1 ; 2620float denom_safe_value = MAX (0.001f ,corr_dims [1 ]- corr_dims [0 ]); 2621acl_scalar_ptr low = ggml_cann_create_scalar (& corr_dims [0 ], aclDataType::ACL_FLOAT ); 2622acl_scalar_ptr zero = ggml_cann_create_scalar (& zero_value , aclDataType::ACL_FLOAT ); 2623acl_scalar_ptr one = ggml_cann_create_scalar (& one_value , aclDataType::ACL_FLOAT ); 2624acl_scalar_ptr denom_safe = ggml_cann_create_scalar (& denom_safe_value , aclDataType::ACL_FLOAT ); 2625acl_scalar_ptr ext_factor_sc = ggml_cann_create_scalar (& ext_factor , aclDataType::ACL_FLOAT ); 2626 2627aclnn_arange (ctx ,acl_yarn_ramp_tensor .get (),0 ,theta_scale_length ,1 ,theta_scale_length ); 2628GGML_CANN_CALL_ACLNN_OP (ctx ,InplaceSubs ,acl_yarn_ramp_tensor .get (),low .get (),one .get ()); 2629GGML_CANN_CALL_ACLNN_OP (ctx ,InplaceDivs ,acl_yarn_ramp_tensor .get (),denom_safe .get ()); 2630GGML_CANN_CALL_ACLNN_OP (ctx ,InplaceThreshold ,acl_yarn_ramp_tensor .get (),zero .get (),zero .get ()); 2631GGML_CANN_CALL_ACLNN_OP (ctx ,InplaceClampMax ,acl_yarn_ramp_tensor .get (),one .get ()); 2632GGML_CANN_CALL_ACLNN_OP (ctx ,InplaceSubs ,acl_yarn_ramp_tensor .get (),one .get (),one .get ()); 2633GGML_CANN_CALL_ACLNN_OP (ctx ,InplaceMuls ,acl_yarn_ramp_tensor .get (),ext_factor_sc .get ()); 2634 2635// theta_interp = freq_scale * theta_extrap; 2636// theta = theta_interp * (1 - ramp_mix) + theta_extrap * ramp_mix; 2637// theta = freq_scale * theta_extrap * (1 - ramp_mix) + theta_extrap * ramp_mix; 2638// theta = freq_scale * theta_extrap - freq_scale * theta_extrap * ramp_mix + theta_extrap * ramp_mix; 2639// theta = theta_extrap * (freq_scale - freq_scale * ramp_mix + ramp_mix); 2640// 2641// we cache (freq_scale - freq_scale * ramp_mix + ramp_mix), Considering that the rope_yarn_ramp here is the inverse 2642// cache freq_scale + (freq_scale - 1) * ramp_mix 2643float freq_scale_1 = freq_scale - 1 ; 2644acl_scalar_ptr freq_scale_sc = ggml_cann_create_scalar (& freq_scale , aclDataType::ACL_FLOAT ); 2645acl_scalar_ptr freq_scale_1_sc = ggml_cann_create_scalar (& freq_scale_1 , aclDataType::ACL_FLOAT ); 2646GGML_CANN_CALL_ACLNN_OP (ctx ,InplaceMuls ,acl_yarn_ramp_tensor .get (),freq_scale_1_sc .get ()); 2647GGML_CANN_CALL_ACLNN_OP (ctx ,InplaceAdds ,acl_yarn_ramp_tensor .get (),freq_scale_sc .get (),one .get ()); 2648 }else { 2649acl_yarn_ramp_tensor = ggml_cann_create_tensor (ctx .rope_cache .yarn_ramp_cache ,ACL_FLOAT ,sizeof (float ), 2650theta_scale_ne ,theta_scale_nb ,1 ); 2651 } 2652// Step 1.3: update theta_scale_tensor according to ext_factor or freq_scale. 2653if (ext_factor != 0 ) { 2654if (theta_scale_updated || yarn_ramp_tensor_updated ) { 2655theta_scale_updated = true; 2656aclnn_mul (ctx ,acl_theta_scale_tensor .get (),acl_yarn_ramp_tensor .get ()); 2657 } 2658 }else { 2659if (freq_scale != 1 && (ctx .rope_cache .freq_scale != freq_scale || theta_scale_updated )) { 2660theta_scale_updated = true; 2661aclnn_muls (ctx ,acl_theta_scale_tensor .get (),freq_scale ,nullptr , true); 2662 } 2663 } 2664 2665// Nothing changed, use cache. 2666if (!theta_scale_updated ) { 2667acl_theta_scale_tensor = ggml_cann_create_tensor (ctx .rope_cache .theta_scale_cache ,ACL_FLOAT ,sizeof (float ), 2668theta_scale_ne ,theta_scale_nb ,GGML_MAX_DIMS ); 2669 } 2670 2671// Step 1.4: prepare select index if mrope 2672acl_tensor_ptr position_select_index_tensor ; 2673if (mrope_used ) { 2674if (ctx .rope_cache .sections [0 ]!= sections [0 ]|| ctx .rope_cache .sections [1 ]!= sections [1 ]|| 2675ctx .rope_cache .sections [2 ]!= sections [2 ]|| ctx .rope_cache .sections [3 ]!= sections [3 ]|| 2676ctx .rope_cache .theta_scale_length != theta_scale_length || ctx .rope_cache .is_imrope != is_imrope ) { 2677if (ctx .rope_cache .position_select_index_host != nullptr ) { 2678free (ctx .rope_cache .position_select_index_host ); 2679 } 2680ctx .rope_cache .position_select_index_host = (int * )malloc (theta_scale_length * sizeof (int )); 2681GGML_ASSERT (ctx .rope_cache .position_select_index_host != nullptr ); 2682int sect_dims = sections [0 ]+ sections [1 ]+ sections [2 ]+ sections [3 ]; 2683int sec_w = sections [1 ]+ sections [0 ]; 2684int sec_e = sections [2 ]+ sec_w ; 2685// t,h,w,e 2686for (int i = 0 ;i < theta_scale_length ;i ++ ) { 2687int sector = i %sect_dims ; 2688 2689if (is_imrope ) {// qwen3vl apply interleaved mrope 2690if (sector %3 == 1 && sector < 3 * sections [1 ]) { 2691ctx .rope_cache .position_select_index_host [i ]= 1 ; 2692 }else if (sector %3 == 2 && sector < 3 * sections [2 ]) { 2693ctx .rope_cache .position_select_index_host [i ]= 2 ; 2694 }else if (sector %3 == 0 && sector < 3 * sections [0 ]) { 2695ctx .rope_cache .position_select_index_host [i ]= 0 ; 2696 }else { 2697ctx .rope_cache .position_select_index_host [i ]= 3 ; 2698 } 2699 }else { 2700if (sector >=sections [0 ]&& sector < sec_w ) { 2701ctx .rope_cache .position_select_index_host [i ]= 1 ; 2702 }else if (sector >=sec_w && sector < sec_e ) { 2703ctx .rope_cache .position_select_index_host [i ]= 2 ; 2704 }else if (sector >=sec_e ) { 2705ctx .rope_cache .position_select_index_host [i ]= 3 ; 2706 }else { 2707ctx .rope_cache .position_select_index_host [i ]= 0 ; 2708 } 2709 } 2710 } 2711 2712if (ctx .rope_cache .position_select_index != nullptr ) { 2713ACL_CHECK (aclrtFree (ctx .rope_cache .position_select_index )); 2714 } 2715ACL_CHECK (aclrtMalloc (& ctx .rope_cache .position_select_index ,theta_scale_length * sizeof (int ), 2716ACL_MEM_MALLOC_HUGE_FIRST )); 2717 2718ACL_CHECK (aclrtMemcpyAsync (ctx .rope_cache .position_select_index ,theta_scale_length * sizeof (int ), 2719ctx .rope_cache .position_select_index_host ,theta_scale_length * sizeof (int ), 2720ACL_MEMCPY_HOST_TO_DEVICE ,ctx .stream ())); 2721 } 2722 2723position_select_index_tensor = ggml_cann_create_tensor (ctx .rope_cache .position_select_index ,ACL_INT32 , 2724sizeof (int ),theta_scale_ne ,theta_scale_nb ,1 ); 2725 } 2726 2727// Step2: divide by freq_factors 2728ggml_cann_pool_alloc freq_fac_res_allocator (ctx .pool ()); 2729if (src2 ) { 2730freq_fac_res_allocator .alloc (theta_scale_length * sizeof (float )); 2731void * freq_fac_res_ptr = freq_fac_res_allocator .get (); 2732acl_tensor_ptr acl_freq_factors_tensor = 2733ggml_cann_create_tensor (src2 -> data ,ggml_cann_type_mapping (src2 -> type ),ggml_type_size (src2 -> type ), 2734theta_scale_ne ,theta_scale_nb ,GGML_MAX_DIMS ); 2735acl_tensor_ptr acl_freq_fac_res_tensor = ggml_cann_create_tensor (freq_fac_res_ptr ,ACL_FLOAT ,sizeof (float ), 2736theta_scale_ne ,theta_scale_nb ,GGML_MAX_DIMS ); 2737aclnn_div (ctx ,acl_theta_scale_tensor .get (),acl_freq_factors_tensor .get (),acl_freq_fac_res_tensor .get ()); 2738 std::swap (acl_theta_scale_tensor ,acl_freq_fac_res_tensor ); 2739 } 2740 2741// Step3: prepare position_tensor 2742acl_tensor_ptr acl_position_tensor ; 2743ggml_cann_pool_alloc mrope_position_acllocator (ctx .pool ()); 2744if (mrope_used ) { 2745// Step3.1: select current position; 2746// position : 2747// pos1: [[0, 1 ,2 ,3 ], 2748// pos2: [4, 5 ,6 ,7 ], 2749// pos3: [8, 9 ,10,11], 2750// pos4: [12,13,14,15] ] 2751// 2752// select index = [0, 1, 2, 2, 1, 0] 2753// 2754// selected_tensor: 2755// [[0, 1 ,2 ,3 ], 2756// [4, 5 ,6 ,7 ], 2757// [8, 9 ,10,11], 2758// [8, 9 ,10,11], 2759// [4, 5 ,6 ,7 ], 2760// [0, 1 ,2 ,3 ]] 2761// 2762// transpose, from [seq_len:dims] to [dims:seq_len] 2763// [0, 4, 8 ,8 ,4, 0], 2764// [1, 5, 9, 9, 5, 1], 2765// [2, 6, 10,10,6 ,2], 2766// [3, 7, 11,11,7 3 ]] 2767// 2768// multipy by theta_scale_tensor 2769// [theta_scale^0, theta_scale^1, ..., theta_scale ^ n] 2770 2771int64_t mrope_position_ne []= {position_length ,4 }; 2772size_t mrope_position_nb []= {sizeof (int ),position_length * sizeof (int ) }; 2773acl_tensor_ptr mrope_position = 2774ggml_cann_create_tensor (src1 -> data ,ggml_cann_type_mapping (src1 -> type ),ggml_type_size (src1 -> type ), 2775mrope_position_ne ,mrope_position_nb ,2 ); 2776 2777// selected position tensor's shape is a transpose of cache tensor. 2778int64_t selected_position_ne []= {position_length ,theta_scale_length }; 2779size_t selected_position_nb []= {sizeof (float ),position_length * sizeof (float ) }; 2780mrope_position_acllocator .alloc (theta_scale_length * position_length * sizeof (float )); 2781void * mrope_position_buffer = mrope_position_acllocator .get (); 2782acl_position_tensor = 2783ggml_cann_create_tensor (mrope_position_buffer ,ggml_cann_type_mapping (src1 -> type ), 2784ggml_type_size (src1 -> type ),selected_position_ne ,selected_position_nb ,2 ); 2785GGML_CANN_CALL_ACLNN_OP (ctx ,IndexSelect ,mrope_position .get (),0 ,position_select_index_tensor .get (), 2786acl_position_tensor .get ()); 2787 2788// transpose 2789int64_t transposed_ne []= {position_length ,1 ,theta_scale_length ,1 }; 2790size_t transposed_nb [GGML_MAX_DIMS ]; 2791transposed_nb [0 ]= sizeof (float ); 2792for (int i = 1 ;i < GGML_MAX_DIMS ;i ++ ) { 2793transposed_nb [i ]= transposed_nb [i - 1 ]* transposed_ne [i - 1 ]; 2794 } 2795 2796 std::swap (transposed_ne [0 ],transposed_ne [2 ]); 2797 std::swap (transposed_nb [0 ],transposed_nb [2 ]); 2798 2799acl_position_tensor = 2800ggml_cann_create_tensor (mrope_position_buffer ,ggml_cann_type_mapping (src1 -> type ), 2801ggml_type_size (src1 -> type ),transposed_ne ,transposed_nb ,GGML_MAX_DIMS ); 2802 2803 }else { 2804// auto bcast. 2805acl_position_tensor = 2806ggml_cann_create_tensor (src1 -> data ,ggml_cann_type_mapping (src1 -> type ),ggml_type_size (src1 -> type ), 2807position_ne ,position_nb ,GGML_MAX_DIMS ); 2808 } 2809 2810// Step4: multiply by the position 2811int64_t theta_length = theta_scale_length * position_length ; 2812ggml_cann_pool_alloc theta_allocator (ctx .pool (),theta_length * sizeof (float )); 2813void * theta_buffer = theta_allocator .get (); 2814 2815acl_tensor_ptr acl_theta_tensor = 2816ggml_cann_create_tensor (theta_buffer ,ACL_FLOAT ,sizeof (float ),cache_ne ,cache_nb ,GGML_MAX_DIMS ); 2817aclnn_mul (ctx ,acl_position_tensor .get (),acl_theta_scale_tensor .get (),acl_theta_tensor .get ()); 2818 2819// Step5: calculate sin cos. 2820// init sin_repeat && cos_repeat, only to accelerate first layer on each device 2821if (position_length > ctx .rope_cache .position_length ) { 2822ctx .rope_cache .position_length = position_length ; 2823if (ctx .rope_cache .sin_cache != nullptr ) { 2824ACL_CHECK (aclrtFree (ctx .rope_cache .sin_cache )); 2825 } 2826if (ctx .rope_cache .cos_cache != nullptr ) { 2827ACL_CHECK (aclrtFree (ctx .rope_cache .cos_cache )); 2828 } 2829int64_t repeat_theta_length = theta_scale_length * position_length * 2 ; 2830ACL_CHECK ( 2831aclrtMalloc (& ctx .rope_cache .sin_cache ,repeat_theta_length * sizeof (float ),ACL_MEM_MALLOC_HUGE_FIRST )); 2832ACL_CHECK ( 2833aclrtMalloc (& ctx .rope_cache .cos_cache ,repeat_theta_length * sizeof (float ),ACL_MEM_MALLOC_HUGE_FIRST )); 2834 } 2835 2836// sin/cos 2837ggml_cann_pool_alloc sin_allocator (ctx .pool (),theta_length * sizeof (float )); 2838void * sin_buffer = sin_allocator .get (); 2839acl_tensor_ptr acl_sin_tensor = 2840ggml_cann_create_tensor (sin_buffer ,ACL_FLOAT ,sizeof (float ),cache_ne ,cache_nb ,GGML_MAX_DIMS ,ACL_FORMAT_ND ); 2841aclnn_sin (ctx ,acl_theta_tensor .get (),acl_sin_tensor .get ()); 2842 2843ggml_cann_pool_alloc cos_allocator (ctx .pool (),theta_length * sizeof (float )); 2844void * cos_buffer = cos_allocator .get (); 2845acl_tensor_ptr acl_cos_tensor = 2846ggml_cann_create_tensor (cos_buffer ,ACL_FLOAT ,sizeof (float ),cache_ne ,cache_nb ,GGML_MAX_DIMS ,ACL_FORMAT_ND ); 2847aclnn_cos (ctx ,acl_theta_tensor .get (),acl_cos_tensor .get ()); 2848 2849if (ext_factor != 0 ) { 2850attn_factor *=1.0f + 0.1f * logf (1.0f /freq_scale ); 2851 } 2852 2853// Step 5: multiply by attn_factor 2854if (attn_factor != 1 ) { 2855aclnn_muls (ctx ,acl_sin_tensor .get (),attn_factor ,nullptr , true); 2856aclnn_muls (ctx ,acl_cos_tensor .get (),attn_factor ,nullptr , true); 2857 } 2858 2859int64_t sin_reshape_ne [4 ]= {rope_dims ,1 ,dst -> ne [2 ],1 }; 2860size_t sin_reshape_nb [GGML_MAX_DIMS ]; 2861sin_reshape_nb [0 ]= sizeof (float ); 2862for (int i = 1 ;i < GGML_MAX_DIMS ;i ++ ) { 2863sin_reshape_nb [i ]= sin_reshape_nb [i - 1 ]* sin_reshape_ne [i - 1 ]; 2864 } 2865acl_tensor_ptr acl_sin_repeat_tensor = ggml_cann_create_tensor (ctx .rope_cache .sin_cache ,ACL_FLOAT ,sizeof (float ), 2866sin_reshape_ne ,sin_reshape_nb ,GGML_MAX_DIMS ); 2867acl_tensor_ptr acl_cos_repeat_tensor = ggml_cann_create_tensor (ctx .rope_cache .cos_cache ,ACL_FLOAT ,sizeof (float ), 2868sin_reshape_ne ,sin_reshape_nb ,GGML_MAX_DIMS ); 2869 2870// Step 6: repeat 2871if (is_neox ) { 2872// [sinθ1, sinθ1, sinθ2, sinθ2, ..., sinθn, sinθn] 2873int64_t repeatsArray []= {1 ,1 ,1 ,2 }; 2874aclnn_repeat (ctx ,acl_sin_tensor .get (),acl_sin_repeat_tensor .get (),repeatsArray ); 2875aclnn_repeat (ctx ,acl_cos_tensor .get (),acl_cos_repeat_tensor .get (),repeatsArray ); 2876 }else { 2877int64_t num_repeats = 2 ; 2878int64_t dim = 3 ; 2879int64_t output_size = theta_scale_length * num_repeats ; 2880// [sinθ1, sinθ2, ..., sinθn, sinθ1, sinθ2, ..., sinθn] 2881aclnn_repeat_interleave (ctx ,acl_sin_tensor .get (),acl_sin_repeat_tensor .get (),dim ,num_repeats ,output_size ); 2882aclnn_repeat_interleave (ctx ,acl_cos_tensor .get (),acl_cos_repeat_tensor .get (),dim ,num_repeats ,output_size ); 2883 } 2884 2885// Update cached value. 2886ctx .rope_cache .cached = true; 2887ctx .rope_cache .set (theta_scale_length ,position_length ,ext_factor ,theta_scale ,freq_scale ,attn_factor ,is_neox , 2888indep_sects ,mrope_used ,is_imrope ,sections ); 2889} 2890 2891#ifdef __cplusplus 2892extern "C" { 2893#endif 2894aclnnStatus aclnnRotaryPositionEmbeddingGetWorkspaceSize (const aclTensor * x , 2895const aclTensor * cos , 2896const aclTensor * sin , 2897int64_t mode , 2898const aclTensor * yOut , 2899uint64_t * workspaceSize , 2900aclOpExecutor ** executor ); 2901aclnnStatus aclnnRotaryPositionEmbedding (void * workspace , 2902uint64_t workspaceSize , 2903aclOpExecutor * executor , 2904aclrtStream stream ); 2905#ifdef __cplusplus 2906} 2907#endif 2908 2909void ggml_cann_rope (ggml_backend_cann_context & ctx ,ggml_tensor * dst ) { 2910ggml_tensor * src0 = dst -> src [0 ];// input 2911 2912// param 2913float freq_base ,freq_scale ,ext_factor ,attn_factor ,beta_fast ,beta_slow ; 2914int sections [4 ]; 2915// const int n_past = ((int32_t *) dst->op_params)[0]; 2916const int n_dims = ((int32_t * )dst -> op_params )[1 ]; 2917const int mode = ((int32_t * )dst -> op_params )[2 ]; 2918// const int n_ctx = ((int32_t *) dst->op_params)[3]; 2919const int n_ctx_orig = ((int32_t * )dst -> op_params )[4 ]; 2920 2921GGML_TENSOR_UNARY_OP_LOCALS 2922 2923memcpy (& freq_base , (int32_t * )dst -> op_params + 5 ,sizeof (float )); 2924memcpy (& freq_scale , (int32_t * )dst -> op_params + 6 ,sizeof (float )); 2925memcpy (& ext_factor , (int32_t * )dst -> op_params + 7 ,sizeof (float )); 2926memcpy (& attn_factor , (int32_t * )dst -> op_params + 8 ,sizeof (float )); 2927memcpy (& beta_fast , (int32_t * )dst -> op_params + 9 ,sizeof (float )); 2928memcpy (& beta_slow , (int32_t * )dst -> op_params + 10 ,sizeof (float )); 2929memcpy (& sections , (int32_t * )dst -> op_params + 11 ,sizeof (int )* 4 ); 2930 2931GGML_ASSERT (n_dims %2 == 0 ); 2932GGML_ASSERT (n_dims <=ne00 ); 2933 2934const float theta_scale = powf (freq_base ,-2.0f /n_dims ); 2935 2936float corr_dims [2 ]; 2937ggml_rope_yarn_corr_dims (n_dims ,n_ctx_orig ,freq_base ,beta_fast ,beta_slow ,corr_dims ); 2938 2939bool is_neox = mode & GGML_ROPE_TYPE_NEOX ; 2940const bool is_imrope = mode == GGML_ROPE_TYPE_IMROPE ;// qwen3vl apply interleaved mrope 2941// mrope_used means the GGML_ROPE_TYPE_MROPE bit is set. 2942// Note: this bit is also set for imrope and some vision modes, 2943// so mrope_used does NOT exclusively indicate pure mrope. 2944const bool mrope_used = mode & GGML_ROPE_TYPE_MROPE ; 2945const bool is_vision = mode == GGML_ROPE_TYPE_VISION ; 2946 2947if (mrope_used ) { 2948GGML_ASSERT (sections [0 ]> 0 || sections [1 ]> 0 || sections [2 ]> 0 ); 2949 } 2950 2951if (is_vision ) { 2952GGML_ASSERT (n_dims == ne0 /2 ); 2953 } 2954 2955if (is_imrope || mrope_used ) { 2956is_neox = true; 2957 } 2958 2959int64_t rope_dims = n_dims ; 2960 2961//Our current RotaryPositionEmbedding does not support the VISION mode, 2962//but essentially it only modifies theta_base in mrope, 2963//then repeats it at the end in the same way as is_neox. 2964//In fact, RoPE is still applied across all dimensions. 2965if (is_vision ) { 2966rope_dims = src0 -> ne [0 ]; 2967 } 2968int64_t tail_dims = ne00 - rope_dims ; 2969bool has_tail = tail_dims > 0 ; 2970 2971// init ctx.rope_cos/rope_sin cache 2972aclnn_rope_cache_init (ctx ,dst ,corr_dims ,ext_factor ,theta_scale ,freq_scale ,attn_factor ,is_neox ,sections , 2973mrope_used ,is_imrope ,is_vision ,rope_dims ); 2974 2975// Cache is generated with ne00 dimensions, so we use ne00 for reshape 2976int64_t sin_reshape_ne [4 ]= {rope_dims ,1 ,ne02 ,1 }; 2977size_t sin_reshape_nb [GGML_MAX_DIMS ]; 2978sin_reshape_nb [0 ]= sizeof (float ); 2979for (int i = 1 ;i < GGML_MAX_DIMS ;i ++ ) { 2980sin_reshape_nb [i ]= sin_reshape_nb [i - 1 ]* sin_reshape_ne [i - 1 ]; 2981 } 2982acl_tensor_ptr acl_sin_reshape_tensor = ggml_cann_create_tensor (ctx .rope_cache .sin_cache ,ACL_FLOAT ,sizeof (float ), 2983sin_reshape_ne ,sin_reshape_nb ,GGML_MAX_DIMS ); 2984acl_tensor_ptr acl_cos_reshape_tensor = ggml_cann_create_tensor (ctx .rope_cache .cos_cache ,ACL_FLOAT ,sizeof (float ), 2985sin_reshape_ne ,sin_reshape_nb ,GGML_MAX_DIMS ); 2986 2987acl_tensor_ptr acl_src = ggml_cann_create_tensor (src0 ); 2988acl_tensor_ptr acl_dst = ggml_cann_create_tensor (dst ); 2989#ifdef ASCEND_310P 2990// Special ROPE operation for 310P 2991 2992// roll input 2993void * input_roll_buffer ; 2994acl_tensor_ptr acl_minus_one_tensor ; 2995void * minus_one_scale_buffer = nullptr ; 2996ggml_cann_pool_alloc roll_allocator (ctx .pool (),ggml_nbytes (src0 )); 2997ggml_cann_pool_alloc minus_one_scale_allocator (ctx .pool (),sizeof (float )* src0 -> ne [0 ]); 2998if (!is_neox ) { 2999// roll input: [q0,q1,q2,q3,...] -> [q1,q0,q3,q2,...] 3000input_roll_buffer = roll_allocator .get (); 3001int64_t input_roll_ne [4 ]= {2 ,src0 -> ne [1 ]* (src0 -> ne [0 ] /2 ),src0 -> ne [2 ],src0 -> ne [3 ] }; 3002size_t input_roll_nb [GGML_MAX_DIMS ]; 3003input_roll_nb [0 ]= ggml_type_size (src0 -> type ); 3004for (int i = 1 ;i < GGML_MAX_DIMS ;i ++ ) { 3005input_roll_nb [i ]= input_roll_nb [i - 1 ]* input_roll_ne [i - 1 ]; 3006 } 3007acl_tensor_ptr acl_input_roll_tensor = 3008ggml_cann_create_tensor (input_roll_buffer ,ggml_cann_type_mapping (src0 -> type ),ggml_type_size (src0 -> type ), 3009input_roll_ne ,input_roll_nb ,GGML_MAX_DIMS ); 3010acl_tensor_ptr acl_input_tensor = 3011ggml_cann_create_tensor (src0 -> data ,ggml_cann_type_mapping (src0 -> type ),ggml_type_size (src0 -> type ), 3012input_roll_ne ,input_roll_nb ,GGML_MAX_DIMS ); 3013 3014int64_t shifts []= {1 }; 3015int64_t dims []= {3 }; 3016aclnn_roll (ctx ,acl_input_tensor .get (),acl_input_roll_tensor .get (),shifts ,dims ); 3017 3018// init [-1, 1, -1, 1, ...] 3019minus_one_scale_buffer = minus_one_scale_allocator .get (); 3020 3021int64_t minus_one_ne [4 ]= {src0 -> ne [0 ],1 ,1 ,1 }; 3022size_t minus_one_nb [GGML_MAX_DIMS ]; 3023minus_one_nb [0 ]= sizeof (float ); 3024for (int i = 1 ;i < GGML_MAX_DIMS ;i ++ ) { 3025minus_one_nb [i ]= minus_one_nb [i - 1 ]* minus_one_ne [i - 1 ]; 3026 } 3027acl_minus_one_tensor = aclnn_values (ctx ,minus_one_scale_buffer ,sizeof (float )* src0 -> ne [0 ],minus_one_ne , 3028GGML_MAX_DIMS ,ACL_FLOAT ,sizeof (float ),1 ); 3029int64_t dim = 3 ; 3030int64_t * index = new int64_t [src0 -> ne [0 ]]; 3031for (int i = 0 ;i < src0 -> ne [0 ];i ++ ) { 3032index [i ]= i /2 * 2 ; 3033 } 3034int64_t index_num = src0 -> ne [0 ]; 3035float value = -1 ; 3036aclnn_index_fill_tensor (ctx ,acl_minus_one_tensor .get (),dim ,index ,index_num ,value ); 3037 }else { 3038// roll input: [q0,q1,q2,...] -> 3039// [q_half,q_half+1,...,q_end,q0,q1,...q_half-1] 3040input_roll_buffer = roll_allocator .get (); 3041acl_tensor_ptr acl_input_roll_tensor = 3042ggml_cann_create_tensor (input_roll_buffer ,ggml_cann_type_mapping (src0 -> type ),ggml_type_size (src0 -> type ), 3043src0 -> ne ,src0 -> nb ,GGML_MAX_DIMS ); 3044acl_tensor_ptr acl_input_tensor = ggml_cann_create_tensor (src0 ); 3045 3046int64_t shifts []= {src0 -> ne [0 ] /2 }; 3047int64_t dims []= {3 }; 3048aclnn_roll (ctx ,acl_input_tensor .get (),acl_input_roll_tensor .get (),shifts ,dims ); 3049 3050// init [-1, -1, -1, 1, 1,1,...] 3051minus_one_scale_buffer = minus_one_scale_allocator .get (); 3052int64_t minus_one_ne [4 ]= {src0 -> ne [0 ],1 ,1 ,1 }; 3053size_t minus_one_nb [GGML_MAX_DIMS ]; 3054minus_one_nb [0 ]= sizeof (float ); 3055for (int i = 1 ;i < GGML_MAX_DIMS ;i ++ ) { 3056minus_one_nb [i ]= minus_one_nb [i - 1 ]* minus_one_ne [i - 1 ]; 3057 } 3058acl_minus_one_tensor = aclnn_values (ctx ,minus_one_scale_buffer ,sizeof (float )* src0 -> ne [0 ],minus_one_ne , 3059GGML_MAX_DIMS ,ACL_FLOAT ,sizeof (float ),1 ); 3060// -1 * first half 3061int64_t first_half_ne [4 ]= {src0 -> ne [0 ] /2 ,1 ,1 ,1 }; 3062size_t first_half_nb [GGML_MAX_DIMS ]; 3063first_half_nb [0 ]= sizeof (float ); 3064for (int i = 1 ;i < GGML_MAX_DIMS ;i ++ ) { 3065first_half_nb [i ]= first_half_nb [i - 1 ]* first_half_ne [i - 1 ]; 3066 } 3067acl_tensor_ptr acl_first_half_tensor = ggml_cann_create_tensor (minus_one_scale_buffer ,ACL_FLOAT ,sizeof (float ), 3068first_half_ne ,first_half_nb ,GGML_MAX_DIMS ); 3069bool inplace = true; 3070float scale = -1 ; 3071aclnn_muls (ctx ,acl_first_half_tensor .get (),scale ,nullptr ,inplace ); 3072 } 3073 3074// TODO: n_dims < ne0 3075GGML_ASSERT (n_dims == src0 -> ne [0 ]); 3076 3077// input * scale 3078ggml_cann_pool_alloc roll_mul_scale_allocator (ctx .pool (),ggml_nbytes (src0 )); 3079void * input_roll_mul_scale_buffer = roll_mul_scale_allocator .get (); 3080size_t input_nb [GGML_MAX_DIMS ]; 3081input_nb [0 ]= ggml_type_size (src0 -> type ); 3082for (int i = 1 ;i < GGML_MAX_DIMS ;i ++ ) { 3083input_nb [i ]= input_nb [i - 1 ]* src0 -> ne [i - 1 ]; 3084 } 3085acl_tensor_ptr acl_input_roll_mul_scale_tensor = 3086ggml_cann_create_tensor (input_roll_mul_scale_buffer ,ggml_cann_type_mapping (src0 -> type ), 3087ggml_type_size (src0 -> type ),src0 -> ne ,input_nb ,GGML_MAX_DIMS ); 3088acl_tensor_ptr acl_input_roll_reshape_tensor = 3089ggml_cann_create_tensor (input_roll_buffer ,ggml_cann_type_mapping (src0 -> type ),ggml_type_size (src0 -> type ), 3090src0 -> ne ,input_nb ,GGML_MAX_DIMS ); 3091 3092aclnn_mul (ctx ,acl_input_roll_reshape_tensor .get (),acl_minus_one_tensor .get (), 3093acl_input_roll_mul_scale_tensor .get ()); 3094 3095// output 3096void * output_fp32_buffer ; 3097if (src0 -> type == GGML_TYPE_F32 ) { 3098aclnn_mul (ctx ,acl_src .get (),acl_cos_reshape_tensor .get ()); 3099aclnn_mul (ctx ,acl_input_roll_mul_scale_tensor .get (),acl_sin_reshape_tensor .get ()); 3100aclnn_add (ctx ,acl_src .get (),acl_input_roll_mul_scale_tensor .get (),acl_dst .get ()); 3101// TODO: ne0 != n_dims in mode2 3102 }else if (src0 -> type == GGML_TYPE_F16 ) { 3103size_t input_fp32_nb [GGML_MAX_DIMS ]; 3104input_fp32_nb [0 ]= sizeof (float ); 3105for (int i = 1 ;i < GGML_MAX_DIMS ;i ++ ) { 3106input_fp32_nb [i ]= input_fp32_nb [i - 1 ]* dst -> ne [i - 1 ]; 3107 } 3108ggml_cann_pool_alloc fp32_allocator1 (ctx .pool (),ggml_nelements (dst )* sizeof (float )); 3109void * input_fp32_buffer1 = fp32_allocator1 .get (); 3110acl_tensor_ptr input_fp32_tensor1 = ggml_cann_create_tensor (input_fp32_buffer1 ,ACL_FLOAT ,sizeof (float ), 3111dst -> ne ,input_fp32_nb ,GGML_MAX_DIMS ); 3112ggml_cann_pool_alloc fp32_allocator2 (ctx .pool (),ggml_nelements (dst )* sizeof (float )); 3113void * input_fp32_buffer2 = fp32_allocator2 .get (); 3114acl_tensor_ptr input_fp32_tensor2 = ggml_cann_create_tensor (input_fp32_buffer2 ,ACL_FLOAT ,sizeof (float ), 3115dst -> ne ,input_fp32_nb ,GGML_MAX_DIMS ); 3116 3117ggml_cann_pool_alloc fp32_allocator (ctx .pool (),ggml_nelements (dst )* sizeof (float )); 3118output_fp32_buffer = fp32_allocator .get (); 3119acl_tensor_ptr output_fp32_tensor = ggml_cann_create_tensor (output_fp32_buffer ,ACL_FLOAT ,sizeof (float ), 3120dst -> ne ,input_fp32_nb ,GGML_MAX_DIMS ); 3121aclnn_mul (ctx ,acl_src .get (),acl_cos_reshape_tensor .get (),input_fp32_tensor1 .get ()); 3122aclnn_mul (ctx ,acl_input_roll_mul_scale_tensor .get (),acl_sin_reshape_tensor .get (),input_fp32_tensor2 .get ()); 3123aclnn_add (ctx ,input_fp32_tensor1 .get (),input_fp32_tensor2 .get (),output_fp32_tensor .get ()); 3124aclnn_cast (ctx ,output_fp32_tensor .get (),acl_dst .get (),ACL_FLOAT16 ); 3125 } 3126return ; 3127#endif 3128int64_t acl_mode = is_neox ?0 :1 ; 3129 3130// Pre-define head and tail dimensions for reuse 3131int64_t head_ne [GGML_MAX_DIMS ]= {rope_dims ,ne01 ,ne02 ,ne03 }; 3132int64_t tail_ne [GGML_MAX_DIMS ]= {tail_dims ,ne01 ,ne02 ,ne03 }; 3133 3134// Step 1: Prepare trans tensors for F16 type conversion to F32 if needed 3135bool src_dst_need_trans = false; 3136ggml_cann_pool_alloc src_trans_allocator (ctx .pool ()); 3137ggml_cann_pool_alloc dst_trans_allocator (ctx .pool ()); 3138acl_tensor_ptr acl_src_trans_tensor ; 3139acl_tensor_ptr acl_dst_trans_tensor ; 3140void * src_trans_buffer = nullptr ; 3141void * dst_trans_buffer = nullptr ; 3142size_t src_dst_trans_nb [GGML_MAX_DIMS ]; 3143if (src0 -> type == GGML_TYPE_F16 ) { 3144src_dst_need_trans = true; 3145src_trans_buffer = src_trans_allocator .alloc (ggml_nelements (src0 )* sizeof (float )); 3146dst_trans_buffer = dst_trans_allocator .alloc (ggml_nelements (dst )* sizeof (float )); 3147 3148src_dst_trans_nb [0 ]= sizeof (float ); 3149for (int i = 1 ;i < GGML_MAX_DIMS ;i ++ ) { 3150src_dst_trans_nb [i ]= src_dst_trans_nb [i - 1 ]* src0 -> ne [i - 1 ]; 3151 } 3152acl_src_trans_tensor = ggml_cann_create_tensor (src_trans_buffer ,ACL_FLOAT ,sizeof (float ),src0 -> ne , 3153src_dst_trans_nb ,GGML_MAX_DIMS ); 3154acl_dst_trans_tensor = ggml_cann_create_tensor (dst_trans_buffer ,ACL_FLOAT ,sizeof (float ),dst -> ne , 3155src_dst_trans_nb ,GGML_MAX_DIMS ); 3156aclnn_cast (ctx ,acl_src .get (),acl_src_trans_tensor .get (),ACL_FLOAT ); 3157 } 3158 3159// Step 2: Prepare head tensors for tail splitting if needed 3160acl_tensor_ptr acl_src_head ; 3161acl_tensor_ptr acl_dst_head ; 3162if (has_tail ) { 3163// Create head views for RotaryPositionEmbedding (only first rope_dims dimensions) 3164// RotaryPositionEmbedding requires contiguous dst tensor, so we use a temporary buffer 3165if (src_dst_need_trans ) { 3166// Use F32 trans tensor strides 3167acl_src_head = ggml_cann_create_tensor ((char * )src_trans_buffer ,ACL_FLOAT ,sizeof (float ),head_ne , 3168src_dst_trans_nb ,GGML_MAX_DIMS ); 3169 }else { 3170// Use original F32 tensor strides 3171acl_src_head = ggml_cann_create_tensor ((char * )src0 -> data ,ACL_FLOAT ,sizeof (float ),head_ne ,src0 -> nb , 3172GGML_MAX_DIMS ); 3173 } 3174 3175int64_t head_elements = rope_dims * ne01 * ne02 * ne03 ; 3176ggml_cann_pool_alloc dst_head_contiguous_allocator (ctx .pool (),head_elements * sizeof (float )); 3177void * dst_head_contiguous_buffer = dst_head_contiguous_allocator .get (); 3178 3179size_t head_contiguous_nb [GGML_MAX_DIMS ]; 3180head_contiguous_nb [0 ]= sizeof (float ); 3181for (int i = 1 ;i < GGML_MAX_DIMS ;i ++ ) { 3182head_contiguous_nb [i ]= head_contiguous_nb [i - 1 ]* head_ne [i - 1 ]; 3183 } 3184acl_dst_head = ggml_cann_create_tensor (dst_head_contiguous_buffer ,ACL_FLOAT ,sizeof (float ),head_ne , 3185head_contiguous_nb ,GGML_MAX_DIMS ); 3186 } 3187 3188// Step 3: Execute RotaryPositionEmbedding 3189if (has_tail ) { 3190// Rotate only the head portion (first rope_dims dimensions) 3191GGML_CANN_CALL_ACLNN_OP (ctx ,RotaryPositionEmbedding ,acl_src_head .get (),acl_cos_reshape_tensor .get (), 3192acl_sin_reshape_tensor .get (),acl_mode ,acl_dst_head .get ()); 3193 3194// Copy head result from contiguous buffer back to destination tensor 3195if (src_dst_need_trans ) { 3196acl_tensor_ptr acl_dst_head_target = ggml_cann_create_tensor ( 3197 (char * )dst_trans_buffer ,ACL_FLOAT ,sizeof (float ),head_ne ,src_dst_trans_nb ,GGML_MAX_DIMS ); 3198cann_copy (ctx ,acl_dst_head .get (),acl_dst_head_target .get ()); 3199 }else { 3200acl_tensor_ptr acl_dst_head_target = 3201ggml_cann_create_tensor ((char * )dst -> data ,ACL_FLOAT ,sizeof (float ),head_ne ,dst -> nb ,GGML_MAX_DIMS ); 3202cann_copy (ctx ,acl_dst_head .get (),acl_dst_head_target .get ()); 3203 } 3204 }else if (src_dst_need_trans ) { 3205// Rotate full tensor (no tail), using trans tensors 3206GGML_CANN_CALL_ACLNN_OP (ctx ,RotaryPositionEmbedding ,acl_src_trans_tensor .get (),acl_cos_reshape_tensor .get (), 3207acl_sin_reshape_tensor .get (),acl_mode ,acl_dst_trans_tensor .get ()); 3208 }else if (src0 -> data == dst -> data && !ggml_is_contiguous (src0 )) { 3209// In-place on non-contiguous tensor: RotaryPositionEmbedding cannot safely 3210// read and write the same non-contiguous buffer. Use contiguous temporaries. 3211size_t contiguous_nb [GGML_MAX_DIMS ]; 3212contiguous_nb [0 ]= sizeof (float ); 3213for (int i = 1 ;i < GGML_MAX_DIMS ;i ++ ) { 3214contiguous_nb [i ]= contiguous_nb [i - 1 ]* src0 -> ne [i - 1 ]; 3215 } 3216int64_t total_elements = ggml_nelements (src0 ); 3217ggml_cann_pool_alloc inplace_src_alloc (ctx .pool (),total_elements * sizeof (float )); 3218ggml_cann_pool_alloc inplace_dst_alloc (ctx .pool (),total_elements * sizeof (float )); 3219 3220acl_tensor_ptr acl_src_contig = ggml_cann_create_tensor (inplace_src_alloc .get (),ACL_FLOAT ,sizeof (float ), 3221src0 -> ne ,contiguous_nb ,GGML_MAX_DIMS ); 3222acl_tensor_ptr acl_dst_contig = ggml_cann_create_tensor (inplace_dst_alloc .get (),ACL_FLOAT ,sizeof (float ), 3223dst -> ne ,contiguous_nb ,GGML_MAX_DIMS ); 3224 3225cann_copy (ctx ,acl_src .get (),acl_src_contig .get ()); 3226GGML_CANN_CALL_ACLNN_OP (ctx ,RotaryPositionEmbedding ,acl_src_contig .get (),acl_cos_reshape_tensor .get (), 3227acl_sin_reshape_tensor .get (),acl_mode ,acl_dst_contig .get ()); 3228cann_copy (ctx ,acl_dst_contig .get (),acl_dst .get ()); 3229 }else { 3230// Rotate full tensor (no tail), using original tensors 3231GGML_CANN_CALL_ACLNN_OP (ctx ,RotaryPositionEmbedding ,acl_src .get (),acl_cos_reshape_tensor .get (), 3232acl_sin_reshape_tensor .get (),acl_mode ,acl_dst .get ()); 3233 } 3234 3235// Step 4: Copy unrotated tail portion from source to destination 3236if (has_tail ) { 3237size_t src_tail_offset ; 3238size_t dst_tail_offset ; 3239 3240auto copy_tail_device = [& ](void * src_ptr ,void * dst_ptr ,aclDataType dtype ,size_t elem_size , 3241size_t * nb_src_arr ,size_t * nb_dst_arr ) { 3242acl_tensor_ptr acl_src_tail = 3243ggml_cann_create_tensor (src_ptr ,dtype ,elem_size ,tail_ne ,nb_src_arr ,GGML_MAX_DIMS ); 3244acl_tensor_ptr acl_dst_tail = 3245ggml_cann_create_tensor (dst_ptr ,dtype ,elem_size ,tail_ne ,nb_dst_arr ,GGML_MAX_DIMS ); 3246cann_copy (ctx ,acl_src_tail .get (),acl_dst_tail .get ()); 3247 }; 3248 3249if (src_dst_need_trans ) { 3250// Use F32 trans tensor strides and offsets 3251src_tail_offset = rope_dims * src_dst_trans_nb [0 ]; 3252dst_tail_offset = rope_dims * src_dst_trans_nb [0 ]; 3253copy_tail_device ((char * )src_trans_buffer + src_tail_offset , (char * )dst_trans_buffer + dst_tail_offset , 3254ACL_FLOAT ,sizeof (float ),src_dst_trans_nb ,src_dst_trans_nb ); 3255 }else { 3256// Use original tensor strides and offsets 3257src_tail_offset = rope_dims * nb00 ; 3258dst_tail_offset = rope_dims * nb0 ; 3259copy_tail_device ((char * )src0 -> data + src_tail_offset , (char * )dst -> data + dst_tail_offset , 3260ggml_cann_type_mapping (dst -> type ),ggml_element_size (dst ),src0 -> nb ,dst -> nb ); 3261 } 3262 } 3263 3264// Step 5: Cast back to F16 if needed 3265if (src_dst_need_trans ) { 3266aclnn_cast (ctx ,acl_dst_trans_tensor .get (),acl_dst .get (),ACL_FLOAT16 ); 3267 } 3268} 3269 3270void ggml_cann_rope_cache_preload (ggml_backend_cann_context & ctx ,ggml_tensor * dst ) { 3271ggml_tensor * src0 = dst -> src [0 ]; 3272 3273float freq_base ,freq_scale ,ext_factor ,attn_factor ,beta_fast ,beta_slow ; 3274int sections [4 ]; 3275const int n_dims = ((int32_t * )dst -> op_params )[1 ]; 3276const int mode = ((int32_t * )dst -> op_params )[2 ]; 3277const int n_ctx_orig = ((int32_t * )dst -> op_params )[4 ]; 3278 3279GGML_TENSOR_UNARY_OP_LOCALS 3280 3281memcpy (& freq_base , (int32_t * )dst -> op_params + 5 ,sizeof (float )); 3282memcpy (& freq_scale , (int32_t * )dst -> op_params + 6 ,sizeof (float )); 3283memcpy (& ext_factor , (int32_t * )dst -> op_params + 7 ,sizeof (float )); 3284memcpy (& attn_factor , (int32_t * )dst -> op_params + 8 ,sizeof (float )); 3285memcpy (& beta_fast , (int32_t * )dst -> op_params + 9 ,sizeof (float )); 3286memcpy (& beta_slow , (int32_t * )dst -> op_params + 10 ,sizeof (float )); 3287memcpy (& sections , (int32_t * )dst -> op_params + 11 ,sizeof (int )* 4 ); 3288 3289const float theta_scale = powf (freq_base ,-2.0f /n_dims ); 3290 3291float corr_dims [2 ]; 3292ggml_rope_yarn_corr_dims (n_dims ,n_ctx_orig ,freq_base ,beta_fast ,beta_slow ,corr_dims ); 3293 3294bool is_neox = mode & GGML_ROPE_TYPE_NEOX ; 3295const bool is_imrope = mode == GGML_ROPE_TYPE_IMROPE ; 3296const bool mrope_used = mode & GGML_ROPE_TYPE_MROPE ; 3297const bool is_vision = mode == GGML_ROPE_TYPE_VISION ; 3298 3299if (is_imrope || mrope_used ) { 3300is_neox = true; 3301 } 3302 3303int64_t rope_dims = n_dims ; 3304if (is_vision ) { 3305rope_dims = src0 -> ne [0 ]; 3306 } 3307 3308// Run the full cache init on the non-captured stream. This performs all 3309// host-to-device memcpy, aclrtMalloc/Free, and on-device computations 3310// so that the memory pool is warmed up and cache metadata is populated. 3311aclnn_rope_cache_init (ctx ,dst ,corr_dims ,ext_factor ,theta_scale ,freq_scale ,attn_factor ,is_neox ,sections , 3312mrope_used ,is_imrope ,is_vision ,rope_dims ); 3313 3314// Reset `cached` so that during graph capture the on-device computations 3315// (sin/cos, position multiply, repeat, etc.) still execute and get recorded 3316// into the captured graph. The cache metadata (theta_scale_length, 3317// theta_scale, sections, position_length, etc.) remains set, which causes 3318// all host-to-device copy and malloc/free branches to be skipped. 3319ctx .rope_cache .cached = false; 3320} 3321 3322void ggml_cann_argmax (ggml_backend_cann_context & ctx ,ggml_tensor * dst ) { 3323ggml_tensor * src0 = dst -> src [0 ]; 3324 3325acl_tensor_ptr acl_src = ggml_cann_create_tensor (src0 ); 3326acl_tensor_ptr acl_dst = ggml_cann_create_tensor (dst ,dst -> ne ,dst -> nb ,3 ); 3327 3328GGML_CANN_CALL_ACLNN_OP (ctx ,ArgMax ,acl_src .get (),3 , false,acl_dst .get ()); 3329} 3330 3331void ggml_cann_conv_transpose_1d (ggml_backend_cann_context & ctx ,ggml_tensor * dst ) { 3332ggml_tensor * src0 = dst -> src [0 ]; 3333ggml_tensor * src1 = dst -> src [1 ]; 3334 3335// stride 3336int64_t s0 = ((const int32_t * ) (dst -> op_params ))[0 ]; 3337 3338acl_tensor_ptr acl_input = ggml_cann_create_tensor (src1 ,src1 -> ne ,src1 -> nb ,3 ,ACL_FORMAT_NCL ); 3339acl_tensor_ptr acl_weight = ggml_cann_create_tensor (src0 ,src0 -> ne ,src0 -> nb ,3 ,ACL_FORMAT_NCL ); 3340acl_tensor_ptr acl_dst = ggml_cann_create_tensor (dst ,dst -> ne ,dst -> nb ,3 ,ACL_FORMAT_NCL ); 3341 3342// get base information of input and kernel 3343int64_t input_len = * (src1 -> ne ); 3344int64_t dst_len = * (dst -> ne ); 3345int64_t kernel_size = * (src0 -> ne ); 3346 3347// set the max kernel size for each conv 3348int64_t max_kernel_size = 255 ; 3349 3350// compute the partition of kernel 3351int64_t part_num = 1 ; 3352part_num = (kernel_size + max_kernel_size - 1 ) /max_kernel_size ; 3353 3354int64_t strideVal [1 ]; 3355strideVal [0 ]= s0 ; 3356acl_int_array_ptr stride = ggml_cann_create_int_array (strideVal ,1 ); 3357int64_t paddingVal []= {0 }; 3358acl_int_array_ptr padding = ggml_cann_create_int_array (paddingVal ,1 ); 3359int64_t dilationVal []= {1 }; 3360acl_int_array_ptr dilation = ggml_cann_create_int_array (dilationVal ,1 ); 3361bool transposed = true; 3362int64_t groups = 1 ; 3363int8_t cubeMathType = 0 ; 3364 3365#ifdef ASCEND_310P 3366cubeMathType = 1 ; 3367#endif 3368 3369auto weight_type = ggml_cann_type_mapping (src0 -> type ); 3370auto dst_type = ggml_cann_type_mapping (dst -> type ); 3371 3372// slice the kernel to make each conv available 3373int64_t slice_dim = -1 ; 3374int64_t slice_start = 0 ; 3375int64_t slice_end = max_kernel_size ; 3376int64_t slice_step = 1 ; 3377int64_t interval = max_kernel_size ; 3378 3379int64_t left_pad_len = dilationVal [0 ]* (max_kernel_size - 1 )+ 1 - 2 * paddingVal [0 ]; 3380int64_t right_pad_len = 0 ; 3381 3382acl_scalar_ptr alpha = nullptr ; 3383float alphaValue = 1.0 ; 3384alpha = ggml_cann_create_scalar (& alphaValue , aclDataType::ACL_FLOAT ); 3385 3386// set zero to destination 3387GGML_CANN_CALL_ACLNN_OP (ctx ,InplaceZero ,acl_dst .get ()); 3388 3389for (int k = 0 ;k < part_num ;k ++ ) { 3390// create part kernel tensor and slice from big kernel 3391slice_start = max_kernel_size * k ; 3392if (k == part_num - 1 ) { 3393slice_end = kernel_size ; 3394interval = kernel_size - max_kernel_size * k ; 3395 }else { 3396slice_end = max_kernel_size * (k + 1 ); 3397 } 3398 3399int64_t part_ne [4 ]; 3400for (int i = 0 ;i < 4 ;i ++ ) { 3401part_ne [i ]= * (src0 -> ne + i ); 3402 } 3403part_ne [0 ]= interval ; 3404 3405size_t part_nb [4 ]; 3406part_nb [0 ]= sizeof (weight_type ); 3407for (int i = 1 ;i < 4 ;i ++ ) { 3408part_nb [i ]= part_nb [i - 1 ]* part_ne [i - 1 ]; 3409 } 3410 3411ggml_cann_pool_alloc part_kernel_allocator ; 3412part_kernel_allocator .alloc (ctx .pool (),part_nb [3 ]); 3413void * part_kernel_buf = part_kernel_allocator .get (); 3414 3415acl_tensor_ptr part_kernel = ggml_cann_create_tensor (part_kernel_buf ,weight_type ,ggml_element_size (src0 ), 3416part_ne ,part_nb ,3 ,ACL_FORMAT_NCL ); 3417 3418GGML_CANN_CALL_ACLNN_OP (ctx ,Slice ,acl_weight .get (),slice_dim ,slice_start ,slice_end ,slice_step , 3419part_kernel .get ()); 3420 3421// create the part conv result tensor 3422int64_t part_dst_ne [4 ]; 3423for (int i = 0 ;i < 4 ;i ++ ) { 3424part_dst_ne [i ]= * (dst -> ne + i ); 3425 } 3426part_dst_ne [0 ]= (input_len - 1 )* strideVal [0 ]- 2 * paddingVal [0 ]+ dilationVal [0 ]* (part_ne [0 ]- 1 )+ 1 ; 3427 3428size_t part_dst_nb [4 ]; 3429part_dst_nb [0 ]= sizeof (weight_type ); 3430for (int i = 1 ;i < 4 ;i ++ ) { 3431part_dst_nb [i ]= part_dst_nb [i - 1 ]* part_dst_ne [i - 1 ]; 3432 } 3433ggml_cann_pool_alloc part_dst_allocator ; 3434part_dst_allocator .alloc (ctx .pool (),part_dst_nb [3 ]); 3435void * part_dst_buf = part_dst_allocator .get (); 3436 3437acl_tensor_ptr acl_part_dst = ggml_cann_create_tensor (part_dst_buf ,dst_type ,ggml_element_size (dst ), 3438part_dst_ne ,part_dst_nb ,3 ,ACL_FORMAT_NCL ); 3439GGML_CANN_CALL_ACLNN_OP (ctx ,InplaceZero ,acl_part_dst .get ()); 3440 3441// compute part conv transpose 1d 3442GGML_CANN_CALL_ACLNN_OP (ctx ,Convolution ,acl_input .get (),part_kernel .get (),nullptr ,stride .get (), 3443padding .get (),dilation .get (),transposed ,padding .get (),groups ,acl_part_dst .get (), 3444cubeMathType ); 3445 3446// compute the position of part result in final result 3447int64_t global_start = slice_start ; 3448int64_t global_end = std::min ((input_len - 1 )* strideVal [0 ]+ slice_end ,dst_len ); 3449 3450left_pad_len = global_start ; 3451right_pad_len = dst_len - global_end ; 3452 3453 std::vector < int64_t > padDataVal = {left_pad_len ,right_pad_len }; 3454acl_int_array_ptr padData = ggml_cann_create_int_array (padDataVal .data (),2 ); 3455 3456acl_scalar_ptr pad_value = nullptr ; 3457float pad_valueVal = 0.0 ; 3458pad_value = ggml_cann_create_scalar (& pad_valueVal , aclDataType::ACL_FLOAT ); 3459 3460int64_t conv_result_ne [4 ]; 3461for (int i = 0 ;i < 4 ;i ++ ) { 3462conv_result_ne [i ]= * (dst -> ne + i ); 3463 } 3464 3465size_t conv_result_nb [4 ]; 3466conv_result_nb [0 ]= sizeof (weight_type ); 3467for (int i = 1 ;i < 4 ;i ++ ) { 3468conv_result_nb [i ]= conv_result_nb [i - 1 ]* conv_result_ne [i - 1 ]; 3469 } 3470 3471ggml_cann_pool_alloc conv_result_allocator ; 3472conv_result_allocator .alloc (ctx .pool (),conv_result_nb [3 ]); 3473void * conv_result_buf = conv_result_allocator .get (); 3474 3475acl_tensor_ptr conv_result = ggml_cann_create_tensor (conv_result_buf ,dst_type ,ggml_element_size (dst ), 3476conv_result_ne ,conv_result_nb ,3 ,ACL_FORMAT_NCL ); 3477 3478GGML_CANN_CALL_ACLNN_OP (ctx ,InplaceZero ,conv_result .get ()); 3479GGML_CANN_CALL_ACLNN_OP (ctx ,ConstantPadNd ,acl_part_dst .get (),padData .get (),pad_value .get (), 3480conv_result .get ()); 3481GGML_CANN_CALL_ACLNN_OP (ctx ,InplaceAdd ,acl_dst .get (),conv_result .get (),alpha .get ()); 3482 } 3483} 3484 3485void ggml_cann_elu (ggml_backend_cann_context & ctx ,ggml_tensor * dst ) { 3486ggml_tensor * src0 = dst -> src [0 ]; 3487 3488acl_tensor_ptr acl_input = ggml_cann_create_tensor (src0 ); 3489acl_tensor_ptr acl_dst = ggml_cann_create_tensor (dst ); 3490 3491float alphaValue = 1.0f ; 3492acl_scalar_ptr alpha = nullptr ; 3493alpha = ggml_cann_create_scalar (& alphaValue , aclDataType::ACL_FLOAT ); 3494 3495GGML_CANN_CALL_ACLNN_OP (ctx ,Elu ,acl_input .get (),alpha .get (),alpha .get (),alpha .get (),acl_dst .get ()); 3496} 3497 3498void ggml_cann_mean (ggml_backend_cann_context & ctx ,ggml_tensor * dst ) { 3499ggml_tensor * src0 = dst -> src [0 ]; 3500 3501acl_tensor_ptr acl_src = ggml_cann_create_tensor (src0 ); 3502acl_tensor_ptr acl_dst = ggml_cann_create_tensor (dst ); 3503 3504int64_t reduceDimValue []= {3 }; 3505acl_int_array_ptr reduceDim = ggml_cann_create_int_array (reduceDimValue ,1 ); 3506bool keepDim = true; 3507 3508GGML_CANN_CALL_ACLNN_OP (ctx ,Mean ,acl_src .get (),reduceDim .get (),keepDim ,ACL_FLOAT ,acl_dst .get ()); 3509} 3510 3511void ggml_cann_pad_reflect_1d (ggml_backend_cann_context & ctx ,ggml_tensor * dst ) { 3512ggml_tensor * src0 = dst -> src [0 ]; 3513int32_t * opts = (int32_t * )dst -> op_params ; 3514int64_t paddingsArray [2 ]= {opts [0 ],opts [1 ] }; 3515acl_int_array_ptr paddings = ggml_cann_create_int_array (paddingsArray ,2 ); 3516 3517// Collapsing ne[2]*ne[3] into a single batch dimension requires that dim3 3518// is contiguous with respect to dim2 in both src and dst. 3519GGML_ASSERT (src0 -> nb [3 ]== src0 -> nb [2 ]* src0 -> ne [2 ]); 3520GGML_ASSERT (dst -> nb [3 ]== dst -> nb [2 ]* dst -> ne [2 ]); 3521 3522int64_t src_ne_3d [3 ]= {src0 -> ne [0 ],src0 -> ne [1 ],src0 -> ne [2 ]* src0 -> ne [3 ] }; 3523int64_t dst_ne_3d [3 ]= {dst -> ne [0 ],dst -> ne [1 ],dst -> ne [2 ]* dst -> ne [3 ] }; 3524 3525acl_tensor_ptr acl_src = ggml_cann_create_tensor (src0 -> data ,ggml_cann_type_mapping (src0 -> type ), 3526ggml_element_size (src0 ),src_ne_3d ,src0 -> nb ,3 ); 3527 3528acl_tensor_ptr acl_dst = ggml_cann_create_tensor (dst -> data ,ggml_cann_type_mapping (dst -> type ), 3529ggml_element_size (dst ),dst_ne_3d ,dst -> nb ,3 ); 3530 3531GGML_CANN_CALL_ACLNN_OP (ctx ,ReflectionPad1d ,acl_src .get (),paddings .get (),acl_dst .get ()); 3532} 3533 3534void ggml_cann_count_equal (ggml_backend_cann_context & ctx ,ggml_tensor * dst ) { 3535ggml_tensor * src0 = dst -> src [0 ]; 3536ggml_tensor * src1 = dst -> src [1 ]; 3537 3538// Write element-wise equality (0 or 1) into a temporary buffer to avoid 3539// modifying src0 in-place. Use the same type as src0 so ReduceSum can 3540// consume it directly without a type cast. 3541ggml_cann_pool_alloc eq_alloc (ctx .pool (),ggml_nelements (src0 )* ggml_element_size (src0 )); 3542size_t eq_nb [GGML_MAX_DIMS ]; 3543eq_nb [0 ]= ggml_element_size (src0 ); 3544for (int i = 1 ;i < GGML_MAX_DIMS ;i ++ ) { 3545eq_nb [i ]= eq_nb [i - 1 ]* src0 -> ne [i - 1 ]; 3546 } 3547acl_tensor_ptr acl_eq = ggml_cann_create_tensor ( 3548eq_alloc .get (),ggml_cann_type_mapping (src0 -> type ),ggml_element_size (src0 ), 3549src0 -> ne ,eq_nb ,GGML_MAX_DIMS ); 3550 3551acl_tensor_ptr acl_self = ggml_cann_create_tensor (src0 ); 3552acl_tensor_ptr acl_other = ggml_cann_create_tensor (src1 ); 3553GGML_CANN_CALL_ACLNN_OP (ctx ,EqTensor ,acl_self .get (),acl_other .get (),acl_eq .get ()); 3554 3555// Sum the 0/1 values into dst. 3556acl_tensor_ptr acl_dst = ggml_cann_create_tensor (dst ); 3557int64_t dims [4 ]= {0 ,1 ,2 ,3 }; 3558acl_int_array_ptr dims_arr = ggml_cann_create_int_array (dims ,4 ); 3559GGML_CANN_CALL_ACLNN_OP (ctx ,ReduceSum ,acl_eq .get (),dims_arr .get (), true, 3560ggml_cann_type_mapping (dst -> type ),acl_dst .get ()); 3561} 3562 3563void ggml_cann_step (ggml_backend_cann_context & ctx ,ggml_tensor * dst ) { 3564ggml_tensor * src0 = dst -> src [0 ]; 3565 3566acl_tensor_ptr acl_src = ggml_cann_create_tensor (src0 ); 3567acl_tensor_ptr acl_dst = ggml_cann_create_tensor (dst ); 3568 3569float alphaValue = 0.0f ; 3570acl_scalar_ptr alpha = nullptr ; 3571alpha = ggml_cann_create_scalar (& alphaValue , aclDataType::ACL_FLOAT ); 3572 3573GGML_CANN_CALL_ACLNN_OP (ctx ,GtScalar ,acl_src .get (),alpha .get (),acl_dst .get ()); 3574} 3575 3576void ggml_cann_softplus (ggml_backend_cann_context & ctx ,ggml_tensor * dst ) { 3577ggml_tensor * src0 = dst -> src [0 ]; 3578 3579acl_tensor_ptr acl_src = ggml_cann_create_tensor (src0 ); 3580acl_tensor_ptr acl_dst = ggml_cann_create_tensor (dst ); 3581 3582float beta_val = 1.0f ; 3583float threshold_val = 20.0f ; 3584acl_scalar_ptr beta = ggml_cann_create_scalar (& beta_val ,ACL_FLOAT ); 3585acl_scalar_ptr threshold = ggml_cann_create_scalar (& threshold_val ,ACL_FLOAT ); 3586 3587GGML_CANN_CALL_ACLNN_OP (ctx ,Softplus ,acl_src .get (),beta .get (),threshold .get (),acl_dst .get ()); 3588} 3589 3590void ggml_cann_geglu_quick (ggml_backend_cann_context & ctx ,ggml_tensor * dst ) { 3591auto gelu_quick_fn = [](ggml_backend_cann_context & ctx ,aclTensor * acl_src ,aclTensor * acl_dst ) { 3592GGML_CANN_CALL_ACLNN_OP (ctx ,GeluV2 ,acl_src ,0 ,acl_dst ); 3593 }; 3594ggml_cann_op_unary_gated (gelu_quick_fn ,ctx ,dst ); 3595} 3596 3597/** 3598* @brief Performs expert-specific matrix multiplication (MoE) with 3599* floating-point precision using the CANN backend. 3600* 3601* This function executes a matrix multiplication operation tailored for 3602* Mixture of Experts (MoE) models, where the input tensor is multiplied 3603* with expert-specific weight matrices. It uses the CANN backend for 3604* efficient computation and stores the result in the destination tensor `dst`. 3605* The operation may leverage identity-based optimizations or routing masks 3606* as part of sparse expert selection. 3607* 3608* @param ctx The context for executing CANN backend operations. 3609* @param dst The destination tensor where the MoE multiplication result 3610* will be stored. 3611* 3612* @note This function assumes floating-point data types and is designed for 3613* MoE architectures, possibly involving sparse expert routing. 3614*/ 3615static void ggml_cann_mul_mat_id_fp (ggml_backend_cann_context & ctx ,ggml_tensor * dst ) { 3616//dst [M, K, N, 1] 3617ggml_tensor * src0 = dst -> src [0 ];//src0 [D, M, A, 1] -> [D, M, K, 1] 3618ggml_tensor * src1 = dst -> src [1 ];//src1 [D, B, N, 1], B = K or B = 1 -> [D, 1, K, 1] 3619ggml_tensor * ids = dst -> src [2 ];//ids [K, N] 3620 3621GGML_ASSERT (src0 -> ne [3 ]== 1 ); 3622GGML_ASSERT (src1 -> ne [3 ]== 1 ); 3623GGML_ASSERT (dst -> ne [3 ]== 1 ); 3624 3625int64_t batch = src1 -> ne [2 ]; 3626GGML_ASSERT (batch == ids -> ne [1 ]); 3627 3628ggml_cann_pool_alloc export_allocator (ctx .pool (),src0 -> ne [0 ]* src0 -> ne [1 ]* ids -> ne [0 ]* ggml_element_size (src0 )); 3629void * export_ptr = export_allocator .get (); 3630for (int64_t i = 0 ;i < batch ;i ++ ) { 3631acl_tensor_ptr select_index = ggml_cann_create_tensor (ids ,ids -> ne ,ids -> nb ,1 ,ACL_FORMAT_ND ,i * ids -> nb [1 ]); 3632acl_tensor_ptr export_weight = ggml_cann_create_tensor (src0 ,src0 -> ne ,src0 -> nb ,3 ); 3633 3634int64_t select_export_ne []= {src0 -> ne [0 ],src0 -> ne [1 ],ids -> ne [0 ] }; 3635size_t select_export_nb [3 ]; 3636select_export_nb [0 ]= src0 -> nb [0 ]; 3637for (int k = 1 ;k < 3 ;k ++ ) { 3638select_export_nb [k ]= select_export_nb [k - 1 ]* select_export_ne [k - 1 ]; 3639 } 3640 3641acl_tensor_ptr select_export = 3642ggml_cann_create_tensor (export_ptr ,ggml_cann_type_mapping (src0 -> type ),ggml_element_size (src0 ), 3643select_export_ne ,select_export_nb ,3 ); 3644GGML_CANN_CALL_ACLNN_OP (ctx ,IndexSelect ,export_weight .get (),0 ,select_index .get (),select_export .get ()); 3645 3646int64_t select_transpose_ne []= {select_export_ne [1 ],select_export_ne [0 ],select_export_ne [2 ] }; 3647size_t select_transpose_nb []= {select_export_nb [1 ],select_export_nb [0 ],select_export_nb [2 ] }; 3648acl_tensor_ptr select_export_transpose = 3649ggml_cann_create_tensor (export_ptr ,ggml_cann_type_mapping (src0 -> type ),ggml_element_size (src0 ), 3650select_transpose_ne ,select_transpose_nb ,3 ); 3651 3652int64_t active_tensor_ne []= {src1 -> ne [0 ],1 ,src1 -> ne [1 ] }; 3653size_t active_tensor_nb []= {src1 -> nb [0 ],src1 -> nb [1 ],src1 -> nb [1 ] }; 3654acl_tensor_ptr active_tensor = 3655ggml_cann_create_tensor (src1 ,active_tensor_ne ,active_tensor_nb ,3 ,ACL_FORMAT_ND ,i * src1 -> nb [2 ]); 3656 3657int64_t dst_ne []= {dst -> ne [0 ],1 ,dst -> ne [1 ] }; 3658size_t dst_nb []= {dst -> nb [0 ],dst -> nb [1 ],dst -> nb [1 ] }; 3659acl_tensor_ptr acl_dst = ggml_cann_create_tensor (dst ,dst_ne ,dst_nb ,3 ,ACL_FORMAT_ND ,i * dst -> nb [2 ]); 3660 3661GGML_CANN_CALL_ACLNN_OP (ctx ,BatchMatMul ,active_tensor .get (),select_export_transpose .get (),acl_dst .get (),2 ); 3662 } 3663} 3664 3665/** 3666* @brief Performs quantized matrix multiplication for Mixture of Experts (MoE) 3667* models using the CANN backend. 3668* 3669* This function implements MUL_MAT_ID operation for quantized weight matrices 3670* (Q4_0 and Q8_0 formats). It selects expert-specific weight matrices based on 3671* the provided expert indices, and computes matrix multiplication using CANN's 3672* WeightQuantBatchMatmulV2 operator. 3673* 3674* The function performs the following steps: 3675* 1. Converts input/output tensors to F16 format if necessary 3676* 2. Uses IndexSelect to extract expert-specific weights and scales based on indices 3677* 3. Performs quantized matrix multiplication for each expert using WeightQuantBatchMatmulV2 3678* 4. Converts output back to the target type if needed 3679* 3680* Tensor shapes: 3681* - dst: [M, K, N, 1] - output tensor 3682* - src0: [D, M, A, 1] - quantized weight matrices (Q4_0 or Q8_0) 3683* - src1: [D, B, N, 1] - input activations (B = K for per-expert input, or B = 1 for broadcast) 3684* - ids: [K, N] - expert indices for routing 3685* 3686* @param ctx The CANN backend context for operation execution. 3687* @param dst The destination tensor where the multiplication result will be stored. 3688* 3689* @note Only Q4_0 and Q8_0 quantization formats are supported. 3690* @note The function handles automatic type conversion to/from F16 as needed by the hardware. 3691*/ 3692static void ggml_cann_mul_mat_id_quant (ggml_backend_cann_context & ctx ,ggml_tensor * dst ) { 3693// dst: [M, K, N, 1] 3694// src0: [D, M, A, 1] - quantized weights 3695// src1: [D, B, N, 1] - input activations, B = K or B = 1 3696// ids: [K, N] - expert indices 3697ggml_tensor * src0 = dst -> src [0 ]; 3698ggml_tensor * src1 = dst -> src [1 ]; 3699ggml_tensor * ids = dst -> src [2 ]; 3700 3701GGML_ASSERT (src0 -> ne [3 ]== 1 ); 3702GGML_ASSERT (src1 -> ne [3 ]== 1 ); 3703GGML_ASSERT (dst -> ne [3 ]== 1 ); 3704GGML_ASSERT (src1 -> ne [2 ]== ids -> ne [1 ]); 3705 3706const int64_t n_batches = ids -> ne [1 ]; 3707const int64_t n_select_experts = ids -> ne [0 ]; 3708const enum ggml_type type = src0 -> type ; 3709 3710const int32_t group_size = QK8_0 ;// Both Q4_0 and Q8_0 use group size of 32 3711GGML_ASSERT (group_size == QK4_0 ); 3712 3713// Calculate element size for quantized weights 3714const float weight_elem_size = 3715 (type == GGML_TYPE_Q4_0 ) ?0.5f : 3716 (type == GGML_TYPE_Q8_0 ) ?1.0f : 3717 (GGML_ABORT ("MUL_MAT_ID only supports Q4_0 and Q8_0" ),0.0f ); 3718 3719// Calculate scale offset in memory 3720const size_t weight_size = src0 -> ne [0 ]* src0 -> ne [1 ]* src0 -> ne [2 ]* weight_elem_size ; 3721const size_t scale_elem_size = sizeof (uint16_t ); 3722char * scale_data = (char * )src0 -> data + weight_size ; 3723 3724// Allocate buffers for selected expert weights and scales 3725const size_t selected_weight_size = src0 -> ne [0 ]* src0 -> ne [1 ]* n_select_experts * weight_elem_size ; 3726ggml_cann_pool_alloc selected_weight_alloc (ctx .pool (),selected_weight_size ); 3727void * selected_weight_buffer = selected_weight_alloc .get (); 3728 3729const size_t selected_scale_size = (src0 -> ne [0 ] /group_size )* src0 -> ne [1 ]* n_select_experts * scale_elem_size ; 3730ggml_cann_pool_alloc selected_scale_alloc (ctx .pool (),selected_scale_size ); 3731void * selected_scale_buffer = selected_scale_alloc .get (); 3732 3733// Helper lambda to allocate and cast tensor to F16 if needed 3734constexpr size_t f16_elem_size = sizeof (uint16_t ); 3735auto prepare_f16_buffer = [& ](ggml_tensor * tensor ,ggml_cann_pool_alloc & allocator , 3736bool need_cast = false)-> void * { 3737if (tensor -> type == GGML_TYPE_F16 ) { 3738return tensor -> data ; 3739 } 3740 3741size_t total_size = f16_elem_size ; 3742for (int i = 0 ;i < GGML_MAX_DIMS ;i ++ ) { 3743total_size *=tensor -> ne [i ]; 3744 } 3745void * buffer = allocator .alloc (total_size ); 3746 3747if (need_cast == false) { 3748return buffer ; 3749 } 3750 3751int64_t ne [GGML_MAX_DIMS ]; 3752size_t nb [GGML_MAX_DIMS ]= {f16_elem_size }; 3753for (int i = 0 ;i < GGML_MAX_DIMS ;i ++ ) { 3754ne [i ]= tensor -> ne [i ]; 3755if (i > 0 ) { 3756nb [i ]= nb [i - 1 ]* ne [i - 1 ]; 3757 } 3758 } 3759 3760acl_tensor_ptr src_tensor = ggml_cann_create_tensor (tensor ); 3761acl_tensor_ptr f16_tensor = ggml_cann_create_tensor (buffer ,ACL_FLOAT16 ,f16_elem_size ,ne ,nb ,GGML_MAX_DIMS ); 3762aclnn_cast (ctx ,src_tensor .get (),f16_tensor .get (),ACL_FLOAT16 ); 3763 3764return buffer ; 3765 }; 3766 3767// Prepare input and output buffers 3768ggml_cann_pool_alloc input_alloc (ctx .pool ()); 3769void * input_buffer = prepare_f16_buffer (src1 ,input_alloc , true); 3770 3771ggml_cann_pool_alloc output_alloc (ctx .pool ()); 3772void * output_buffer = prepare_f16_buffer (dst ,output_alloc , false); 3773 3774// Process each batch 3775for (int64_t batch_idx = 0 ;batch_idx < n_batches ;batch_idx ++ ) { 3776// Create index tensor for current batch 3777const size_t index_offset = batch_idx * ids -> nb [1 ]; 3778acl_tensor_ptr batch_indices = ggml_cann_create_tensor (ids ,ids -> ne ,ids -> nb ,1 ,ACL_FORMAT_ND ,index_offset ); 3779 3780// Select quantized weights using expert indices 3781// Q4_0 stores 2 values per byte, Q8_0 stores 1 value per byte 3782const int64_t weight_d = (type == GGML_TYPE_Q4_0 ) ?src0 -> ne [0 ] /2 :src0 -> ne [0 ]; 3783const int64_t weight_m = src0 -> ne [1 ]; 3784const int64_t weight_n_experts = src0 -> ne [2 ]; 3785 3786int64_t weight_ne [3 ]= {weight_d ,weight_m ,weight_n_experts }; 3787size_t weight_nb [3 ]= {sizeof (int8_t ),weight_d * sizeof (int8_t ),weight_d * weight_m * sizeof (int8_t ) }; 3788 3789acl_tensor_ptr all_weights = 3790ggml_cann_create_tensor (src0 -> data ,ACL_INT8 ,sizeof (int8_t ),weight_ne ,weight_nb ,3 ); 3791 3792int64_t selected_weight_ne [3 ]= {weight_d ,weight_m ,n_select_experts }; 3793size_t selected_weight_nb [3 ]= {sizeof (int8_t ),weight_d * sizeof (int8_t ), 3794weight_d * weight_m * sizeof (int8_t ) }; 3795 3796acl_tensor_ptr selected_weights = ggml_cann_create_tensor (selected_weight_buffer ,ACL_INT8 ,sizeof (int8_t ), 3797selected_weight_ne ,selected_weight_nb ,3 ); 3798 3799GGML_CANN_CALL_ACLNN_OP (ctx ,IndexSelect ,all_weights .get (),0 ,batch_indices .get (),selected_weights .get ()); 3800 3801// Select scales using the same expert indices 3802const int64_t scale_d = src0 -> ne [0 ] /group_size ; 3803int64_t scale_ne [3 ]= {scale_d ,weight_m ,weight_n_experts }; 3804size_t scale_nb [3 ]= {scale_elem_size ,scale_d * scale_elem_size ,scale_d * weight_m * scale_elem_size }; 3805 3806acl_tensor_ptr all_scales = 3807ggml_cann_create_tensor (scale_data ,ACL_FLOAT16 ,scale_elem_size ,scale_ne ,scale_nb ,3 ); 3808 3809int64_t selected_scale_ne [3 ]= {scale_d ,weight_m ,n_select_experts }; 3810size_t selected_scale_nb [3 ]= {scale_elem_size ,scale_d * scale_elem_size , 3811scale_d * weight_m * scale_elem_size }; 3812 3813acl_tensor_ptr selected_scales = ggml_cann_create_tensor (selected_scale_buffer ,ACL_FLOAT16 ,scale_elem_size , 3814selected_scale_ne ,selected_scale_nb ,3 ); 3815 3816GGML_CANN_CALL_ACLNN_OP (ctx ,IndexSelect ,all_scales .get (),0 ,batch_indices .get (),selected_scales .get ()); 3817 3818// Process each expert for current batch 3819// IndexSelect output layout: [D, M, K] in contiguous format 3820// WeightQuantBatchMatmulV2 expects: [M, D] with row-major stride 3821for (int64_t expert_idx = 0 ;expert_idx < n_select_experts ;expert_idx ++ ) { 3822// Determine input offset: broadcast if src1->ne[1]==1, otherwise use per-expert input 3823const size_t input_offset = 3824 (batch_idx * src1 -> ne [1 ]+ (src1 -> ne [1 ]== 1 ?0 :expert_idx ))* src1 -> ne [0 ]* f16_elem_size ; 3825const size_t output_offset = (batch_idx * dst -> ne [1 ]+ expert_idx )* dst -> ne [0 ]* f16_elem_size ; 3826 3827// Create weight view for current expert: [D, M, K] -> [M, D] 3828int64_t weight_view_ne [2 ]= {weight_m ,src0 -> ne [0 ] }; 3829float weight_view_nb [2 ]= {src0 -> ne [0 ]* weight_elem_size ,weight_elem_size }; 3830const size_t weight_view_offset = expert_idx * selected_weight_nb [2 ]; 3831 3832acl_tensor_ptr weight_view = 3833ggml_cann_create_tensor (selected_weight_buffer ,ggml_cann_type_mapping (type ),weight_elem_size , 3834weight_view_ne ,weight_view_nb ,2 ,ACL_FORMAT_ND ,weight_view_offset ); 3835 3836// Create scale view for current expert: [D, M, K] -> [M, D] 3837int64_t scale_view_ne [2 ]= {weight_m ,scale_d }; 3838size_t scale_view_nb [2 ]= {selected_scale_nb [1 ],selected_scale_nb [0 ] }; 3839const size_t scale_view_offset = expert_idx * selected_scale_nb [2 ]; 3840 3841acl_tensor_ptr scale_view = 3842ggml_cann_create_tensor (selected_scale_buffer ,ACL_FLOAT16 ,scale_elem_size ,scale_view_ne , 3843scale_view_nb ,2 ,ACL_FORMAT_ND ,scale_view_offset ); 3844 3845// Create input activation tensor [D, 1] 3846int64_t input_ne [2 ]= {src1 -> ne [0 ],1 }; 3847size_t input_nb [2 ]= {f16_elem_size ,src1 -> ne [0 ]* f16_elem_size }; 3848 3849acl_tensor_ptr input_tensor = ggml_cann_create_tensor (input_buffer ,ACL_FLOAT16 ,f16_elem_size ,input_ne , 3850input_nb ,2 ,ACL_FORMAT_ND ,input_offset ); 3851 3852// Create output tensor [M, 1] 3853int64_t output_ne [2 ]= {dst -> ne [0 ],1 }; 3854size_t output_nb [2 ]= {f16_elem_size ,dst -> ne [0 ]* f16_elem_size }; 3855 3856acl_tensor_ptr output_tensor = ggml_cann_create_tensor (output_buffer ,ACL_FLOAT16 ,f16_elem_size ,output_ne , 3857output_nb ,2 ,ACL_FORMAT_ND ,output_offset ); 3858 3859// Perform quantized matrix multiplication 3860GGML_CANN_CALL_ACLNN_OP (ctx ,WeightQuantBatchMatmulV2 ,input_tensor .get (),weight_view .get (), 3861scale_view .get (),nullptr ,nullptr ,nullptr ,nullptr ,group_size , 3862output_tensor .get ()); 3863 } 3864 } 3865 3866// Cast output back to original type if we used a temporary F16 buffer 3867if (dst -> type != GGML_TYPE_F16 ) { 3868int64_t ne [GGML_MAX_DIMS ]; 3869size_t nb [GGML_MAX_DIMS ]= {f16_elem_size }; 3870for (int i = 0 ;i < GGML_MAX_DIMS ;i ++ ) { 3871ne [i ]= dst -> ne [i ]; 3872if (i > 0 ) { 3873nb [i ]= nb [i - 1 ]* ne [i - 1 ]; 3874 } 3875 } 3876 3877acl_tensor_ptr f16_output = 3878ggml_cann_create_tensor (output_buffer ,ACL_FLOAT16 ,f16_elem_size ,ne ,nb ,GGML_MAX_DIMS ); 3879acl_tensor_ptr dst_tensor = ggml_cann_create_tensor (dst ); 3880 3881aclnn_cast (ctx ,f16_output .get (),dst_tensor .get (),ggml_cann_type_mapping (dst -> type )); 3882 } 3883} 3884 3885void ggml_cann_mul_mat_id (ggml_backend_cann_context & ctx ,ggml_tensor * dst ) { 3886const enum ggml_type type = dst -> src [0 ]-> type ; 3887switch (type ) { 3888case GGML_TYPE_F32 : 3889case GGML_TYPE_F16 : 3890ggml_cann_mul_mat_id_fp (ctx ,dst ); 3891break ; 3892case GGML_TYPE_Q4_0 : 3893case GGML_TYPE_Q8_0 : 3894ggml_cann_mul_mat_id_quant (ctx ,dst ); 3895break ; 3896default : 3897GGML_ABORT ("Unsupported type for mul_mat_id" ); 3898break ; 3899 } 3900} 3901 3902void ggml_cann_flash_attn_ext (ggml_backend_cann_context & ctx ,ggml_tensor * dst ) { 3903ggml_tensor * src0 = dst -> src [0 ];// q, fp32 | B, N, S, D (uncont) -> B, S, N, D (cont) 3904ggml_tensor * src1 = dst -> src [1 ];// k, fp16 | B, N, S, D (uncont) -> B, S, N, D (cont) 3905ggml_tensor * src2 = dst -> src [2 ];// v, fp16 | B, N, S, D (uncont) -> B, S, N, D (cont) 3906ggml_tensor * src3 = dst -> src [3 ];// mask, fp16 3907 3908// B, N, S, D (uncont) -> B, S, N, D (cont) 3909int64_t src0_bsnd_ne [GGML_MAX_DIMS ]; 3910memcpy (src0_bsnd_ne ,src0 -> ne ,GGML_MAX_DIMS * sizeof (int64_t )); 3911size_t src0_bsnd_nb [GGML_MAX_DIMS ]; 3912memcpy (src0_bsnd_nb ,src0 -> nb ,GGML_MAX_DIMS * sizeof (size_t )); 3913int64_t src1_bsnd_ne [GGML_MAX_DIMS ]; 3914memcpy (src1_bsnd_ne ,src1 -> ne ,GGML_MAX_DIMS * sizeof (int64_t )); 3915size_t src1_bsnd_nb [GGML_MAX_DIMS ]; 3916memcpy (src1_bsnd_nb ,src1 -> nb ,GGML_MAX_DIMS * sizeof (size_t )); 3917int64_t src2_bsnd_ne [GGML_MAX_DIMS ]; 3918memcpy (src2_bsnd_ne ,src2 -> ne ,GGML_MAX_DIMS * sizeof (int64_t )); 3919size_t src2_bsnd_nb [GGML_MAX_DIMS ]; 3920memcpy (src2_bsnd_nb ,src2 -> nb ,GGML_MAX_DIMS * sizeof (size_t )); 3921 3922auto transpose12 = [](int64_t * ne ,size_t * nb ) { 3923int64_t ne_tmp = ne [1 ]; 3924size_t nb_tmp = nb [1 ]; 3925ne [1 ]= ne [2 ]; 3926nb [1 ]= nb [2 ]; 3927ne [2 ]= ne_tmp ; 3928nb [2 ]= nb_tmp ; 3929 }; 3930 3931transpose12 (src0_bsnd_ne ,src0_bsnd_nb ); 3932transpose12 (src1_bsnd_ne ,src1_bsnd_nb ); 3933transpose12 (src2_bsnd_ne ,src2_bsnd_nb ); 3934 3935float maxBias = 0.0f ; 3936float scaleValue = 1.0f ; 3937float logitSoftcap = 0.0f ; 3938memcpy (& scaleValue , (float * )dst -> op_params + 0 ,sizeof (float )); 3939memcpy (& maxBias , (float * )dst -> op_params + 1 ,sizeof (float )); 3940memcpy (& logitSoftcap , (float * )dst -> op_params + 2 ,sizeof (float )); 3941 3942if (logitSoftcap == 0.0f ) { 3943size_t faElemSize = sizeof (uint16_t ); 3944auto faDataType = ACL_FLOAT16 ;//ACL_BF16; 3945 3946acl_tensor_ptr acl_q_tensor = nullptr ; 3947acl_tensor_ptr acl_k_tensor = nullptr ; 3948acl_tensor_ptr acl_v_tensor = nullptr ; 3949 3950// Step 1: cast the src0 (Query) to fp16 if needed 3951ggml_cann_pool_alloc src0_f16_allocator (ctx .pool ()); 3952void * src0_f16_buffer = nullptr ; 3953 3954if (ggml_cann_type_mapping (src0 -> type )!= faDataType ) { 3955acl_tensor_ptr acl_src0_f32_tensor = 3956ggml_cann_create_tensor (src0 ,src0_bsnd_ne ,src0_bsnd_nb ,GGML_MAX_DIMS ); 3957src0_f16_buffer = src0_f16_allocator .alloc (ggml_nelements (src0 )* faElemSize ); 3958 3959int64_t * src0_f16_ne = src0_bsnd_ne ; 3960size_t src0_f16_nb [GGML_MAX_DIMS ]; 3961src0_f16_nb [0 ]= sizeof (uint16_t ); 3962for (int i = 1 ;i < GGML_MAX_DIMS ;++ i ) { 3963src0_f16_nb [i ]= src0_f16_nb [i - 1 ]* src0_f16_ne [i - 1 ]; 3964 } 3965 3966acl_q_tensor = ggml_cann_create_tensor (src0_f16_buffer ,faDataType ,faElemSize ,src0_f16_ne ,src0_f16_nb , 3967GGML_MAX_DIMS ); 3968aclnn_cast (ctx ,acl_src0_f32_tensor .get (),acl_q_tensor .get (),faDataType ); 3969 }else { 3970acl_q_tensor = ggml_cann_create_tensor (src0 ,src0_bsnd_ne ,src0_bsnd_nb ,GGML_MAX_DIMS ); 3971 } 3972 3973// Step 2: create the acl tensors for src1 (Key), src2 (Value), 3974// and the direct output from FusedInferAttention 3975 3976acl_k_tensor = ggml_cann_create_tensor (src1 ,src1_bsnd_ne ,src1_bsnd_nb ,GGML_MAX_DIMS ); 3977acl_v_tensor = ggml_cann_create_tensor (src2 ,src2_bsnd_ne ,src2_bsnd_nb ,GGML_MAX_DIMS ); 3978 3979// Step 2.5: Pad Q, K, V along head dimension if D is not a multiple of 16 3980// (required by FusedInferAttentionScoreV2) 3981const int64_t D = src0 -> ne [0 ]; 3982const int64_t D_padded = GGML_PAD (D ,16 ); 3983const bool needs_padding = (D != D_padded ); 3984 3985ggml_cann_pool_alloc q_pad_allocator (ctx .pool ()); 3986ggml_cann_pool_alloc k_pad_allocator (ctx .pool ()); 3987ggml_cann_pool_alloc v_pad_allocator (ctx .pool ()); 3988 3989if (needs_padding ) { 3990int64_t paddings []= {0 ,D_padded - D ,0 ,0 ,0 ,0 ,0 ,0 }; 3991 3992auto pad_fa_tensor = [& ](acl_tensor_ptr & tensor ,const int64_t * bsnd_ne , 3993ggml_cann_pool_alloc & allocator ) { 3994int64_t pad_ne [GGML_MAX_DIMS ]= {D_padded ,bsnd_ne [1 ],bsnd_ne [2 ],bsnd_ne [3 ] }; 3995size_t pad_nb [GGML_MAX_DIMS ]; 3996pad_nb [0 ]= faElemSize ; 3997for (int i = 1 ;i < GGML_MAX_DIMS ;++ i ) { 3998pad_nb [i ]= pad_nb [i - 1 ]* pad_ne [i - 1 ]; 3999 } 4000int64_t nelements = pad_ne [0 ]* pad_ne [1 ]* pad_ne [2 ]* pad_ne [3 ]; 4001void * buffer = allocator .alloc (nelements * faElemSize ); 4002acl_tensor_ptr padded = 4003ggml_cann_create_tensor (buffer ,faDataType ,faElemSize ,pad_ne ,pad_nb ,GGML_MAX_DIMS ); 4004aclnn_pad (ctx ,tensor .get (),padded .get (),paddings ); 4005tensor = std::move (padded ); 4006 }; 4007 4008pad_fa_tensor (acl_q_tensor ,src0_bsnd_ne ,q_pad_allocator ); 4009pad_fa_tensor (acl_k_tensor ,src1_bsnd_ne ,k_pad_allocator ); 4010pad_fa_tensor (acl_v_tensor ,src2_bsnd_ne ,v_pad_allocator ); 4011 4012src0_bsnd_ne [0 ]= D_padded ; 4013src1_bsnd_ne [0 ]= D_padded ; 4014src2_bsnd_ne [0 ]= D_padded ; 4015 } 4016 4017// Step 3: create the PSEShift tensor if needed 4018// this tensor is considered as mask (f16) in the llama.cpp 4019acl_tensor_ptr bcast_pse_tensor ; 4020ggml_cann_pool_alloc bcast_pse_allocator (ctx .pool ()); 4021if (src3 != nullptr ) { 4022// Construct the truncated pse tensor (common for prefill/decode) 4023int64_t trunc_pse_ne [GGML_MAX_DIMS ]= { 4024src3 -> ne [0 ],// D 4025src0 -> ne [1 ],// S (number of Q tokens) 4026src3 -> ne [2 ],// mask N 4027src3 -> ne [3 ]// B 4028 }; 4029size_t * trunc_pse_nb = src3 -> nb ; 4030 4031acl_tensor_ptr acl_mask_f16_trunc_tensor = ggml_cann_create_tensor ( 4032src3 -> data ,ACL_FLOAT16 ,sizeof (uint16_t ),trunc_pse_ne ,trunc_pse_nb ,GGML_MAX_DIMS ); 4033 4034int64_t bcast_pse_ne [GGML_MAX_DIMS ]; 4035size_t bcast_pse_nb [GGML_MAX_DIMS ]; 4036bcast_pse_ne [0 ]= src3 -> ne [0 ];// D 4037bcast_pse_ne [1 ]= src0 -> ne [1 ];// S 4038bcast_pse_ne [2 ]= src0 -> ne [2 ];// N (num_heads) 4039bcast_pse_ne [3 ]= src3 -> ne [3 ];// B 4040if (maxBias == 0.0f ) { 4041// When maxBias == 0.0f, use nb = 0 reduce once repeat (Qwen2) 4042// Construct the bcast tensor (simulate repeat on the head dimension using stride=0) 4043bcast_pse_nb [0 ]= sizeof (uint16_t ); 4044bcast_pse_nb [1 ]= bcast_pse_nb [0 ]* bcast_pse_ne [0 ]; 4045bcast_pse_nb [2 ]= 0 ;// <---- the head dimension shares the same data 4046bcast_pse_nb [3 ]= src3 -> nb [3 ]; 4047 4048bcast_pse_tensor = ggml_cann_create_tensor (src3 -> data ,ACL_FLOAT16 ,sizeof (uint16_t ),bcast_pse_ne , 4049bcast_pse_nb ,GGML_MAX_DIMS ); 4050 4051 }else { 4052bcast_pse_nb [0 ]= sizeof (uint16_t ); 4053for (int i = 1 ;i < GGML_MAX_DIMS ;i ++ ) { 4054bcast_pse_nb [i ]= bcast_pse_nb [i - 1 ]* bcast_pse_ne [i - 1 ]; 4055 } 4056 4057void * bcast_pse_buffer = 4058bcast_pse_allocator .alloc (ggml_nelements (src3 )* src0 -> ne [2 ]* sizeof (uint16_t )); 4059 4060bcast_pse_tensor = ggml_cann_create_tensor (bcast_pse_buffer ,ACL_FLOAT16 ,sizeof (uint16_t ), 4061bcast_pse_ne ,bcast_pse_nb ,GGML_MAX_DIMS ); 4062 4063int64_t repeats []= {1 ,src0 -> ne [2 ],1 ,1 }; 4064aclnn_repeat (ctx ,acl_mask_f16_trunc_tensor .get (),bcast_pse_tensor .get (),repeats ); 4065 4066// alibi 4067// Compute the slope if needed. Derived from ggml_cann_softmax(). 4068const int64_t n_heads = src0 -> ne [2 ]; 4069ggml_cann_pool_alloc slope_allocator (ctx .pool (),n_heads * sizeof (uint16_t )); 4070void * slope_buffer = slope_allocator .get (); 4071aclnn_get_slope (ctx ,n_heads ,slope_buffer ,maxBias ,GGML_TYPE_F16 ); 4072 4073int64_t slope_ne []= {1 ,1 ,n_heads ,1 }; 4074size_t slope_nb [GGML_MAX_DIMS ]; 4075slope_nb [0 ]= sizeof (uint16_t ); 4076for (int i = 1 ;i < GGML_MAX_DIMS ;i ++ ) { 4077slope_nb [i ]= slope_nb [i - 1 ]* slope_ne [0 ]; 4078 } 4079 4080acl_tensor_ptr slope_tensor = ggml_cann_create_tensor (slope_buffer ,ACL_FLOAT16 ,sizeof (uint16_t ), 4081slope_ne ,slope_nb ,GGML_MAX_DIMS ); 4082GGML_CANN_CALL_ACLNN_OP (ctx ,InplaceMul ,bcast_pse_tensor .get (),slope_tensor .get ()); 4083 } 4084 } 4085 4086// Step 4: set the inputs for FusedInferAttention. 4087acl_tensor_list_ptr acl_k_tensor_list = ggml_cann_create_tensor_list (acl_k_tensor ); 4088acl_tensor_list_ptr acl_v_tensor_list = ggml_cann_create_tensor_list (acl_v_tensor ); 4089 4090int64_t numHeads = src0 -> ne [2 ];// N 4091int64_t numKeyValueHeads = src1 -> ne [2 ]; 4092// double scaleValue = 1 / sqrt(src0->ne[0]); // 1/sqrt(d) 4093int64_t preTokens = 65535 ; 4094int64_t nextTokens = 65535 ; 4095char layout [5 ]= {'B' ,'S' ,'N' ,'D' ,0 }; 4096int64_t sparseMode = 0 ; 4097int64_t innerPrecise = (src0 -> ne [1 ]== 1 ) ?0 :2 ; 4098int64_t blockSize = 0 ; 4099int64_t antiquantMode = 0 ; 4100bool softmaxLseFlag = false; 4101int64_t keyAntiquantMode = 0 ; 4102int64_t valueAntiquantMode = 0 ; 4103 4104GGML_ASSERT (dst -> type == GGML_TYPE_F32 || dst -> type == GGML_TYPE_F16 ); 4105acl_tensor_ptr fa_dst_tensor ; 4106ggml_cann_pool_alloc out_f16_allocator (ctx .pool ()); 4107if (dst -> type == GGML_TYPE_F32 || needs_padding ) { 4108int64_t * out_f16_ne = src0_bsnd_ne ; 4109size_t out_f16_nb [GGML_MAX_DIMS ]; 4110out_f16_nb [0 ]= faElemSize ; 4111for (int i = 1 ;i < GGML_MAX_DIMS ;++ i ) { 4112out_f16_nb [i ]= out_f16_nb [i - 1 ]* out_f16_ne [i - 1 ]; 4113 } 4114int64_t out_nelements = out_f16_ne [0 ]* out_f16_ne [1 ]* out_f16_ne [2 ]* out_f16_ne [3 ]; 4115void * out_f16_buffer = out_f16_allocator .alloc (out_nelements * faElemSize ); 4116 4117fa_dst_tensor = 4118ggml_cann_create_tensor (out_f16_buffer ,faDataType ,faElemSize ,out_f16_ne ,out_f16_nb ,GGML_MAX_DIMS ); 4119 }else { 4120fa_dst_tensor = ggml_cann_create_tensor (dst ); 4121 } 4122 4123GGML_CANN_CALL_ACLNN_OP (ctx ,FusedInferAttentionScoreV2 ,acl_q_tensor .get (),acl_k_tensor_list .get (), 4124acl_v_tensor_list .get (),// q, k, v 4125bcast_pse_tensor .get (),nullptr ,// pse, mask 4126nullptr ,nullptr ,// actSeqLen, actSeqLenkv 4127nullptr ,nullptr ,// deqScale1, quantScale1 4128nullptr ,nullptr ,nullptr ,// deqScale2, quantScale2, quantOffset2 4129nullptr ,nullptr ,// antiquantScale, antiquantOffset 4130nullptr ,// blockTable 4131nullptr ,nullptr ,// qPadSize, kvPadSize 4132nullptr ,nullptr ,// kAntiquantScale, kAntiQuantOffset 4133nullptr ,nullptr ,// vAntiquantScale, vAntiQuantOffset 4134nullptr ,nullptr ,nullptr ,// kSharedPrefix, vSharedPrefix, actSharedLen 4135numHeads ,scaleValue ,// heads, scaleValue 4136preTokens ,nextTokens ,// preTokens, nextTokens 4137layout ,// inputLayout 4138numKeyValueHeads ,// numKVHeads 4139sparseMode ,innerPrecise ,// sparseMode, innerPrecise 4140blockSize ,antiquantMode ,// blockSize, antiquantMode 4141softmaxLseFlag ,// softmaxLseFlag 4142keyAntiquantMode ,valueAntiquantMode ,// keyAntiqMode, valueAntiqMode 4143fa_dst_tensor .get (),// attentionOut 4144nullptr // softmaxLse 4145 ); 4146 4147// Step 6: post-processing — slice padded output and/or cast to f32 4148if (needs_padding ) { 4149ggml_cann_pool_alloc sliced_f16_allocator (ctx .pool ()); 4150 4151if (dst -> type == GGML_TYPE_F32 ) { 4152int64_t sliced_ne [GGML_MAX_DIMS ]= {D ,src0_bsnd_ne [1 ],src0_bsnd_ne [2 ],src0_bsnd_ne [3 ] }; 4153size_t sliced_nb [GGML_MAX_DIMS ]; 4154sliced_nb [0 ]= faElemSize ; 4155for (int i = 1 ;i < GGML_MAX_DIMS ;++ i ) { 4156sliced_nb [i ]= sliced_nb [i - 1 ]* sliced_ne [i - 1 ]; 4157 } 4158int64_t sliced_nelements = sliced_ne [0 ]* sliced_ne [1 ]* sliced_ne [2 ]* sliced_ne [3 ]; 4159void * sliced_buffer = sliced_f16_allocator .alloc (sliced_nelements * faElemSize ); 4160acl_tensor_ptr sliced_f16_tensor = ggml_cann_create_tensor (sliced_buffer ,faDataType ,faElemSize , 4161sliced_ne ,sliced_nb ,GGML_MAX_DIMS ); 4162 4163GGML_CANN_CALL_ACLNN_OP (ctx ,Slice ,fa_dst_tensor .get (), 4164 (int64_t )-1 , (int64_t )0 ,D , (int64_t )1 ,sliced_f16_tensor .get ()); 4165 4166acl_tensor_ptr acl_dst_tensor = ggml_cann_create_tensor (dst ); 4167aclnn_cast (ctx ,sliced_f16_tensor .get (),acl_dst_tensor .get (),ggml_cann_type_mapping (dst -> type )); 4168 }else { 4169acl_tensor_ptr acl_dst_tensor = ggml_cann_create_tensor (dst ); 4170GGML_CANN_CALL_ACLNN_OP (ctx ,Slice ,fa_dst_tensor .get (), 4171 (int64_t )-1 , (int64_t )0 ,D , (int64_t )1 ,acl_dst_tensor .get ()); 4172 } 4173 }else if (dst -> type == GGML_TYPE_F32 ) { 4174acl_tensor_ptr acl_dst_tensor = ggml_cann_create_tensor (dst ); 4175aclnn_cast (ctx ,fa_dst_tensor .get (),acl_dst_tensor .get (),ggml_cann_type_mapping (dst -> type )); 4176 } 4177 }else { 4178GGML_ABORT ("Function is not implemented." ); 4179 } 4180} 4181 4182static void ggml_cann_out_prod_fp (ggml_backend_cann_context & ctx ,ggml_tensor * dst ) { 4183ggml_tensor * src0 = dst -> src [0 ];// weight [ne00=m, ne01=K, ne02, ne03] 4184ggml_tensor * src1 = dst -> src [1 ];// input [ne10=n, ne11=K, ne12, ne13] 4185GGML_TENSOR_BINARY_OP_LOCALS 4186 4187// dst[i,j] = sum_k src0[i,k] * src1[j,k] i.e. dst = src0 @ src1^T. 4188// 4189// ggml_cann_create_tensor reverses dimension order, so ACL sees: 4190// acl_src0 slice: ggml[m,K] -> ACL[K,m] 4191// acl_src1 slice: ggml[n,K] -> ACL[K,n] 4192// acl_dst slice: ggml[m,n] -> ACL[n,m] 4193// 4194// Build a transposed view of src1 by swapping ne[0]/ne[1]: 4195// src1_t: ggml[K,n] (swapped strides) -> ACL[n,K] 4196// 4197// Matmul(src1_t [n,K], src0 [K,m]) = [n,m] = acl_dst ✓ 4198// 4199// The outer batch loop is kept because src0 may have fewer batch slices than 4200// dst (ne02 <= ne2, ne03 <= ne3): this is a strided-broadcast not supported 4201// by standard CANN Matmul broadcasting. 4202 4203const aclDataTypesrc0_acl_type = ggml_cann_type_mapping (src0 -> type ); 4204const aclDataType src1_acl_type = ggml_cann_type_mapping (src1 -> type ); 4205const aclDataType dst_acl_type = ggml_cann_type_mapping (dst -> type ); 4206const size_t src0_type_sz = ggml_type_size (src0 -> type ); 4207const size_t src1_type_sz = ggml_type_size (src1 -> type ); 4208const size_t dst_type_sz = ggml_type_size (dst -> type ); 4209 4210const int64_t dps2 = ne2 /ne02 ; 4211const int64_t dps3 = ne3 /ne03 ; 4212 4213for (int64_t i3 = 0 ;i3 < ne3 ;i3 ++ ) { 4214for (int64_t i2 = 0 ;i2 < ne2 ;i2 ++ ) { 4215const int64_t i02 = i2 /dps2 ; 4216const int64_t i03 = i3 /dps3 ; 4217 4218// src0 2D slice at [i02, i03]: ggml [m, K] -> ACL [K, m] 4219int64_t src0_ne [2 ]= {ne00 ,ne01 }; 4220size_t src0_nb [2 ]= {nb00 ,nb01 }; 4221acl_tensor_ptr acl_src0_s = ggml_cann_create_tensor ( 4222 (char * )src0 -> data + i02 * nb02 + i03 * nb03 , 4223src0_acl_type ,src0_type_sz ,src0_ne ,src0_nb ,2 ); 4224 4225// src1 transposed 2D slice at [i2, i3]: swap ne/nb -> ggml[K,n] -> ACL[n,K] 4226int64_t src1_t_ne [2 ]= {ne11 ,ne10 }; 4227size_t src1_t_nb [2 ]= {nb11 ,nb10 }; 4228acl_tensor_ptr acl_src1_t = ggml_cann_create_tensor ( 4229 (char * )src1 -> data + i2 * nb12 + i3 * nb13 , 4230src1_acl_type ,src1_type_sz ,src1_t_ne ,src1_t_nb ,2 ); 4231 4232// dst 2D slice at [i2, i3]: ggml [m, n] -> ACL [n, m] 4233int64_t dst_ne [2 ]= {ne0 ,ne1 }; 4234size_t dst_nb [2 ]= {nb0 ,nb1 }; 4235acl_tensor_ptr acl_dst_s = ggml_cann_create_tensor ( 4236 (char * )dst -> data + i2 * nb2 + i3 * nb3 , 4237dst_acl_type ,dst_type_sz ,dst_ne ,dst_nb ,2 ); 4238 4239// Matmul(src1_t [n,K], src0 [K,m]) = [n,m] = acl_dst_s ✓ 4240GGML_CANN_CALL_ACLNN_OP (ctx ,Matmul , 4241acl_src1_t .get (),acl_src0_s .get (),acl_dst_s .get (), (int8_t )1 ); 4242 } 4243 } 4244} 4245 4246void ggml_cann_out_prod (ggml_backend_cann_context & ctx ,ggml_tensor * dst ) { 4247ggml_tensor * src0 = dst -> src [0 ]; 4248 4249const enum ggml_type type = src0 -> type ; 4250 4251switch (type ) { 4252case GGML_TYPE_F32 : 4253case GGML_TYPE_F16 : 4254ggml_cann_out_prod_fp (ctx ,dst ); 4255break ; 4256default : 4257GGML_ABORT ("Unsupport type for GGML_OP_OUT_PROD" ); 4258break ; 4259 } 4260} 4261 4262void ggml_cann_ssm_conv (ggml_backend_cann_context & ctx ,ggml_tensor * dst ) { 4263ggml_tensor * src0 = dst -> src [0 ];// conv_x 4264ggml_tensor * src1 = dst -> src [1 ];// conv1d.weight 4265 4266// This op is currently defined only for F32 in ggml_cpu 4267GGML_ASSERT (src0 -> type == GGML_TYPE_F32 ); 4268GGML_ASSERT (src1 -> type == GGML_TYPE_F32 ); 4269GGML_ASSERT (dst -> type == GGML_TYPE_F32 ); 4270 4271// Shapes follow ggml_compute_forward_ssm_conv_f32 4272const int64_t nc = src1 -> ne [0 ];// d_conv 4273const int64_t ncs = src0 -> ne [0 ];// d_conv - 1 + n_t 4274const int64_t nr = src0 -> ne [1 ];// d_inner 4275const int64_t n_s = src0 -> ne [2 ];// n_seqs 4276 4277const int64_t n_t = dst -> ne [1 ];// tokens per sequence 4278 4279GGML_ASSERT (dst -> ne [0 ]== nr );// dst: {d_inner, n_t, n_s} 4280GGML_ASSERT (src1 -> ne [1 ]== nr );// weight: {d_conv, d_inner} 4281GGML_ASSERT (ncs == nc - 1 + n_t );// conv_x: {d_conv - 1 + n_t, d_inner, n_s} 4282GGML_ASSERT (src0 -> nb [0 ]== sizeof (float )); 4283GGML_ASSERT (src1 -> nb [0 ]== sizeof (float )); 4284 4285// --- Build CANN tensors --- 4286 4287// 1) Input: conv_x as NCL 4288// 4289// src0->ne = { ncs, nr, n_s, 1 } // {L_in, C, N} 4290// Passing ACL_FORMAT_NCL here means: 4291// reversed dims -> [N, C, L_in] = [n_s, nr, ncs] 4292acl_tensor_ptr acl_x = ggml_cann_create_tensor (src0 ,src0 -> ne ,src0 -> nb ,3 ,ACL_FORMAT_NCL ); 4293 4294// 2) Weights: depthwise conv kernel, view src1 as {K, 1, C} 4295// 4296// src1 original: ne = { nc, nr, 1, 1 } // [K, C, 1, 1] 4297// we want a view: ne_w = { nc, 1, nr } // [K, 1, C] 4298// so that reversed dims -> [C, 1, K] which matches 4299// [out_channels, in_channels/groups, kernel_size] 4300int64_t w_ne [GGML_MAX_DIMS ]= {nc ,1 ,nr ,1 };// [K, 1 input ch. per group, C groups] 4301// Layout: src1 data is [K, C] with 4302// offset(k, c) = k*nb0 + c*nb1 4303// We want offset_w(k, 0, c) = k*nb0 + c*nb1, 4304// so we can reuse nb0 and nb1, and set nb2 = nb1. 4305size_t w_nb [GGML_MAX_DIMS ]= {src1 -> nb [0 ],src1 -> nb [1 ],src1 -> nb [1 ],src1 -> nb [3 ] };// same as src1 4306 4307acl_tensor_ptr acl_w = ggml_cann_create_tensor (src1 -> data ,ggml_cann_type_mapping (src1 -> type ), 4308ggml_type_size (src1 -> type ),w_ne ,w_nb ,3 ,ACL_FORMAT_NCL ); 4309 4310// 3) Output: dst is { d_inner, n_t, n_s } (CLN) 4311// 4312// We need an NCL view of the same buffer: 4313// desired NCL logical shape: { L_out = n_t, C = nr, N = n_s } 4314// 4315// Original CLN layout: 4316// dst->ne = { nr, n_t, n_s } 4317// dst->nb[0] = sizeof(float) 4318// dst->nb[1] = nr * sizeof(float) 4319// dst->nb[2] = nr * n_t * sizeof(float) 4320// 4321// We want offset_new(L, C, N) = offset_orig(C, L, N). 4322// Choose: 4323// nb_y[0] = nr * sizeof(float); // step in L 4324// nb_y[1] = sizeof(float); // step in C 4325// nb_y[2] = nr * n_t * sizeof(float); // step in N 4326int64_t y_ne [GGML_MAX_DIMS ]= {n_t ,nr ,n_s ,1 };// [L_out, C, N] 4327size_t y_nb [GGML_MAX_DIMS ]= {dst -> ne [0 ]* sizeof (float ),sizeof (float ),dst -> ne [0 ]* dst -> ne [1 ]* sizeof (float ), 4328dst -> nb [3 ] };// [nr, 1, nr * n_t] 4329 4330acl_tensor_ptr acl_y = ggml_cann_create_tensor (dst -> data ,ggml_cann_type_mapping (dst -> type ), 4331ggml_type_size (dst -> type ),y_ne ,y_nb ,3 ,ACL_FORMAT_NCL ); 4332 4333// --- Conv1d parameters: depthwise, stride 1, no padding ("valid") --- 4334int64_t strideVal [1 ]= {1 }; 4335int64_t paddingVal [1 ]= {0 }; 4336int64_t dilationVal [1 ]= {1 }; 4337 4338acl_int_array_ptr stride = ggml_cann_create_int_array (strideVal ,1 ); 4339acl_int_array_ptr padding = ggml_cann_create_int_array (paddingVal ,1 ); 4340acl_int_array_ptr dilation = ggml_cann_create_int_array (dilationVal ,1 ); 4341 4342const bool transposed = false; 4343const int64_t groups = nr ;// depthwise: one group per inner dim 4344int8_t cubeMathType = 0 ; 4345 4346#ifdef ASCEND_310P 4347cubeMathType = 1 ; 4348#endif 4349 4350GGML_CANN_CALL_ACLNN_OP (ctx ,Convolution , 4351acl_x .get (),// input: N, C, L_in = ncs 4352acl_w .get (),// weight: [C, 1, K] with groups=nr 4353nullptr ,// bias 4354stride .get (),padding .get (),dilation .get (),transposed , 4355padding .get (),// output padding (unused for non-transposed) 4356groups ,acl_y .get (),cubeMathType ); 4357} 4358 4359void ggml_cann_op_add_rms_norm_fused (ggml_backend_cann_context & ctx , 4360ggml_tensor * add_node , 4361ggml_tensor * rms_norm_node ) { 4362// Get the two input tensors for ADD operation 4363ggml_tensor * x1 = add_node -> src [0 ]; 4364ggml_tensor * x2 = add_node -> src [1 ]; 4365 4366// Create ACL tensors for the two ADD inputs 4367acl_tensor_ptr acl_x1 = ggml_cann_create_tensor (x1 ); 4368acl_tensor_ptr acl_x2 = ggml_cann_create_tensor (x2 ); 4369 4370// Get epsilon parameter from rms_norm_tensor 4371float eps ; 4372memcpy (& eps ,rms_norm_node -> op_params ,sizeof (float )); 4373 4374// Build gamma tensor (RMS normalization scaling factor) 4375// Gamma should match the normalized dimensions (last dimension of x1) 4376size_t acl_gamma_nb [GGML_MAX_DIMS ]; 4377acl_gamma_nb [0 ]= ggml_type_size (rms_norm_node -> type ); 4378for (int i = 1 ;i < GGML_MAX_DIMS ;i ++ ) { 4379acl_gamma_nb [i ]= acl_gamma_nb [i - 1 ]* x1 -> ne [i - 1 ]; 4380 } 4381acl_tensor_ptr acl_gamma = 4382get_cache_acl_tensor (ctx ,& ctx .rms_norm_one_tensor_cache .cache ,ctx .rms_norm_one_tensor_cache .size ,x1 -> ne , 4383acl_gamma_nb ,rms_norm_node -> type , 43841 ,// dims - only the last dimension 43851.0f // value 4386 ); 4387 4388// Build rstdOut tensor (output for normalized standard deviation) 4389// Shape should be the dimensions that are NOT normalized 4390int64_t acl_rstd_ne []= {1 ,x1 -> ne [1 ],x1 -> ne [2 ],x1 -> ne [3 ] }; 4391size_t acl_rstd_nb [GGML_MAX_DIMS - 1 ]; 4392acl_rstd_nb [0 ]= sizeof (float ); 4393for (int i = 1 ;i < GGML_MAX_DIMS - 1 ;i ++ ) { 4394acl_rstd_nb [i ]= acl_rstd_nb [i - 1 ]* acl_rstd_ne [i - 1 ]; 4395 } 4396acl_tensor_ptr acl_rstd = 4397get_cache_acl_tensor (ctx ,& ctx .rms_norm_zero_tensor_cache .cache ,ctx .rms_norm_zero_tensor_cache .size , 4398acl_rstd_ne ,acl_rstd_nb ,GGML_TYPE_F32 ,GGML_MAX_DIMS , 43990.0f // value 4400 ); 4401 4402acl_tensor_ptr acl_xout = ggml_cann_create_tensor (add_node ); 4403 4404// Create yOut tensor (final output after RMS normalization) 4405acl_tensor_ptr acl_yout = ggml_cann_create_tensor (rms_norm_node ); 4406 4407// Call fused ADD + RMS_NORM operator 4408GGML_CANN_CALL_ACLNN_OP (ctx ,AddRmsNorm ,acl_x1 .get (),acl_x2 .get (),acl_gamma .get (), 4409eps ,// double type 4410acl_yout .get (),acl_rstd .get (),acl_xout .get ()); 4411} 4412 4413void ggml_cann_gated_linear_attn (ggml_backend_cann_context & ctx ,ggml_tensor * dst ) { 4414ggml_tensor * k = dst -> src [0 ]; 4415ggml_tensor * v = dst -> src [1 ]; 4416ggml_tensor * q = dst -> src [2 ]; 4417ggml_tensor * g = dst -> src [3 ]; 4418ggml_tensor * s = dst -> src [4 ]; 4419 4420int64_t B = dst -> src [4 ]-> ne [1 ]; 4421int64_t T = dst -> src [0 ]-> ne [2 ]; 4422int64_t H = dst -> src [0 ]-> ne [1 ]; 4423int64_t C = dst -> ne [0 ]; 4424int64_t D = C /H ; 4425int64_t L = T /B ; 4426 4427int64_t ne_qkg [2 ]= {1 ,D }; 4428int64_t ne_s [2 ]= {D ,D }; 4429int64_t ne_st [2 ]= {ne_s [1 ],ne_s [0 ] }; 4430int64_t ne_vo [2 ]= {D ,1 }; 4431int64_t ne_q [1 ]= {D }; 4432size_t nb_base = ggml_type_size (k -> type ); 4433size_t nb_qkg [2 ]= {nb_base ,nb_base }; 4434size_t nb_s [2 ]= {nb_base ,D * nb_base }; 4435size_t nb_st [2 ]= {nb_s [1 ],nb_s [0 ] }; 4436size_t nb_vo [2 ]= {nb_base ,D * nb_base }; 4437size_t nb_q [1 ]= {nb_base }; 4438 4439const float scale = ggml_get_op_params_f32 (dst ,0 ); 4440 4441acl_tensor_ptr acl_s = ggml_cann_create_tensor (s ,s -> ne ,s -> nb ,2 ,ACL_FORMAT_ND ); 4442acl_tensor_ptr new_state = ggml_cann_create_tensor (dst ,s -> ne ,s -> nb ,2 ,ACL_FORMAT_ND , (B * L * H * D )* nb_base ); 4443cann_copy (ctx ,acl_s .get (),new_state .get ()); 4444 4445for (int64_t b = 0 ;b < B ;b ++ ) { 4446for (int64_t h = 0 ;h < H ;h ++ ) { 4447size_t s_offset = (b * (H * D * D )+ h * (D * D ))* nb_base ; 4448// D * D 4449acl_tensor_ptr acl_s_new = 4450ggml_cann_create_tensor (dst ,ne_s ,nb_s ,2 ,ACL_FORMAT_ND , (B * L * H * D )* nb_base + s_offset ); 4451acl_tensor_ptr acl_s_new_t = 4452ggml_cann_create_tensor (dst ,ne_st ,nb_st ,2 ,ACL_FORMAT_ND , (B * L * H * D )* nb_base + s_offset ); 4453for (int64_t l = 0 ;l < L ;l ++ ) { 4454size_t qkvgo_offset = (b * (L * H * D )+ l * (H * D )+ h * (D ))* nb_base ; 4455// D * 1 4456acl_tensor_ptr acl_k = ggml_cann_create_tensor (k ,ne_qkg ,nb_qkg ,2 ,ACL_FORMAT_ND ,qkvgo_offset ); 4457acl_tensor_ptr acl_g = ggml_cann_create_tensor (g ,ne_qkg ,nb_qkg ,2 ,ACL_FORMAT_ND ,qkvgo_offset ); 4458// D 4459acl_tensor_ptr acl_q = ggml_cann_create_tensor (q ,ne_q ,nb_q ,1 ,ACL_FORMAT_ND ,qkvgo_offset ); 4460// 1 * D 4461acl_tensor_ptr acl_v = ggml_cann_create_tensor (v ,ne_vo ,nb_vo ,2 ,ACL_FORMAT_ND ,qkvgo_offset ); 4462// D 4463acl_tensor_ptr acl_o = ggml_cann_create_tensor (dst ,ne_q ,nb_q ,1 ,ACL_FORMAT_ND ,qkvgo_offset ); 4464// k ⊗ v 4465size_t buf_size = D * D * nb_base ; 4466ggml_cann_pool_alloc buffer_allocator (ctx .pool (),buf_size ); 4467acl_tensor_ptr tmp_tensor = ggml_cann_create_tensor ( 4468buffer_allocator .get (),ggml_cann_type_mapping (k -> type ),nb_base ,ne_s ,nb_s ,2 ); 4469aclnn_mul (ctx ,acl_k .get (),acl_v .get (),tmp_tensor .get ()); 4470//s_new = g ⊗ s_old + k ⊗ v 4471aclnn_mul (ctx ,acl_s_new .get (),acl_g .get (),nullptr ); 4472aclnn_add (ctx ,acl_s_new .get (),tmp_tensor .get (),nullptr ); 4473// compute output 4474GGML_CANN_CALL_ACLNN_OP (ctx ,Mv ,acl_s_new_t .get (),acl_q .get (),acl_o .get (),1 ); 4475aclnn_muls (ctx ,acl_o .get (),scale ,nullptr , true); 4476 } 4477 } 4478 } 4479}