From fa92107b08dc5f07669b81571969d88abd47e316 Mon Sep 17 00:00:00 2001 From: TecJesh Date: Thu, 30 Oct 2025 06:56:04 +0000 Subject: [PATCH 1/3] update L2_NORM op support --- ggml/src/ggml-cann/aclnn_ops.cpp | 29 +++++++++++++++++++++++++++++ ggml/src/ggml-cann/aclnn_ops.h | 24 ++++++++++++++++++++++++ ggml/src/ggml-cann/ggml-cann.cpp | 4 ++++ 3 files changed, 57 insertions(+) diff --git a/ggml/src/ggml-cann/aclnn_ops.cpp b/ggml/src/ggml-cann/aclnn_ops.cpp index 5df6dc96a3b2e..068d017ceacb4 100644 --- a/ggml/src/ggml-cann/aclnn_ops.cpp +++ b/ggml/src/ggml-cann/aclnn_ops.cpp @@ -448,6 +448,35 @@ void ggml_cann_norm(ggml_backend_cann_context & ctx, ggml_tensor * dst) { ggml_cann_release_resources(ctx, norm, acl_src, acl_dst); } +void ggml_cann_l2_norm(ggml_backend_cann_context & ctx, ggml_tensor * dst) { + ggml_tensor * src = dst->src[0]; + + aclTensor * acl_src = ggml_cann_create_tensor(src); + aclTensor * acl_dst = ggml_cann_create_tensor(dst); + + size_t type_size = ggml_type_size(src->type); + int64_t n_bytes = src->ne[3]* src->ne[2]* src->ne[1]* type_size; + ggml_cann_pool_alloc temp_buffer_allocator(ctx.pool(), n_bytes); + void * buffer = temp_buffer_allocator.get(); + + int64_t div_ne[] = {1, src->ne[1], src->ne[2], src->ne[3]}; + size_t div_nb[GGML_MAX_DIMS]; + div_nb[0] = sizeof(float); + for (int i = 1; i < GGML_MAX_DIMS; ++i) { + div_nb[i] = div_nb[i - 1] * div_ne[i - 1]; + } + aclTensor * acl_div = ggml_cann_create_tensor(buffer, ACL_FLOAT, type_size, div_ne, div_nb, 4); + + std::vector norm_dims = { 3 }; + aclIntArray * dims_array = aclCreateIntArray(norm_dims.data(), norm_dims.size()); + + float p_value = 2.0f; + aclScalar * p_scalar = aclCreateScalar(&p_value, aclDataType::ACL_FLOAT); + GGML_CANN_CALL_ACLNN_OP(ctx, Norm, acl_src, p_scalar, dims_array, true, acl_div); + GGML_CANN_CALL_ACLNN_OP(ctx, Div, acl_src, acl_div, acl_dst); + ggml_cann_release_resources(ctx, dims_array, p_scalar, acl_src, acl_dst, acl_div); +} + void ggml_cann_group_norm(ggml_backend_cann_context & ctx, ggml_tensor * dst) { ggml_tensor * src = dst->src[0]; diff --git a/ggml/src/ggml-cann/aclnn_ops.h b/ggml/src/ggml-cann/aclnn_ops.h index ec7455af88cd5..060eedbbb0282 100644 --- a/ggml/src/ggml-cann/aclnn_ops.h +++ b/ggml/src/ggml-cann/aclnn_ops.h @@ -46,6 +46,7 @@ #include #include #include +#include #include "acl_tensor.h" #include "common.h" @@ -187,6 +188,29 @@ void ggml_cann_argsort(ggml_backend_cann_context & ctx, ggml_tensor * dst); */ void ggml_cann_norm(ggml_backend_cann_context & ctx, ggml_tensor * dst); +/** + * @brief Computes the L2 Normalization for a ggml tensor using the CANN + * backend. + * + * @details This function applies the L2 Normalization operation on the + * input tensor `src` and stores the result in the destination tensor + * `dst`. L2 Normalization scales the input tensor such that the + * L2 norm along the specified dimension equals 1. This operation + * is commonly used in neural networks for feature normalization + * and vector scaling. + * The operation is defined as: + * \f[ + * \text{out} = \frac{x}{\sqrt{\sum{x^2}}} + * \f] + * The normalization is performed along the last dimension by default. + * + * @param ctx The CANN context used for operations. + * @param dst The destination tensor where the normalized values will be stored. + * @attention The normalization is performed along the last dimension of the + * input tensor by default. + */ +void ggml_cann_l2_norm(ggml_backend_cann_context & ctx, ggml_tensor * dst); + /** * @brief Computes the Group Normalization for a ggml tensor using the CANN * backend. diff --git a/ggml/src/ggml-cann/ggml-cann.cpp b/ggml/src/ggml-cann/ggml-cann.cpp index 51345742ee59e..9de9440ac6502 100644 --- a/ggml/src/ggml-cann/ggml-cann.cpp +++ b/ggml/src/ggml-cann/ggml-cann.cpp @@ -1777,6 +1777,9 @@ static bool ggml_cann_compute_forward(ggml_backend_cann_context & ctx, struct gg case GGML_OP_GROUP_NORM: ggml_cann_group_norm(ctx, dst); break; + case GGML_OP_L2_NORM: + ggml_cann_l2_norm(ctx, dst); + break; case GGML_OP_CONCAT: ggml_cann_concat(ctx, dst); break; @@ -2515,6 +2518,7 @@ static bool ggml_backend_cann_supports_op(ggml_backend_dev_t dev, const ggml_ten // value of paddingW should be at most half of kernelW return (p0 <= (k0 / 2)) && (p1 <= (k1 / 2)); } + case GGML_OP_L2_NORM: case GGML_OP_DUP: case GGML_OP_SUM: case GGML_OP_IM2COL: From 0829127ffd9fd546992e9c88c83adee4522fccef Mon Sep 17 00:00:00 2001 From: TecJesh Date: Thu, 30 Oct 2025 07:59:45 +0000 Subject: [PATCH 2/3] update L2_NORM op support --- ggml/src/ggml-cann/aclnn_ops.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/ggml/src/ggml-cann/aclnn_ops.cpp b/ggml/src/ggml-cann/aclnn_ops.cpp index 068d017ceacb4..889a4b4e4d586 100644 --- a/ggml/src/ggml-cann/aclnn_ops.cpp +++ b/ggml/src/ggml-cann/aclnn_ops.cpp @@ -465,9 +465,9 @@ void ggml_cann_l2_norm(ggml_backend_cann_context & ctx, ggml_tensor * dst) { for (int i = 1; i < GGML_MAX_DIMS; ++i) { div_nb[i] = div_nb[i - 1] * div_ne[i - 1]; } - aclTensor * acl_div = ggml_cann_create_tensor(buffer, ACL_FLOAT, type_size, div_ne, div_nb, 4); + aclTensor * acl_div = ggml_cann_create_tensor(buffer, ACL_FLOAT, type_size, div_ne, div_nb, GGML_MAX_DIMS); - std::vector norm_dims = { 3 }; + std::vector norm_dims = { 3 }; aclIntArray * dims_array = aclCreateIntArray(norm_dims.data(), norm_dims.size()); float p_value = 2.0f; From 3eb2ea0f15f31b3490ea9cccb0fa6b0b31e2ad48 Mon Sep 17 00:00:00 2001 From: TecJesh Date: Thu, 30 Oct 2025 11:21:53 +0000 Subject: [PATCH 3/3] remove extra whitespace --- ggml/src/ggml-cann/aclnn_ops.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ggml/src/ggml-cann/aclnn_ops.cpp b/ggml/src/ggml-cann/aclnn_ops.cpp index 889a4b4e4d586..4835c5c0387d1 100644 --- a/ggml/src/ggml-cann/aclnn_ops.cpp +++ b/ggml/src/ggml-cann/aclnn_ops.cpp @@ -459,7 +459,7 @@ void ggml_cann_l2_norm(ggml_backend_cann_context & ctx, ggml_tensor * dst) { ggml_cann_pool_alloc temp_buffer_allocator(ctx.pool(), n_bytes); void * buffer = temp_buffer_allocator.get(); - int64_t div_ne[] = {1, src->ne[1], src->ne[2], src->ne[3]}; + int64_t div_ne[] = {1, src->ne[1], src->ne[2], src->ne[3]}; size_t div_nb[GGML_MAX_DIMS]; div_nb[0] = sizeof(float); for (int i = 1; i < GGML_MAX_DIMS; ++i) {