nareshmlx/opencv-pr huggingface dataset:
**File:** modules/dnn/src/layers/einsum_layer.cpp
**Change Type:** modified
**Context:** PR #24322: Ellipses supported added for Einsum Layer

**Code Changes:**
```diff
@@ -32,16 +32,15 @@ static bool IsTransposeReshapeForEinsum(const std::vector<size_t>& perm,
     return true;
 }
 
-Mat batchwiseMatMul(
+static Mat batchwiseMatMul(
     const Mat& input1,
     const MatShape& input1ShapeOverride,
     const Mat& input2,
     const MatShape& input2ShapeOverride)
```

Review comment:
Looks like the 3rd dimension is redundant. You can create output mat with 2 dimensions and drop reshape at the end.
**File:** modules/dnn/src/layers/einsum_layer.cpp
**Change Type:** modified
**Context:** PR #24322: Ellipses supported added for Einsum Layer

**Code Changes:**
```diff
@@ -32,16 +32,15 @@ static bool IsTransposeReshapeForEinsum(const std::vector<size_t>& perm,
     return true;
 }
 
-Mat batchwiseMatMul(
+static Mat batchwiseMatMul(
     const Mat& input1,
     const MatShape& input1ShapeOverride,
     const Mat& input2,
     const MatShape& input2ShapeOverride)
```

Review comment:
tested suggestion. This breaks the the tests. Let's leave as it is maybe? since the suggestion only reduces one reshape operation
**File:** modules/dnn/src/layers/einsum_layer.cpp
**Change Type:** modified
**Context:** PR #24322: Ellipses supported added for Einsum Layer

**Code Changes:**
```diff
@@ -32,16 +32,15 @@ static bool IsTransposeReshapeForEinsum(const std::vector<size_t>& perm,
     return true;
 }
 
-Mat batchwiseMatMul(
+static Mat batchwiseMatMul(
     const Mat& input1,
     const MatShape& input1ShapeOverride,
     const Mat& input2,
     const MatShape& input2ShapeOverride)
```

Review comment:
`MatShape` is a `typedef std::vector<int> MatShape`. So this can be replaced to ```cpp MatShape order(permutation.begin(), permutation.end()); ```
**File:** modules/dnn/src/layers/einsum_layer.cpp
**Change Type:** modified
**Context:** PR #24322: Ellipses supported added for Einsum Layer
**Review Line:** 143

**Code Changes:**
```diff
 };
 
-Mat Transpose(
-    const cv::Mat& input,
+static Mat Transpose(
+    const Mat& input,
     const MatShape& input_shape_override,
     const std::vector<size_t> permutation)
 {
 
     int input_rank = input_shape_override.size();
```

Review comment:
Are these functions, such as `batchwiseMatMul`, `Transpose`, defined and declared only in this file? If so, I propose to add `static`.
**File:** modules/dnn/src/layers/einsum_layer.cpp
**Change Type:** modified
**Context:** PR #24322: Ellipses supported added for Einsum Layer

**Code Changes:**
```diff
@@ -32,16 +32,15 @@ static bool IsTransposeReshapeForEinsum(const std::vector<size_t>& perm,
     return true;
 }
 
-Mat batchwiseMatMul(
+static Mat batchwiseMatMul(
     const Mat& input1,
     const MatShape& input1ShapeOverride,
     const Mat& input2,
     const MatShape& input2ShapeOverride)
```

Review comment:
All these comments are for `DiagonalInnermostDims` right? I propose to use `/**/` for these comments to avoid misleading.
**File:** modules/dnn/src/layers/einsum_layer.cpp
**Change Type:** modified
**Context:** PR #24322: Ellipses supported added for Einsum Layer

**Code Changes:**
```diff
@@ -32,16 +32,15 @@ static bool IsTransposeReshapeForEinsum(const std::vector<size_t>& perm,
     return true;
 }
 
-Mat batchwiseMatMul(
+static Mat batchwiseMatMul(
     const Mat& input1,
     const MatShape& input1ShapeOverride,
     const Mat& input2,
     const MatShape& input2ShapeOverride)
```

