From 63cde0b90d378337cdf280e7e3d129b38b030439 Mon Sep 17 00:00:00 2001 From: fengyuentau Date: Fri, 5 Jan 2024 17:24:09 +0800 Subject: [PATCH 1/5] multi-threaded scatter and refactor perf --- modules/dnn/perf/perf_layer.cpp | 123 +++++++++++------------ modules/dnn/src/layers/scatter_layer.cpp | 100 +++++++++--------- 2 files changed, 111 insertions(+), 112 deletions(-) diff --git a/modules/dnn/perf/perf_layer.cpp b/modules/dnn/perf/perf_layer.cpp index 66b5ad62c2..04e7d04153 100644 --- a/modules/dnn/perf/perf_layer.cpp +++ b/modules/dnn/perf/perf_layer.cpp @@ -258,76 +258,71 @@ PERF_TEST_P_(Layer_Slice, FastNeuralStyle_eccv16) test_slice<4>(inputShape, begin, end); } -struct Layer_Scatter : public TestBaseWithParam > -{ - void test_layer(const std::vector& shape, const String reduction = "none", int axis = 0) +using Layer_Scatter = TestBaseWithParam, std::string, int, tuple>>; +PERF_TEST_P_(Layer_Scatter, scatter) { + std::vector shape = get<0>(GetParam()); + std::string reduction = get<1>(GetParam()); + int axis = get<2>(GetParam()); + int backend_id = get<0>(get<3>(GetParam())); + int target_id = get<1>(get<3>(GetParam())); + + Mat data(shape, CV_32FC1); + Mat indices(shape, CV_32FC1); + Mat updates(shape, CV_32FC1); + + randn(data, 0.f, 1.f); + randu(indices, 0, shape[axis]); + randn(updates, 0.f, 1.f); + + indices.convertTo(indices, CV_32SC1, 1, -1); + + Net net; + LayerParams lp; + lp.type = "Scatter"; + lp.name = "testLayer"; + lp.set("reduction", reduction); + lp.set("axis", axis); + + int id = net.addLayerToPrev(lp.name, lp.type, lp); + net.connect(0, 0, id, 0); + net.connect(0, 1, id, 1); + net.connect(0, 2, id, 2); + + // warmup { - int backendId = get<0>(GetParam()); - int targetId = get<1>(GetParam()); + std::vector input_names{"data", "indices", "updates"}; + net.setInputsNames(input_names); + net.setInput(data, input_names[0]); + net.setInput(indices, input_names[1]); + net.setInput(updates, input_names[2]); - Mat data(shape, CV_32FC1); - Mat indices(shape, CV_32FC1); - Mat updates(shape, CV_32FC1); - - Scalar mean = 0.f; - Scalar std = 1.f; - randn(data, mean, std); - randu(indices, 0, shape[axis]); - randn(updates, mean, std); - - indices.convertTo(indices, CV_32SC1, 1, -1); - - Net net; - LayerParams lp; - lp.type = "Scatter"; - lp.name = "testLayer"; - lp.set("reduction", reduction); - lp.set("axis", axis); - - int id = net.addLayerToPrev(lp.name, lp.type, lp); - net.connect(0, 0, id, 0); - net.connect(0, 1, id, 1); - net.connect(0, 2, id, 2); - - // warmup - { - std::vector inpNames(3); - inpNames[0] = "data"; - inpNames[1] = "indices"; - inpNames[2] = "updates"; - net.setInputsNames(inpNames); - net.setInput(data, inpNames[0]); - net.setInput(indices, inpNames[1]); - net.setInput(updates, inpNames[2]); - - net.setPreferableBackend(backendId); - net.setPreferableTarget(targetId); - Mat out = net.forward(); - } - - TEST_CYCLE() - { - Mat res = net.forward(); - } - - SANITY_CHECK_NOTHING(); + net.setPreferableBackend(backend_id); + net.setPreferableTarget(target_id); + Mat out = net.forward(); } - int N = 8; - int C = 256; - int H = 128; - int W = 100; -}; + // perf + TEST_CYCLE() + { + Mat res = net.forward(); + } -PERF_TEST_P_(Layer_Scatter, DISABLED_Scatter) -{ - test_layer({N, C, H, W}); + SANITY_CHECK_NOTHING(); } -PERF_TEST_P_(Layer_Scatter, DISABLED_Scatter_add) -{ - test_layer({N, C, H, W}, "add"); -} +INSTANTIATE_TEST_CASE_P(/**/, Layer_Scatter, Combine( + Values(std::vector{2, 128, 64, 50}), + Values(std::string("none"), std::string("add")), + Values(0), // use Values(0, 1, 2, 3) for more details + dnnBackendsAndTargets(/* withInferenceEngine= */ false, + /* withHalide= */ false, + /* withCpuOCV= */ true, + /* withVkCom= */ false, + /* withCUDA= */ false, + /* withNgraph= */ false, + /* withWebnn= */ false, + /* withCann= */ false) // only test on CPU +)); struct Layer_ScatterND : public TestBaseWithParam > { @@ -800,7 +795,7 @@ INSTANTIATE_TEST_CASE_P(/**/, Layer_NaryEltwise, testing::Values(std::make_tuple #ifdef HAVE_CUDA INSTANTIATE_TEST_CASE_P(CUDA, Layer_NaryEltwise, testing::Values(std::make_tuple(DNN_BACKEND_CUDA, DNN_TARGET_CUDA))); #endif -INSTANTIATE_TEST_CASE_P(/**/, Layer_Scatter, testing::Values(std::make_tuple(DNN_BACKEND_OPENCV, DNN_TARGET_CPU))); +// INSTANTIATE_TEST_CASE_P(/**/, Layer_Scatter, testing::Values(std::make_tuple(DNN_BACKEND_OPENCV, DNN_TARGET_CPU))); INSTANTIATE_TEST_CASE_P(/**/, Layer_ScatterND, testing::Values(std::make_tuple(DNN_BACKEND_OPENCV, DNN_TARGET_CPU))); INSTANTIATE_TEST_CASE_P(/**/, Layer_LayerNorm, testing::Values(std::make_tuple(DNN_BACKEND_OPENCV, DNN_TARGET_CPU))); INSTANTIATE_TEST_CASE_P(/**/, Layer_LayerNormExpanded, testing::Values(std::make_tuple(DNN_BACKEND_OPENCV, DNN_TARGET_CPU))); diff --git a/modules/dnn/src/layers/scatter_layer.cpp b/modules/dnn/src/layers/scatter_layer.cpp index 084eecb03c..3e0ee2affb 100644 --- a/modules/dnn/src/layers/scatter_layer.cpp +++ b/modules/dnn/src/layers/scatter_layer.cpp @@ -81,59 +81,63 @@ public: } template - void forward_impl(const Functor& rd, const Mat& data, const Mat& indices, const Mat& updates, Mat& out) + void forward_impl(const Functor& reduce_operation, const Mat& input_mat, const Mat& indices_mat, const Mat& updates_mat, Mat& output_mat) { - data.copyTo(out); + input_mat.copyTo(output_mat); - const int ndims = data.dims; - const int* shape = data.size.p; - const size_t* step = data.step.p; + const int ndims = input_mat.dims; + const auto &input_mat_shape = shape(input_mat); + std::vector input_mat_step(ndims); - const int* ind_shape = indices.size.p; - const size_t* ind_step = indices.step.p; + const auto &indices_mat_shape = shape(indices_mat); + // const auto &indices_mat_step = indices_mat.step; + std::vector indices_mat_step(ndims); - size_t inp_offset = 0; - size_t ind_offset = 0; - const T* p_index = indices.ptr(); - const T* p_update = updates.ptr(); - T* p_out = out.ptr(); - - size_t total = indices.total(); - - int j, offset_at_idx, index; - size_t t, idx; - for (size_t i = 0; i < total; i++) - { - t = i; - inp_offset = 0; - ind_offset = 0; - int offset_at_axis = 0; - for (j = ndims - 1; j >= 0; j--) - { - idx = t / ind_shape[j]; - offset_at_idx = (int)(t - idx * ind_shape[j]); - ind_offset += offset_at_idx * ind_step[j]; - inp_offset += offset_at_idx * step[j]; - t = idx; - if (j == axis) - { - offset_at_axis = offset_at_idx * step[j]; - } - } - ind_offset /= sizeof(T); - - // get index and overwrite current indices - const T* tmp_p_index = p_index + ind_offset; - index = (int)(*tmp_p_index); - CV_Assert(index < shape[axis] && index > -shape[axis]); - - inp_offset = inp_offset - offset_at_axis + ((index + shape[axis]) % shape[axis]) * step[axis]; - inp_offset /= sizeof(T); - - const T* tmp_p_update = p_update + ind_offset; - T* tmp_p_out = p_out + inp_offset; - *tmp_p_out = rd(*tmp_p_out, *tmp_p_update); + for (int i = 0; i < ndims; i++) { + input_mat_step[i] = static_cast(input_mat.step.p[i] / sizeof(T)); + indices_mat_step[i] = static_cast(indices_mat.step.p[i] / sizeof(T)); } + + const T* indices = indices_mat.ptr(); + const T* updates = updates_mat.ptr(); + T* output = output_mat.ptr(); + + auto fn = [&](const Range &r) { + size_t input_offset = 0, indices_offset = 0; + + int indices_index, index; + size_t axis_offset, tmp_index, j_index; + for (int i = r.start; i < r.end; i++) { + input_offset = 0; + indices_offset = 0; + indices_index = i; + axis_offset = 0; + for (int j = ndims - 1; j >= 0; j--) { + tmp_index = indices_index / indices_mat_shape[j]; + j_index = (size_t)(indices_index - tmp_index * indices_mat_shape[j]); + input_offset += j_index * input_mat_step[j]; + indices_offset += j_index * indices_mat_step[j]; + indices_index = tmp_index; + if (j == axis) { + axis_offset = j_index * input_mat_step[j]; + } + } + + // get index and overwrite current indices + index = static_cast(*(indices + indices_offset)); + index = (index + input_mat_shape[axis]) % input_mat_shape[axis]; + CV_Assert(index < input_mat_shape[axis] && index >= 0); + input_offset = input_offset - axis_offset + index * input_mat_step[axis]; + + const T* update = updates + indices_offset; + T* y = output + input_offset; + *y = reduce_operation(*y, *update); + } + }; + + size_t total = indices_mat.total(); + double nstripes = (size_t)total * ndims * (1 / 1024.0); + parallel_for_(Range(0, total), fn, nstripes); } template From 2997b4c5fe0c00493d61530dae22280b58390d4a Mon Sep 17 00:00:00 2001 From: fengyuentau Date: Fri, 5 Jan 2024 18:15:27 +0800 Subject: [PATCH 2/5] pretty format --- modules/dnn/src/layers/scatter_layer.cpp | 19 +++++++++---------- 1 file changed, 9 insertions(+), 10 deletions(-) diff --git a/modules/dnn/src/layers/scatter_layer.cpp b/modules/dnn/src/layers/scatter_layer.cpp index 3e0ee2affb..3b803b16c1 100644 --- a/modules/dnn/src/layers/scatter_layer.cpp +++ b/modules/dnn/src/layers/scatter_layer.cpp @@ -81,16 +81,15 @@ public: } template - void forward_impl(const Functor& reduce_operation, const Mat& input_mat, const Mat& indices_mat, const Mat& updates_mat, Mat& output_mat) - { + void forward_impl(const Functor &reduce_operation, const Mat &input_mat, const Mat &indices_mat, const Mat &updates_mat, Mat &output_mat) { input_mat.copyTo(output_mat); const int ndims = input_mat.dims; + const auto &input_mat_shape = shape(input_mat); std::vector input_mat_step(ndims); const auto &indices_mat_shape = shape(indices_mat); - // const auto &indices_mat_step = indices_mat.step; std::vector indices_mat_step(ndims); for (int i = 0; i < ndims; i++) { @@ -98,16 +97,16 @@ public: indices_mat_step[i] = static_cast(indices_mat.step.p[i] / sizeof(T)); } - const T* indices = indices_mat.ptr(); - const T* updates = updates_mat.ptr(); - T* output = output_mat.ptr(); - auto fn = [&](const Range &r) { size_t input_offset = 0, indices_offset = 0; int indices_index, index; size_t axis_offset, tmp_index, j_index; for (int i = r.start; i < r.end; i++) { + const T* indices = indices_mat.ptr(); + const T* updates = updates_mat.ptr(); + T* output = output_mat.ptr(); + input_offset = 0; indices_offset = 0; indices_index = i; @@ -129,9 +128,9 @@ public: CV_Assert(index < input_mat_shape[axis] && index >= 0); input_offset = input_offset - axis_offset + index * input_mat_step[axis]; - const T* update = updates + indices_offset; - T* y = output + input_offset; - *y = reduce_operation(*y, *update); + updates += indices_offset; + output += input_offset; + *output = reduce_operation(*output, *updates); } }; From 2ed97b9ef3f096031b55e44dff254533dc14afa2 Mon Sep 17 00:00:00 2001 From: fengyuentau Date: Fri, 5 Jan 2024 18:15:59 +0800 Subject: [PATCH 3/5] multi-threaded scatterND and refactor perf --- modules/dnn/perf/perf_layer.cpp | 168 ++++++++++----------- modules/dnn/src/layers/scatterND_layer.cpp | 78 +++++----- 2 files changed, 123 insertions(+), 123 deletions(-) diff --git a/modules/dnn/perf/perf_layer.cpp b/modules/dnn/perf/perf_layer.cpp index 04e7d04153..3e477da125 100644 --- a/modules/dnn/perf/perf_layer.cpp +++ b/modules/dnn/perf/perf_layer.cpp @@ -324,103 +324,95 @@ INSTANTIATE_TEST_CASE_P(/**/, Layer_Scatter, Combine( /* withCann= */ false) // only test on CPU )); -struct Layer_ScatterND : public TestBaseWithParam > -{ - void test_layer(const std::vector& shape, const String reduction = "none") +using Layer_ScatterND = TestBaseWithParam, std::string, tuple>>; +PERF_TEST_P_(Layer_ScatterND, scatterND) { + std::vector shape = get<0>(GetParam()); + std::string reduction = get<1>(GetParam()); + int backend_id = get<0>(get<2>(GetParam())); + int target_id = get<1>(get<2>(GetParam())); + + std::vector indices_shape(shape); + indices_shape.push_back(int(shape.size())); + Mat data(shape, CV_32FC1); + Mat indices(indices_shape, CV_32FC1); + Mat updates(shape, CV_32FC1); + + randn(data, 0.f, 1.f); + randn(updates, 0.f, 1.f); + + // initialize the indices with index tuples like [0...N, 0...C, 0...H, 0...W] + std::vector current_index_tuple(shape.size()); + int total = data.total(); + std::vector indices_step; + for (int i = 0; i < indices.dims; i++) { - int backendId = get<0>(GetParam()); - int targetId = get<1>(GetParam()); - - std::vector indices_shape(shape); - indices_shape.push_back(int(shape.size())); - Mat data(shape, CV_32FC1); - Mat indices(indices_shape, CV_32FC1); - Mat updates(shape, CV_32FC1); - - Scalar mean = 0.f; - Scalar std = 1.f; - randn(data, mean, std); - randn(updates, mean, std); - - // initialize the indices with index tuples like [0...N, 0...C, 0...H, 0...W] - std::vector current_index_tuple(shape.size()); - int total = data.total(); - std::vector indices_step; - for (int i = 0; i < indices.dims; i++) + int step = indices.step.p[i] / sizeof(float); + indices_step.push_back(step); + } + int t, j, idx, offset_at_idx, offset; + for (int i = 0; i < total; i++) + { + t = i; + for (j = shape.size() - 1; j >= 0; j--) { - int step = indices.step.p[i] / sizeof(float); - indices_step.push_back(step); - } - int t, j, idx, offset_at_idx, offset; - for (int i = 0; i < total; i++) - { - t = i; - for (j = shape.size() - 1; j >= 0; j--) - { - idx = t / shape[j]; - offset_at_idx = (int)(t - idx * shape[j]); - current_index_tuple[j] = offset_at_idx; - t = idx; - } - - offset = 0; - for (j = 0; j < shape.size(); j++) - offset += current_index_tuple[j] * indices_step[j]; - - for (j = 0; j < shape.size(); j++) - indices.at(offset + j) = current_index_tuple[j]; + idx = t / shape[j]; + offset_at_idx = (int)(t - idx * shape[j]); + current_index_tuple[j] = offset_at_idx; + t = idx; } - Net net; - LayerParams lp; - lp.type = "ScatterND"; - lp.name = "testLayer"; - lp.set("reduction", reduction); + offset = 0; + for (j = 0; j < shape.size(); j++) + offset += current_index_tuple[j] * indices_step[j]; - int id = net.addLayerToPrev(lp.name, lp.type, lp); - net.connect(0, 0, id, 0); - net.connect(0, 1, id, 1); - net.connect(0, 2, id, 2); - - // warmup - { - std::vector inpNames(3); - inpNames[0] = "data"; - inpNames[1] = "indices"; - inpNames[2] = "updates"; - net.setInputsNames(inpNames); - net.setInput(data, inpNames[0]); - net.setInput(indices, inpNames[1]); - net.setInput(updates, inpNames[2]); - - net.setPreferableBackend(backendId); - net.setPreferableTarget(targetId); - Mat out = net.forward(); - } - - TEST_CYCLE() - { - Mat res = net.forward(); - } - - SANITY_CHECK_NOTHING(); + for (j = 0; j < shape.size(); j++) + indices.at(offset + j) = current_index_tuple[j]; } - int N = 8; - int C = 256; - int H = 128; - int W = 100; -}; + Net net; + LayerParams lp; + lp.type = "ScatterND"; + lp.name = "testLayer"; + lp.set("reduction", reduction); -PERF_TEST_P_(Layer_ScatterND, DISABLED_ScatterND) -{ - test_layer({N, C, H ,W}); + int id = net.addLayerToPrev(lp.name, lp.type, lp); + net.connect(0, 0, id, 0); + net.connect(0, 1, id, 1); + net.connect(0, 2, id, 2); + + // warmup + { + std::vector input_names{"data", "indices", "updates"}; + net.setInputsNames(input_names); + net.setInput(data, input_names[0]); + net.setInput(indices, input_names[1]); + net.setInput(updates, input_names[2]); + + net.setPreferableBackend(backend_id); + net.setPreferableTarget(target_id); + Mat out = net.forward(); + } + + TEST_CYCLE() + { + Mat res = net.forward(); + } + + SANITY_CHECK_NOTHING(); } -PERF_TEST_P_(Layer_ScatterND, DISABLED_ScatterND_add) -{ - test_layer({N, C, H , W}, "add"); -} +INSTANTIATE_TEST_CASE_P(/**/, Layer_ScatterND, Combine( + Values(std::vector{2, 128, 64, 50}), + Values(std::string("none"), std::string("add")), + dnnBackendsAndTargets(/* withInferenceEngine= */ false, + /* withHalide= */ false, + /* withCpuOCV= */ true, + /* withVkCom= */ false, + /* withCUDA= */ false, + /* withNgraph= */ false, + /* withWebnn= */ false, + /* withCann= */ false) // only test on CPU +)); struct Layer_LayerNorm : public TestBaseWithParam > { @@ -795,8 +787,6 @@ INSTANTIATE_TEST_CASE_P(/**/, Layer_NaryEltwise, testing::Values(std::make_tuple #ifdef HAVE_CUDA INSTANTIATE_TEST_CASE_P(CUDA, Layer_NaryEltwise, testing::Values(std::make_tuple(DNN_BACKEND_CUDA, DNN_TARGET_CUDA))); #endif -// INSTANTIATE_TEST_CASE_P(/**/, Layer_Scatter, testing::Values(std::make_tuple(DNN_BACKEND_OPENCV, DNN_TARGET_CPU))); -INSTANTIATE_TEST_CASE_P(/**/, Layer_ScatterND, testing::Values(std::make_tuple(DNN_BACKEND_OPENCV, DNN_TARGET_CPU))); INSTANTIATE_TEST_CASE_P(/**/, Layer_LayerNorm, testing::Values(std::make_tuple(DNN_BACKEND_OPENCV, DNN_TARGET_CPU))); INSTANTIATE_TEST_CASE_P(/**/, Layer_LayerNormExpanded, testing::Values(std::make_tuple(DNN_BACKEND_OPENCV, DNN_TARGET_CPU))); INSTANTIATE_TEST_CASE_P(/**/, Layer_GatherElements, testing::Values(std::make_tuple(DNN_BACKEND_OPENCV, DNN_TARGET_CPU))); diff --git a/modules/dnn/src/layers/scatterND_layer.cpp b/modules/dnn/src/layers/scatterND_layer.cpp index 648d35fc0c..531d32f45b 100644 --- a/modules/dnn/src/layers/scatterND_layer.cpp +++ b/modules/dnn/src/layers/scatterND_layer.cpp @@ -89,49 +89,59 @@ public: // NOTE: This impl does not check whether indices have duplicate entries. // The last duplicate entry will overwrite the previous. template - void forward_impl(const Functor& rd, const Mat& data, const Mat& indices, const Mat& updates, Mat& out) - { - data.copyTo(out); + void forward_impl(const Functor &reduce_operation, const Mat &input_mat, const Mat &indices_mat, const Mat &updates_mat, Mat& output_mat) { + input_mat.copyTo(output_mat); - const int* shape = data.size.p; - const size_t* step = data.step.p; + const auto &input_mat_shape = shape(input_mat); + std::vector input_mat_step(input_mat_shape.size()); + for (int i = 0; i < input_mat.dims; i++) { + input_mat_step[i] = static_cast(input_mat.step.p[i] / sizeof(T)); + } - const int ind_ndims = indices.dims; - const int* ind_shape = indices.size.p; - const T* p_indices = indices.ptr(); + const int indices_mat_ndims = indices_mat.dims; + const auto &indices_mat_shape = shape(indices_mat); - const int upd_ndims = updates.dims; - const int* upd_shape = updates.size.p; - const T* p_updates = updates.ptr(); + const int updates_mat_ndims = updates_mat.dims; + const auto &updates_mat_shape = shape(updates_mat); - T* p_out = out.ptr(); - - int k = ind_shape[ind_ndims - 1]; // last dim of indices - size_t total = (size_t)(indices.total() / k); + int indices_last_dim = indices_mat_shape[indices_mat_ndims - 1]; // last dim of indices size_t updates_size = 1; - for (int i = ind_ndims - 1; i < upd_ndims; i++) - updates_size *= upd_shape[i]; + for (int i = indices_mat_ndims - 1; i < updates_mat_ndims; i++) + updates_size *= updates_mat_shape[i]; - size_t inp_start_offset = 0; - size_t ind_start_offset = 0; - size_t upd_start_offset = 0; - for (size_t i = 0; i < total; i++, ind_start_offset += k, upd_start_offset += updates_size) - { - const T* tmp_p_indices = p_indices + ind_start_offset; - inp_start_offset = 0; - for (int j = 0; j < k; j++) - { - CV_Assert(tmp_p_indices[j] < shape[j] && tmp_p_indices[j] > -shape[j]); - inp_start_offset += (((int)tmp_p_indices[j] + shape[j]) % shape[j]) * step[j]; + auto fn = [&](const Range &r) { + size_t input_offset = 0, + indices_offset = r.start * indices_last_dim, + updates_offset = r.start * updates_size; + for (int i = r.start; i < r.end; i++) { + const T* indices = indices_mat.ptr(); + const T* updates = updates_mat.ptr(); + T* output = output_mat.ptr(); + + input_offset = 0; + indices += indices_offset; + for (int j = 0; j < indices_last_dim; j++) { + int index = static_cast(*(indices + j)); + index = (index + input_mat_shape[j]) % input_mat_shape[j]; + CV_Assert(index < input_mat_shape[j] && index >= 0); + input_offset += index * input_mat_step[j]; + } + + updates += updates_offset; + output += input_offset; + for (int j = 0; j < updates_size; j++) { + output[j] = reduce_operation(output[j], updates[j]); + } + + indices_offset += indices_last_dim; + updates_offset += updates_size; } - inp_start_offset /= sizeof(T); + }; - const T* tmp_p_updates = p_updates + upd_start_offset; - T* tmp_p_out = p_out + inp_start_offset; - for (int j = 0; j < updates_size; j++) - tmp_p_out[j] = rd(tmp_p_out[j], tmp_p_updates[j]); - } + size_t total = (size_t)(indices_mat.total() / indices_last_dim); + double nstripes = (size_t)total * (indices_last_dim + updates_size) * (1 / 1024.0); + parallel_for_(Range(0, total), fn, nstripes); } template From b7d70613e431a5f8875001bc590d72d710429954 Mon Sep 17 00:00:00 2001 From: Yuantao Feng Date: Fri, 5 Jan 2024 18:33:01 +0000 Subject: [PATCH 4/5] fix failed assertion in debug build --- modules/dnn/perf/perf_layer.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/modules/dnn/perf/perf_layer.cpp b/modules/dnn/perf/perf_layer.cpp index 3e477da125..ad3bd4c223 100644 --- a/modules/dnn/perf/perf_layer.cpp +++ b/modules/dnn/perf/perf_layer.cpp @@ -350,6 +350,7 @@ PERF_TEST_P_(Layer_ScatterND, scatterND) { indices_step.push_back(step); } int t, j, idx, offset_at_idx, offset; + auto *indices_ptr = indices.ptr(); for (int i = 0; i < total; i++) { t = i; @@ -366,7 +367,7 @@ PERF_TEST_P_(Layer_ScatterND, scatterND) { offset += current_index_tuple[j] * indices_step[j]; for (j = 0; j < shape.size(); j++) - indices.at(offset + j) = current_index_tuple[j]; + indices_ptr[offset + j] = current_index_tuple[j]; } Net net; From 13127365e257ad4ca7b05d2367b5a7d58b256ed3 Mon Sep 17 00:00:00 2001 From: fengyuentau Date: Mon, 8 Jan 2024 11:55:06 +0800 Subject: [PATCH 5/5] better comment --- modules/dnn/perf/perf_layer.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/dnn/perf/perf_layer.cpp b/modules/dnn/perf/perf_layer.cpp index ad3bd4c223..94a0a6b249 100644 --- a/modules/dnn/perf/perf_layer.cpp +++ b/modules/dnn/perf/perf_layer.cpp @@ -340,7 +340,7 @@ PERF_TEST_P_(Layer_ScatterND, scatterND) { randn(data, 0.f, 1.f); randn(updates, 0.f, 1.f); - // initialize the indices with index tuples like [0...N, 0...C, 0...H, 0...W] + // Create indices such that indices[n_i, c_j, h_k, w_l, :4] = [i, j, k, l] std::vector current_index_tuple(shape.size()); int total = data.total(); std::vector indices_step;