Review comment:
Why not initialize output with the final dimensions once but int the loop work with a data pointer?
**File:** modules/dnn/src/layers/einsum_layer.cpp
**Change Type:** modified
**Context:** PR #24322: Ellipses supported added for Einsum Layer

**Code Changes:**
```diff
@@ -32,16 +32,15 @@ static bool IsTransposeReshapeForEinsum(const std::vector<size_t>& perm,
     return true;
 }
 
-Mat batchwiseMatMul(
+static Mat batchwiseMatMul(
     const Mat& input1,
     const MatShape& input1ShapeOverride,
     const Mat& input2,
     const MatShape& input2ShapeOverride)
```

Review comment:
This method can be without template by using `cv::Mat::diag`: ```cpp input = input(1, total_slices); output = output.reshape(1, total_slices); for (int slice = 0; slice < total_slices; ++slice) { Mat src = input.row(slice).reshape(1, inner_stride).diag(0); Mat dst = output.row(slice); src.copyTo(dst); }
**File:** modules/dnn/src/layers/einsum_layer.cpp
**Change Type:** modified
**Context:** PR #24322: Ellipses supported added for Einsum Layer
**Review Line:** 279

**Code Changes:**
```diff
+    // TODO: hande different types
+    Mat output = DiagonalDataAssignment<float>(input);
+
+    if (output_dims != shape(output)){
+        CV_Error(Error::StsError, "Output shape does not match with calculated shape");
+    }
+    return output;
+}
+
+Mat Diagonal(const Mat& input, int dim1, int dim2)
 {
```

Review comment:
Do we really need `output_dims` as it's used only for the check?
**File:** modules/dnn/src/layers/einsum_layer.cpp
**Change Type:** modified
**Context:** PR #24322: Ellipses supported added for Einsum Layer
**Review Line:** 279

**Code Changes:**
```diff
+    // TODO: hande different types
+    Mat output = DiagonalDataAssignment<float>(input);
+
+    if (output_dims != shape(output)){
+        CV_Error(Error::StsError, "Output shape does not match with calculated shape");
+    }
+    return output;
+}
+
+Mat Diagonal(const Mat& input, int dim1, int dim2)
 {
```

Review comment:
do we not need to check?
**File:** modules/dnn/src/layers/einsum_layer.cpp
**Change Type:** modified
**Context:** PR #24322: Ellipses supported added for Einsum Layer

**Code Changes:**
```diff
@@ -32,16 +32,15 @@ static bool IsTransposeReshapeForEinsum(const std::vector<size_t>& perm,
     return true;
 }
 
-Mat batchwiseMatMul(
+static Mat batchwiseMatMul(
     const Mat& input1,
     const MatShape& input1ShapeOverride,
     const Mat& input2,
     const MatShape& input2ShapeOverride)
```

Review comment:
changed. now without reshape
**File:** modules/dnn/src/layers/einsum_layer.cpp
**Change Type:** modified
**Context:** PR #24322: Ellipses supported added for Einsum Layer

**Code Changes:**
```diff
@@ -32,16 +32,15 @@ static bool IsTransposeReshapeForEinsum(const std::vector<size_t>& perm,
     return true;
 }
 
-Mat batchwiseMatMul(
+static Mat batchwiseMatMul(
     const Mat& input1,
     const MatShape& input1ShapeOverride,
     const Mat& input2,
     const MatShape& input2ShapeOverride)
```

Review comment:
tested, this introduces regression in accuracy
**File:** modules/dnn/src/layers/einsum_layer.cpp
**Change Type:** modified
**Context:** PR #24322: Ellipses supported added for Einsum Layer
**Review Line:** 279

**Code Changes:**
```diff
+    // TODO: hande different types
+    Mat output = DiagonalDataAssignment<float>(input);
+
+    if (output_dims != shape(output)){
+        CV_Error(Error::StsError, "Output shape does not match with calculated shape");
+    }
+    return output;
+}
+
+Mat Diagonal(const Mat& input, int dim1, int dim2)
 {
```

Review comment:
We probably initialize output somewhere once in the code with such shapes.
**File:** modules/dnn/src/layers/einsum_layer.cpp
**Change Type:** modified
**Context:** PR #24322: Ellipses supported added for Einsum Layer
**Review Line:** 279

**Code Changes:**
```diff
+    // TODO: hande different types
+    Mat output = DiagonalDataAssignment<float>(input);
+
+    if (output_dims != shape(output)){
+        CV_Error(Error::StsError, "Output shape does not match with calculated shape");
+    }
+    return output;
+}
+
+Mat Diagonal(const Mat& input, int dim1, int dim2)
 {
```

Review comment:
output shape for this particular function is not saved anywhere. However, overall output shape is save, of course. Because of this I need to check the outputs for compatibility.
**File:** modules/imgproc/src/cornersubpix.cpp
**Change Type:** modified
**Context:** PR #24527: Fix out of image corners in cv::cornerSubPix

**Code Changes:**
```diff
@@ -96,6 +96,7 @@ void cv::cornerSubPix( InputArray _image, InputOutputArray _corners,
     for( int pt_i = 0; pt_i < count; pt_i++ )
     {
         Point2f cT = corners[pt_i], cI = cT;
+        CV_Assert( Rect(0, 0, src.cols, src.rows).contains(cT) );
         int iter = 0;
         double err = 0;
 
@@ -140,9 +141,10 @@ void cv::cornerSubPix( InputArray _image, InputOutputArray _corners,
             cI2.x = (float)(cI.x + c*scale*bb1 - b*scale*bb2);
```

Review comment:
Possible alternative: lines 143 - 145: ``` if (Rect(0, 0, src.cols, src.rows).contains(cI2)) { cI = cI2; } else { break; } ``` Also it makes sense to perform input validation right after the line 98 ``` CV_Assert(Rect(0, 0, src.cols, src.rows).contains(cT)); ```
**File:** modules/core/test/test_operations.cpp
**Change Type:** modified
**Context:** PR #24271: fix to convert float32 to int32/uint32 with rounding to nearest (ties to even).

**Code Changes:**
```diff
@@ -1561,4 +1561,54 @@ TEST(Core_Arithm, scalar_handling_19599)  // https://github.com/opencv/opencv/is
     EXPECT_EQ(1, c.rows);
 }
 
+// https://github.com/opencv/opencv/issues/24163
+typedef tuple<perf::MatDepth,int,int,int> Arith_Regression24163Param;
+typedef testing::TestWithParam<Arith_Regression24163Param> Core_Arith_Regression24163;
+
+#if defined __riscv
+TEST_P(Core_Arith_Regression24163, DISABLED_test_for_ties_to_even)
```

Review comment:
Maybe it would be better to use non 16-divisible size to verify that tail processing also works as expected. E.g. 20 elements. Comon array size can be stored as a separate constant to reduce duplication.
**File:** 3rdparty/carotene/src/convert_scale.cpp
**Change Type:** modified
**Context:** PR #24271: fix to convert float32 to int32/uint32 with rounding to nearest (ties to even).
**Review Line:** 1252

**Code Changes:**
```diff
         int16x4_t vRes2 = vqmovn_s32(vline2_s32);
         uint8x8_t vRes = vqmovun_s16(vcombine_s16(vRes1, vRes2));
@@ -1249,7 +1250,7 @@ CVTS_FUNC(u16, s8, 16,
 #else
 CVTS_FUNC(u16, s8, 16,
     float32x4_t vscale = vdupq_n_f32((f32)alpha);
-    float32x4_t vshift = vdupq_n_f32((f32)beta + 0.5f);,
+    float32x4_t vshift = vdupq_n_f32((f32)beta);,
 {
     for (size_t i = 0; i < w; i += 8)
     {
```

Review comment:
coma is not needed.
**File:** 3rdparty/carotene/src/convert_scale.cpp
**Change Type:** modified
**Context:** PR #24271: fix to convert float32 to int32/uint32 with rounding to nearest (ties to even).
**Review Line:** 1310

**Code Changes:**
```diff
         int16x4_t vRes2 = vqmovn_s32(vline2_s32);
         int8x8_t vRes = vqmovn_s16(vcombine_s16(vRes1, vRes2));
@@ -1307,7 +1308,7 @@ CVTS_FUNC1(u16, 16,
 #else
 CVTS_FUNC1(u16, 16,
     float32x4_t vscale = vdupq_n_f32((f32)alpha);
-    float32x4_t vshift = vdupq_n_f32((f32)beta + 0.5f);,
+    float32x4_t vshift = vdupq_n_f32((f32)beta);,
 {
     for (size_t i = 0; i < w; i += 8)
     {
```

Review comment:
coma is not needed.
**File:** 3rdparty/carotene/src/convert_scale.cpp
**Change Type:** modified
**Context:** PR #24271: fix to convert float32 to int32/uint32 with rounding to nearest (ties to even).
**Review Line:** 1424

**Code Changes:**
```diff
         int16x4_t vRes2 = vqmovn_s32(vline2_s32);
         vst1q_s16(_dst + i, vcombine_s16(vRes1, vRes2));
@@ -1421,7 +1422,7 @@ CVTS_FUNC(u16, s32, 8,
 #else
 CVTS_FUNC(u16, s32, 8,
     float32x4_t vscale = vdupq_n_f32((f32)alpha);
-    float32x4_t vshift = vdupq_n_f32((f32)beta + 0.5f);,
+    float32x4_t vshift = vdupq_n_f32((f32)beta);,
 {
     for (size_t i = 0; i < w; i += 8)
     {
```

Review comment:
coma is not needed.
**File:** 3rdparty/carotene/src/vround_helper.hpp
**Change Type:** added
**Context:** PR #24271: fix to convert float32 to int32/uint32 with rounding to nearest (ties to even).

**Code Changes:**
```diff
@@ -0,0 +1,102 @@
+/*
+ * By downloading, copying, installing or using the software you agree to this license.
+ * If you do not agree to this license, do not download, install,
+ * copy or use the software.
+ *
+ *
+ *                           License Agreement
+ *                For Open Source Computer Vision Library
+ *                        (3-clause BSD License)
```

Review comment:
Please, add CAROTENE prefix to the macro, `ROUND_DELTA` name is too generic and may conflict with something else
**File:** modules/core/include/opencv2/core/hal/intrin_neon.hpp
**Change Type:** modified
**Context:** PR #24271: fix to convert float32 to int32/uint32 with rounding to nearest (ties to even).

**Code Changes:**
```diff
@@ -1969,11 +1969,9 @@ inline v_int32x4 v_round(const v_float32x4& a)
 #else
 inline v_int32x4 v_round(const v_float32x4& a)
 {
-    static const int32x4_t v_sign = vdupq_n_s32(1 << 31),
-        v_05 = vreinterpretq_s32_f32(vdupq_n_f32(0.5f));
-
-    int32x4_t v_addition = vorrq_s32(v_05, vandq_s32(v_sign, vreinterpretq_s32_f32(a.val)));
-    return v_int32x4(vcvtq_s32_f32(vaddq_f32(a.val, vreinterpretq_f32_s32(v_addition))));
+    // See https://github.com/opencv/opencv/pull/24271#issuecomment-1867318007
```

Review comment:
OK, I cleared it is not related with this work. (Some code is updated, however almost are not changed.) I believe we can split from this issue. https://github.com/opencv/opencv/blob/953dddd26b5cdc32fc9c2fc21fdedef1fa6fb04d/modules/core/src/has_non_zero.simd.hpp#L192-L202 I disabled L196 to stop using simd, same this test is passed. And those code is simple, loading from memory and or-ing registers, checking to equal it with zero. So this logic is not related currently fixing. More investigation is required, but it is related with only special cases(denorm_min). https://github.com/opencv/opencv/blob/953dddd26b5cdc32fc9c2fc21fdedef1fa6fb04d/modules/core/test/test_hasnonzero.cpp#L86-L110
**File:** modules/imgcodecs/test/test_tiff.cpp
**Change Type:** modified
**Context:** PR #24405: Extend the signature of imdecodemulti()

**Code Changes:**
```diff
@@ -965,7 +965,7 @@ TEST_P(Imgcodecs_Tiff_Modes, decode_multipage)
     }
 }
 
-TEST_P(Imgcodecs_Tiff_Modes, decode_multipage_use_memory_buffer)
+TEST_P(Imgcodecs_Tiff_Modes, decode_multipage_use_memory_buffer_all_pages)
 {
     const int mode = GetParam();
     const string root = cvtest::TS::ptr()->get_data_path();
@@ -984,13 +984,14 @@ TEST_P(Imgcodecs_Tiff_Modes, decode_multipage_use_memory_buffer)
```

Review comment:
``` size_t file_size = ftell(fp); std::vector<uchar> buf(file_size); fseek(fp, 0, SEEK_SET); size_t actual_read = fread(&buf[0], 1, file_size, fp); fclose(fp); ASSERT_EQ(file_size, actual_read); ```
**File:** modules/imgcodecs/test/test_tiff.cpp
**Change Type:** modified
**Context:** PR #24405: Extend the signature of imdecodemulti()

**Code Changes:**
```diff
@@ -965,7 +965,7 @@ TEST_P(Imgcodecs_Tiff_Modes, decode_multipage)
     }
 }
 
-TEST_P(Imgcodecs_Tiff_Modes, decode_multipage_use_memory_buffer)
+TEST_P(Imgcodecs_Tiff_Modes, decode_multipage_use_memory_buffer_all_pages)
 {
     const int mode = GetParam();
     const string root = cvtest::TS::ptr()->get_data_path();
@@ -984,13 +984,14 @@ TEST_P(Imgcodecs_Tiff_Modes, decode_multipage_use_memory_buffer)
```

Review comment:
I do not think that we need all combination here. It's enough to call `imdecodemulti` once with trange like `(1, size-2)` to check not default behaviour. Other cases and tiff specific are indirectly tested with `imreadmulti`.
**File:** modules/imgcodecs/test/test_tiff.cpp
**Change Type:** modified
**Context:** PR #24405: Extend the signature of imdecodemulti()

**Code Changes:**
```diff
@@ -965,7 +965,7 @@ TEST_P(Imgcodecs_Tiff_Modes, decode_multipage)
     }
 }
 
-TEST_P(Imgcodecs_Tiff_Modes, decode_multipage_use_memory_buffer)
+TEST_P(Imgcodecs_Tiff_Modes, decode_multipage_use_memory_buffer_all_pages)
 {
     const int mode = GetParam();
     const string root = cvtest::TS::ptr()->get_data_path();
@@ -984,13 +984,14 @@ TEST_P(Imgcodecs_Tiff_Modes, decode_multipage_use_memory_buffer)
```

Review comment:
I have revised the code as requested, but please note that, strictly speaking, the proposed test did not check all combinations, which would be nonsensical, but all _contiguous subsequences_. If you have a sequence of length _n_, there are _n_ × (_n_ + 1)/2 ~ O(_n_<sup>2</sup>) contiguous subsequences, which for the current _n_ = 6 gives 21.
**File:** modules/imgcodecs/src/loadsave.cpp
**Change Type:** modified
**Context:** PR #24405: Extend the signature of imdecodemulti()

**Code Changes:**
```diff
@@ -1095,12 +1095,21 @@ imdecodemulti_(const Mat& buf, int flags, std::vector<Mat>& mats, int start, int
     return !mats.empty();
 }
 
-bool imdecodemulti(InputArray _buf, int flags, CV_OUT std::vector<Mat>& mats)
+bool imdecodemulti(InputArray _buf, int flags, CV_OUT std::vector<Mat>& mats, const Range& range)
 {
     CV_TRACE_FUNCTION();
 
     Mat buf = _buf.getMat();
```

Review comment:
CV_CheckGE CV_CheckGT
**File:** platforms/android/build_aar.sh
**Change Type:** added
**Context:** PR #24752: Enable Android AAR package build with SDK project itself without Python
**Review Line:** 2

**Code Changes:**
```diff
@@ -0,0 +1,45 @@
+#!/bin/bash -e
+SDK_DIR=$1
+
+echo "OpenCV Android SDK path: ${SDK_DIR}"
+
+ANDROID_HOME=${ANDROID_HOME:-${ANDROID_SDK_ROOT:-${ANDROID_SDK?Required ANDROID_HOME/ANDROID_SDK/ANDROID_SDK_ROOT}}}
+ANDROID_NDK=${ANDROID_NDK_HOME-${ANDROID_NDK:-${NDKROOT?Required ANDROID_NDK_HOME/ANDROID_NDK/NDKROOT}}}
```

Review comment:
`${1:?Required OpenCV Android SDK path}` ?
**File:** platforms/android/build_aar.sh
**Change Type:** added
**Context:** PR #24752: Enable Android AAR package build with SDK project itself without Python
**Review Line:** 6

**Code Changes:**
```diff
+#!/bin/bash -e
+SDK_DIR=$1
+
+echo "OpenCV Android SDK path: ${SDK_DIR}"
+
+ANDROID_HOME=${ANDROID_HOME:-${ANDROID_SDK_ROOT:-${ANDROID_SDK?Required ANDROID_HOME/ANDROID_SDK/ANDROID_SDK_ROOT}}}
+ANDROID_NDK=${ANDROID_NDK_HOME-${ANDROID_NDK:-${NDKROOT?Required ANDROID_NDK_HOME/ANDROID_NDK/NDKROOT}}}
+
+echo "Android SDK: ${ANDROID_HOME}"
+echo "Android NDK: ${ANDROID_NDK}"
+
```

Review comment:
Prefer using `:?` to avoid empty values too. Details: https://tldp.org/LDP/abs/html/parameter-substitution.html
**File:** platforms/android/build_aar.sh
**Change Type:** added
**Context:** PR #24752: Enable Android AAR package build with SDK project itself without Python

**Code Changes:**
```diff
@@ -0,0 +1,45 @@
+#!/bin/bash -e
+SDK_DIR=$1
+
+echo "OpenCV Android SDK path: ${SDK_DIR}"
+
+ANDROID_HOME=${ANDROID_HOME:-${ANDROID_SDK_ROOT:-${ANDROID_SDK?Required ANDROID_HOME/ANDROID_SDK/ANDROID_SDK_ROOT}}}
+ANDROID_NDK=${ANDROID_NDK_HOME-${ANDROID_NDK:-${NDKROOT?Required ANDROID_NDK_HOME/ANDROID_NDK/NDKROOT}}}
+
+echo "Android SDK: ${ANDROID_HOME}"
```

Review comment:
`gradlew ${OPENCV_GRADLE_VERBOSE_OPTIONS:--i} ...` ? to run gradle with debug/verbose mode without modification of the script. Ref: https://github.com/opencv/opencv/blob/4.8.0/cmake/android/android_gradle_projects.cmake#L164-L167
**File:** modules/dnn/include/opencv2/dnn/all_layers.hpp
**Change Type:** modified
**Context:** PR #24476: dnn: add attention layer

**Code Changes:**
```diff
@@ -1178,6 +1178,11 @@ CV__DNN_INLINE_NS_BEGIN
         static Ptr<InstanceNormLayer> create(const LayerParams &params);
     };
 
+    class CV_EXPORTS AttentionLayer : public Layer {
+     public:
+        static Ptr<AttentionLayer> create(const LayerParams &params);
+    };
+
 //! @}
```

Review comment:
Can be moved to implementation? To avoid future ABI changes
**File:** modules/dnn/src/onnx/onnx_graph_simplifier.cpp
**Change Type:** modified
**Context:** PR #24476: dnn: add attention layer

**Code Changes:**
```diff
@@ -13,6 +13,7 @@
 
 #include <opencv2/core/utils/logger.hpp>
 #include <queue>
+#include <limits>
 
 namespace cv { namespace dnn {
 CV__DNN_INLINE_NS_BEGIN
@@ -181,6 +182,17 @@ static Mat extractConstant(const Ptr<ImportGraphWrapper>& net, int node_id, int
     }
```

Review comment:
Why not a part of `finalize`?
**File:** modules/dnn/include/opencv2/dnn/all_layers.hpp
**Change Type:** modified
**Context:** PR #24476: dnn: add attention layer

**Code Changes:**
```diff
@@ -1178,6 +1178,11 @@ CV__DNN_INLINE_NS_BEGIN
         static Ptr<InstanceNormLayer> create(const LayerParams &params);
     };
 
+    class CV_EXPORTS AttentionLayer : public Layer {
+     public:
+        static Ptr<AttentionLayer> create(const LayerParams &params);
+    };
+
 //! @}
```

Review comment:
Yes, will do. We have had this issue, after all.
**File:** modules/dnn/src/onnx/onnx_graph_simplifier.cpp
**Change Type:** modified
**Context:** PR #24476: dnn: add attention layer

**Code Changes:**
```diff
@@ -13,6 +13,7 @@
 
 #include <opencv2/core/utils/logger.hpp>
 #include <queue>
+#include <limits>
 
 namespace cv { namespace dnn {
 CV__DNN_INLINE_NS_BEGIN
@@ -181,6 +182,17 @@ static Mat extractConstant(const Ptr<ImportGraphWrapper>& net, int node_id, int
     }
```

Review comment:
If it is put in `finalize`, member variables are not needed then. It should also work.
**File:** modules/dnn/src/onnx/onnx_graph_simplifier.cpp
**Change Type:** modified
**Context:** PR #24476: dnn: add attention layer

**Code Changes:**
```diff
@@ -13,6 +13,7 @@
 
 #include <opencv2/core/utils/logger.hpp>
 #include <queue>
+#include <limits>
 
 namespace cv { namespace dnn {
 CV__DNN_INLINE_NS_BEGIN
@@ -181,6 +182,17 @@ static Mat extractConstant(const Ptr<ImportGraphWrapper>& net, int node_id, int
     }
```

Review comment:
Just realize that `getAttributes` needs `matchedNodesIds` which is not existed in `finalize`.
**File:** modules/dnn/perf/perf_layer.cpp
**Change Type:** modified
**Context:** PR #24476: dnn: add attention layer
**Review Line:** 781

**Code Changes:**
```diff
+            net.setInput(x, input_names[0]);
+            net.setInput(weight, input_names[1]);
+            net.setInput(bias, input_names[2]);
+
+            net.setPreferableBackend(backendId);
+            net.setPreferableTarget(targetId);
+            Mat out = net.forward();
+        }
+
+        TEST_CYCLE()
+        {
```

Review comment:
- [ ] I will benchmark on CUDA and with OpenVINO
**File:** modules/dnn/src/layers/attention_layer.cpp
**Change Type:** added
**Context:** PR #24476: dnn: add attention layer
**Review Line:** 145

**Code Changes:**
```diff
+            const auto &input = inputs[0];
+            const auto &bias = inputs[2];
+            const auto *input_data = input.ptr<const float>();
+            const auto *bias_data = bias.ptr<const float>();
+
+            opt.multi_thread = false;
+            auto fn = [&](const Range &r) {
+                for (int i = r.start; i < r.end; i++) {
+                    const int batch_index = static_cast<int>((i / 3) / num_heads);
+                    const int head_index = static_cast<int>((i / 3) % num_heads);
+                    const int qkv_index = static_cast<int>(i % 3);
```

Review comment:
Is there any problems with multiple threads?