From fdb1a94c42706b286f53fe9ac8df559b7aa4393a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E4=B9=90=E4=BB=81=E5=8D=8E?= <31504341+lerenhua@users.noreply.github.com> Date: Mon, 28 Aug 2023 13:54:21 +0800 Subject: [PATCH 01/25] GNNE-1904 Support coordinate_mode and nearest_mode selection for nearest resize_image (#1065) * Support coordinate_mode and nearest_mode selection for nearest resize * Support comment in json and add resize_image config json * Fix aligned corners in nearest resize * Fix bug * Add more resize_image case * Fix cos compution occur nan --------- Co-authored-by: lerenhua --- .../include/nncase/kernels/kernel_utils.h | 1 + .../nncase/kernels/stackvm/resize_image.h | 94 +++++++ .../src/kernels/stackvm/optimized/opt_ops.h | 4 +- .../stackvm/optimized/resize_image.cpp | 36 ++- .../src/kernels/stackvm/reference/ref_ops.h | 3 + .../stackvm/reference/resize_image.cpp | 36 ++- src/Native/src/kernels/stackvm/tensor_ops.cpp | 6 +- tests/kernels/kernel_test.h | 97 ++++--- tests/kernels/test_resize_image.cpp | 258 +++++------------- tests/kernels/test_resize_image.json | 8 +- 10 files changed, 289 insertions(+), 254 deletions(-) create mode 100644 src/Native/include/nncase/kernels/stackvm/resize_image.h diff --git a/src/Native/include/nncase/kernels/kernel_utils.h b/src/Native/include/nncase/kernels/kernel_utils.h index 2dc83ec4a6..f787f5976f 100644 --- a/src/Native/include/nncase/kernels/kernel_utils.h +++ b/src/Native/include/nncase/kernels/kernel_utils.h @@ -17,6 +17,7 @@ #include #include #include +#include #include #include diff --git a/src/Native/include/nncase/kernels/stackvm/resize_image.h b/src/Native/include/nncase/kernels/stackvm/resize_image.h new file mode 100644 index 0000000000..72ff9a69d9 --- /dev/null +++ b/src/Native/include/nncase/kernels/stackvm/resize_image.h @@ -0,0 +1,94 @@ +/* Copyright 2019-2023 Canaan Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#pragma once +#include + +using namespace nncase::runtime::stackvm; + +using get_coordinate_func_t = float (*)(float, float, float, float, float, + float); +using get_nearest_pixel_func_t = int64_t (*)(float); + +get_coordinate_func_t get_coordinate_from_resized( + image_resize_transformation_mode_t coordinate_transform_mode); + +get_nearest_pixel_func_t +get_nearest_pixel_from_origin(image_resize_nearest_mode_t nearest_mode); + +inline get_coordinate_func_t get_coordinate_from_resized( + image_resize_transformation_mode_t coordinate_transform_mode) { + switch (coordinate_transform_mode) { + case image_resize_transformation_mode_t::asymmetric: + return [](float x_resized, float x_scale, float, float, float, float) { + return x_resized * x_scale; + }; + case image_resize_transformation_mode_t::pytorch_half_pixel: + return [](float x_resized, float x_scale, float length_resized, float, + float, float) { + return length_resized > 1 ? (x_resized + 0.5f) * x_scale - 0.5f + : 0.0f; + }; + case image_resize_transformation_mode_t::align_corners: + return [](float x_resized, float, float length_resized, + float length_original, float, float) { + return length_resized == 1 ? 0 + : x_resized * (length_original - 1) / + (length_resized - 1); + }; + case image_resize_transformation_mode_t::tfcrop_and_resize: + return [](float x_resized, float, float length_resized, + float length_original, float roi_start, float roi_end) { + auto orig = + length_resized > 1 + ? roi_start * (length_original - 1) + + (x_resized * (roi_end - roi_start) * + (length_original - 1)) / + (length_resized - 1) + : 0.5 * (roi_start + roi_end) * (length_original - 1); + return static_cast(orig); + }; + default: // "image_resize_transformation_mode_t::half_pixel" + return [](float x_resized, float x_scale, float, float, float, float) { + return ((x_resized + 0.5f) * x_scale) - 0.5f; + }; + } +} + +inline get_nearest_pixel_func_t +get_nearest_pixel_from_origin(image_resize_nearest_mode_t nearest_mode) { + switch (nearest_mode) { + case image_resize_nearest_mode_t::round_prefer_ceil: + return [](float x_original) { + return static_cast(std::round(x_original)); + }; + case image_resize_nearest_mode_t::floor: + return [](float x_original) { + return static_cast(std::floor(x_original)); + }; + case image_resize_nearest_mode_t::ceil: + return [](float x_original) { + return static_cast(std::ceil(x_original)); + }; + default: // default is round_prefer_floor + return [](float x_original) { + // for half way cases prefer floor + if (x_original == static_cast(x_original) + 0.5f) { + return static_cast(std::floor(x_original)); + } + return static_cast(std::round(x_original)); + }; + } +} \ No newline at end of file diff --git a/src/Native/src/kernels/stackvm/optimized/opt_ops.h b/src/Native/src/kernels/stackvm/optimized/opt_ops.h index 7c935a722f..c15fba913d 100644 --- a/src/Native/src/kernels/stackvm/optimized/opt_ops.h +++ b/src/Native/src/kernels/stackvm/optimized/opt_ops.h @@ -17,13 +17,13 @@ */ #pragma once #include +#include #include #include #include #include #include #include - BEGIN_NS_NNCASE_KERNELS_MODULE(stackvm) namespace optimized { @@ -111,6 +111,8 @@ NNCASE_API result resize_nearest_neighbor( gsl::span in_shape, gsl::span in_strides, gsl::span out_strides, int32_t out_h, int32_t out_w, bool align_corners, bool half_pixel_centers, + get_coordinate_func_t get_coordinate_func, + get_nearest_pixel_func_t get_nearset_func, kernel_context &context) noexcept; NNCASE_API result diff --git a/src/Native/src/kernels/stackvm/optimized/resize_image.cpp b/src/Native/src/kernels/stackvm/optimized/resize_image.cpp index 57d87462d4..14b1672718 100644 --- a/src/Native/src/kernels/stackvm/optimized/resize_image.cpp +++ b/src/Native/src/kernels/stackvm/optimized/resize_image.cpp @@ -89,7 +89,10 @@ result resize_nearest_neighbor_impl( const T *input, T *output, gsl::span in_shape, NNCASE_UNUSED gsl::span in_strides, NNCASE_UNUSED gsl::span out_strides, int32_t out_h, - int32_t out_w, bool align_corners, bool half_pixel_centers, + int32_t out_w, NNCASE_UNUSED bool align_corners, + NNCASE_UNUSED bool half_pixel_centers, + get_coordinate_func_t get_coordinate_func, + get_nearest_pixel_func_t get_nearset_func, NNCASE_UNUSED kernel_context &context) noexcept { auto scales = kernels::detail::get_resize_scales(in_shape, out_h, out_w, align_corners); @@ -110,15 +113,23 @@ result resize_nearest_neighbor_impl( auto *output_ptr = begin_output_ptr + oc * out_image_size; for (int oy = 0; oy < out_h; oy++) { - auto in_y = kernels::detail::get_nearest_neighbor( - oy, in_shape[2], height_scale, align_corners, - half_pixel_centers); + auto iy = get_coordinate_func(oy, height_scale, out_h, + in_shape[2], 0, 0); + int64_t in_y = get_nearset_func(iy); + if (in_y < 0) + in_y = 0; + if (in_y >= in_shape[2]) + in_y = in_shape[2] - 1; auto *in_row = input_ptr + in_y * in_shape[3]; for (int ox = 0; ox < out_w; ox++) { - auto in_x = kernels::detail::get_nearest_neighbor( - ox, in_shape[3], width_scale, align_corners, - half_pixel_centers); + auto ix = get_coordinate_func(ox, width_scale, out_w, + in_shape[3], 0, 0); + int64_t in_x = get_nearset_func(ix); + if (in_x < 0) + in_x = 0; + if (in_x >= in_shape[3]) + in_x = in_shape[3] - 1; *output_ptr++ = in_row[in_x]; } } @@ -264,10 +275,11 @@ inline result resize_bilinear_impl( half_pixel_centers, context); #define RESIZE_NEAREST_NEIGHBOR_IMPL(type) \ - resize_nearest_neighbor_impl(reinterpret_cast(input), \ - reinterpret_cast(output), in_shape, \ - in_strides, out_strides, out_h, out_w, \ - align_corners, half_pixel_centers, context); + resize_nearest_neighbor_impl( \ + reinterpret_cast(input), \ + reinterpret_cast(output), in_shape, in_strides, out_strides, \ + out_h, out_w, align_corners, half_pixel_centers, get_coordinate_func, \ + get_nearset_func, context); result optimized::resize_bilinear( typecode_t type, const gsl::byte *input, gsl::byte *output, @@ -283,6 +295,8 @@ result optimized::resize_nearest_neighbor( gsl::span in_shape, gsl::span in_strides, gsl::span out_strides, int32_t out_h, int32_t out_w, bool align_corners, bool half_pixel_centers, + get_coordinate_func_t get_coordinate_func, + get_nearest_pixel_func_t get_nearset_func, kernel_context &context) noexcept { FP_OR_Q_IMPL(type, RESIZE_NEAREST_NEIGHBOR_IMPL); } \ No newline at end of file diff --git a/src/Native/src/kernels/stackvm/reference/ref_ops.h b/src/Native/src/kernels/stackvm/reference/ref_ops.h index c6bc7b2d7d..4111eaaac5 100644 --- a/src/Native/src/kernels/stackvm/reference/ref_ops.h +++ b/src/Native/src/kernels/stackvm/reference/ref_ops.h @@ -18,6 +18,7 @@ #pragma once #include #include +#include #include #include #include @@ -345,6 +346,8 @@ NNCASE_API result resize_nearest_neighbor( gsl::span in_shape, gsl::span in_strides, gsl::span out_strides, int32_t out_h, int32_t out_w, bool align_corners, bool half_pixel_centers, + get_coordinate_func_t get_coordinate_func, + get_nearest_pixel_func_t get_nearset_func, kernel_context &context) noexcept; NNCASE_API result reverse_sequence( diff --git a/src/Native/src/kernels/stackvm/reference/resize_image.cpp b/src/Native/src/kernels/stackvm/reference/resize_image.cpp index f9d62d40e2..4cc973c906 100644 --- a/src/Native/src/kernels/stackvm/reference/resize_image.cpp +++ b/src/Native/src/kernels/stackvm/reference/resize_image.cpp @@ -91,7 +91,10 @@ template result resize_nearest_neighbor_impl( const T *input, T *output, gsl::span in_shape, gsl::span in_strides, gsl::span out_strides, - int32_t out_h, int32_t out_w, bool align_corners, bool half_pixel_centers, + int32_t out_h, int32_t out_w, NNCASE_UNUSED bool align_corners, + NNCASE_UNUSED bool half_pixel_centers, + get_coordinate_func_t get_coordinate_func, + get_nearest_pixel_func_t get_nearset_func, NNCASE_UNUSED kernel_context &context) noexcept { auto scales = kernels::detail::get_resize_scales(in_shape, out_h, out_w, align_corners); @@ -106,16 +109,24 @@ result resize_nearest_neighbor_impl( in_index[1] = oc; out_index[1] = oc; for (size_t oy = 0; oy < (size_t)out_h; oy++) { - auto in_y = kernels::detail::get_nearest_neighbor( - oy, in_shape[2], height_scale, align_corners, - half_pixel_centers); + auto iy = get_coordinate_func(oy, height_scale, out_h, + in_shape[2], 0, 0); + int64_t in_y = get_nearset_func(iy); + if (in_y < 0) + in_y = 0; + if (in_y >= in_shape[2]) + in_y = in_shape[2] - 1; in_index[2] = in_y; out_index[2] = oy; for (size_t ox = 0; ox < (size_t)out_w; ox++) { - auto in_x = kernels::detail::get_nearest_neighbor( - ox, in_shape[3], width_scale, align_corners, - half_pixel_centers); + auto ix = get_coordinate_func(ox, width_scale, out_w, + in_shape[3], 0, 0); + int64_t in_x = get_nearset_func(ix); + if (in_x < 0) + in_x = 0; + if (in_x >= in_shape[3]) + in_x = in_shape[3] - 1; in_index[3] = in_x; out_index[3] = ox; output[offset(out_strides, out_index)] = @@ -154,10 +165,11 @@ result resize_nearest_neighbor_impl( half_pixel_centers, context); #define RESIZE_NEAREST_NEIGHBOR_IMPL(type) \ - resize_nearest_neighbor_impl(reinterpret_cast(input), \ - reinterpret_cast(output), in_shape, \ - in_strides, out_strides, out_h, out_w, \ - align_corners, half_pixel_centers, context); + resize_nearest_neighbor_impl( \ + reinterpret_cast(input), \ + reinterpret_cast(output), in_shape, in_strides, out_strides, \ + out_h, out_w, align_corners, half_pixel_centers, get_coordinate_func, \ + get_nearset_func, context); } // namespace result nncase::kernels::stackvm::reference::resize_bilinear( @@ -174,6 +186,8 @@ result nncase::kernels::stackvm::reference::resize_nearest_neighbor( gsl::span in_shape, gsl::span in_strides, gsl::span out_strides, int32_t out_h, int32_t out_w, bool align_corners, bool half_pixel_centers, + get_coordinate_func_t get_coordinate_func, + get_nearest_pixel_func_t get_nearset_func, kernel_context &context) noexcept { FP_OR_Q_IMPL(type, RESIZE_NEAREST_NEIGHBOR_IMPL); } \ No newline at end of file diff --git a/src/Native/src/kernels/stackvm/tensor_ops.cpp b/src/Native/src/kernels/stackvm/tensor_ops.cpp index 7f668492c3..ea5726d8cb 100644 --- a/src/Native/src/kernels/stackvm/tensor_ops.cpp +++ b/src/Native/src/kernels/stackvm/tensor_ops.cpp @@ -841,11 +841,15 @@ result nncase::kernels::stackvm::resize_image( new_size_value[2], new_size_value[3], align_corner, half_pixel, context); } else if (resize_mode == image_resize_mode_t::nearest_neighbor) { + auto get_coordinate_func = + get_coordinate_from_resized(transformation_mode); + auto get_nearset_func = get_nearest_pixel_from_origin(nearest_mode); CONTIGUOUS_KERNEL(resize_nearest_neighbor, input_tensor, tycode, in_mem, out_mem, input_tensor->shape(), input_tensor->strides(), output_tensor->strides(), new_size_value[2], new_size_value[3], align_corner, - half_pixel, context); + half_pixel, get_coordinate_func, get_nearset_func, + context); } else { return err(nncase_errc::runtime_not_found); } diff --git a/tests/kernels/kernel_test.h b/tests/kernels/kernel_test.h index fa3e491cc1..c0ba0ca2ea 100644 --- a/tests/kernels/kernel_test.h +++ b/tests/kernels/kernel_test.h @@ -838,8 +838,8 @@ class KernelTest { } } - std::vector vec1; - std::vector vec2; + std::vector vec1; + std::vector vec2; vec1.reserve(compute_size(lhs.shape())); vec2.reserve(compute_size(rhs.shape())); @@ -849,79 +849,83 @@ class KernelTest { auto dtype = lhs.datatype(); switch (dtype) { case dt_int8: { - vec1.push_back(static_cast(get(lhs, index))); - vec2.push_back(static_cast(get(rhs, index))); + vec1.push_back( + static_cast(get(lhs, index))); + vec2.push_back( + static_cast(get(rhs, index))); break; } case dt_int16: { vec1.push_back( - static_cast(get(lhs, index))); + static_cast(get(lhs, index))); vec2.push_back( - static_cast(get(rhs, index))); + static_cast(get(rhs, index))); break; } case dt_int32: { vec1.push_back( - static_cast(get(lhs, index))); + static_cast(get(lhs, index))); vec2.push_back( - static_cast(get(rhs, index))); + static_cast(get(rhs, index))); break; } case dt_int64: { vec1.push_back( - static_cast(get(lhs, index))); + static_cast(get(lhs, index))); vec2.push_back( - static_cast(get(rhs, index))); + static_cast(get(rhs, index))); break; } case dt_uint8: { vec1.push_back( - static_cast(get(lhs, index))); + static_cast(get(lhs, index))); vec2.push_back( - static_cast(get(rhs, index))); + static_cast(get(rhs, index))); break; } case dt_uint16: { vec1.push_back( - static_cast(get(lhs, index))); + static_cast(get(lhs, index))); vec2.push_back( - static_cast(get(rhs, index))); + static_cast(get(rhs, index))); break; } case dt_uint32: { vec1.push_back( - static_cast(get(lhs, index))); + static_cast(get(lhs, index))); vec2.push_back( - static_cast(get(rhs, index))); + static_cast(get(rhs, index))); break; } case dt_uint64: { vec1.push_back( - static_cast(get(lhs, index))); + static_cast(get(lhs, index))); vec2.push_back( - static_cast(get(rhs, index))); + static_cast(get(rhs, index))); break; } case dt_float16: { - vec1.push_back(static_cast(get(lhs, index))); - vec2.push_back(static_cast(get(rhs, index))); + vec1.push_back(static_cast(get(lhs, index))); + vec2.push_back(static_cast(get(rhs, index))); break; } case dt_bfloat16: { vec1.push_back( - static_cast(get(lhs, index))); + static_cast(get(lhs, index))); vec2.push_back( - static_cast(get(rhs, index))); + static_cast(get(rhs, index))); break; } case dt_float32: { - vec1.push_back(get(lhs, index)); - vec2.push_back(get(rhs, index)); + vec1.push_back(static_cast(get(lhs, index))); + vec2.push_back(static_cast(get(rhs, index))); break; } case dt_float64: { - vec1.push_back(static_cast(get(lhs, index))); - vec2.push_back(static_cast(get(rhs, index))); + vec1.push_back( + static_cast(get(lhs, index))); + vec2.push_back( + static_cast(get(rhs, index))); break; } default: { @@ -932,13 +936,13 @@ class KernelTest { }) .is_ok(); - float dotProduct = - std::inner_product(vec1.begin(), vec1.end(), vec2.begin(), 0.0f); - float norm1 = std::sqrt( - std::inner_product(vec1.begin(), vec1.end(), vec1.begin(), 0.0f)); - float norm2 = std::sqrt( - std::inner_product(vec2.begin(), vec2.end(), vec2.begin(), 0.0f)); - float cosine_similarity = dotProduct / (norm1 * norm2); + double dotProduct = std::inner_product(vec1.begin(), vec1.end(), + vec2.begin(), (double)0.0); + double norm1 = std::sqrt(std::inner_product(vec1.begin(), vec1.end(), + vec1.begin(), (double)0.0)); + double norm2 = std::sqrt(std::inner_product(vec2.begin(), vec2.end(), + vec2.begin(), (double)0.0)); + double cosine_similarity = dotProduct / (norm1 * norm2); std::cout << "cosine_similarity:" << cosine_similarity << std::endl; @@ -1071,7 +1075,7 @@ class KernelTest { } static void ParseJson(Document &document, std::string js_str) { - if (document.Parse(js_str.c_str()).HasParseError()) + if (document.Parse(js_str.c_str()).HasParseError()) std::cout << "Parsing Error: " << (unsigned)document.GetErrorOffset() << " " << GetParseError_En(document.GetParseError()) @@ -1080,7 +1084,7 @@ class KernelTest { } void ParseJson(std::string js_str) { - if (_document.Parse(js_str.c_str()).HasParseError()) + if (_document.Parse(js_str.c_str()).HasParseError()) std::cout << "Parsing Error: " << (unsigned)_document.GetErrorOffset() << " " << GetParseError_En(_document.GetParseError()) @@ -1112,6 +1116,11 @@ class KernelTest { return Str2DataType(_document[key].GetString()); } + std::string GetString(const char *key) { + assert(_document[key].IsString()); + return _document[key].GetString(); + } + dims_t GetShapeArray(const char *key) { assert(_document[key].IsArray()); @@ -1130,6 +1139,24 @@ class KernelTest { return cArray; } + std::vector GetDataArray(const char *key) { + assert(_document[key].IsArray()); + + Value &array = _document[key]; + size_t arraySize = array.Size(); + std::vector cArray(arraySize); + for (rapidjson::SizeType i = 0; i < arraySize; i++) { + if (array[i].IsUint()) { + cArray[i] = array[i].GetUint(); + } else { + std::cout << "Invalid JSON format. Expected unsigned integer " + "values in the array." + << std::endl; + } + } + return cArray; + } + axes_t GetAxesArray(const char *key) { assert(_document[key].IsArray()); diff --git a/tests/kernels/test_resize_image.cpp b/tests/kernels/test_resize_image.cpp index 947020b3a0..63a722edf3 100644 --- a/tests/kernels/test_resize_image.cpp +++ b/tests/kernels/test_resize_image.cpp @@ -24,6 +24,7 @@ using namespace nncase; using namespace nncase::runtime; +using namespace nncase::runtime::stackvm; using namespace ortki; #define TEST_CASE_NAME "test_resize_image" @@ -36,32 +37,68 @@ class ResizeImageTest : public KernelTest, auto typecode = GetDataType("lhs_type"); auto l_shape = GetShapeArray("i_shape"); - + resize_mode_str = GetString("resize_mode"); + tranform_mode_str = GetString("transform_mode"); + nearest_mode_str = GetString("nearest_mode"); + resize_mode = Str2Mode(resize_mode_str, str_2_resizemode); + tranform_mode = Str2Mode(tranform_mode_str, str_2_transformmode); + nearest_mode = Str2Mode(nearest_mode_str, str_2_nearestmode); + new_shape_array = GetDataArray("o_shape"); + new_shape = + hrt::create(dt_int64, {4}, + {reinterpret_cast(new_shape_array.data()), + sizeof(new_shape_array[0]) * new_shape_array.size()}, + true, host_runtime_tensor::pool_cpu_only) + .expect("create tensor failed"); lhs = hrt::create(typecode, l_shape, host_runtime_tensor::pool_cpu_only) .expect("create tensor failed"); init_tensor(lhs); } + template + T Str2Mode(std::string type, std::map &str_2_mode) { + std::cout << type << std::endl; + if (str_2_mode.find(type) != str_2_mode.end()) { + return str_2_mode[type]; + } else { + // should not be here + return static_cast(0); + } + } void TearDown() override { CLEAR_SUBCASE() } protected: runtime_tensor lhs; + runtime_tensor new_shape; + image_resize_mode_t resize_mode; + std::string resize_mode_str; + image_resize_transformation_mode_t tranform_mode; + std::string tranform_mode_str; + image_resize_nearest_mode_t nearest_mode; + std::string nearest_mode_str; + std::vector new_shape_array; + std::map str_2_resizemode = { + {"linear", image_resize_mode_t::bilinear}, + {"nearest", image_resize_mode_t::nearest_neighbor}}; + std::map + str_2_transformmode = { + {"half_pixel", image_resize_transformation_mode_t::half_pixel}, + {"pytorch_half_pixel", + image_resize_transformation_mode_t::pytorch_half_pixel}, + {"align_corners", + image_resize_transformation_mode_t::align_corners}, + {"asymmetric", image_resize_transformation_mode_t::asymmetric}}; + std::map str_2_nearestmode = { + {"round_prefer_floor", image_resize_nearest_mode_t::round_prefer_floor}, + {"round_prefer_ceil", image_resize_nearest_mode_t::round_prefer_ceil}, + {"floor", image_resize_nearest_mode_t::floor}, + {"ceil", image_resize_nearest_mode_t::ceil}}; }; INSTANTIATE_TEST_SUITE_P(ResizeImage, ResizeImageTest, testing::Combine(testing::Range(0, MAX_CASE_NUM))); TEST_P(ResizeImageTest, ResizeImage) { - - // actual - int64_t new_shape_array[] = {1, 3, 112, 112}; - auto new_shape = - hrt::create(dt_int64, {4}, - {reinterpret_cast(new_shape_array), - sizeof(new_shape_array)}, - true, host_runtime_tensor::pool_cpu_only) - .expect("create tensor failed"); - float roi_array[1]; auto roi = hrt::create(dt_float32, {1}, {reinterpret_cast(roi_array), @@ -95,24 +132,17 @@ TEST_P(ResizeImageTest, ResizeImage) { auto output = kernels::stackvm::resize_image( - runtime::stackvm::image_resize_mode_t::bilinear, - runtime::stackvm::image_resize_transformation_mode_t::half_pixel, - runtime::stackvm::image_resize_nearest_mode_t::round_prefer_floor, - false, lhs.impl(), roi.impl(), new_shape.impl(), - cubic_coeff_a.impl(), exclude_outside.impl(), - extrapolation_value.impl()) + resize_mode, tranform_mode, nearest_mode, false, lhs.impl(), + roi.impl(), new_shape.impl(), cubic_coeff_a.impl(), + exclude_outside.impl(), extrapolation_value.impl()) .expect("resize_image failed"); runtime_tensor actual(output.as().expect("as tensor failed")); - const char *transformation_mode = "half_pixel"; - const char *resize_mode_t = "linear"; - const char *nearest_mode_t = "round_prefer_floor"; - // expected auto output_ort = ortki_ResizeWithSizes( runtime_tensor_2_ort_tensor(lhs), runtime_tensor_2_ort_tensor(roi), - runtime_tensor_2_ort_tensor(new_shape), transformation_mode, -0.75f, 0l, - 0.0f, resize_mode_t, nearest_mode_t); + runtime_tensor_2_ort_tensor(new_shape), tranform_mode_str.c_str(), + -0.75f, 0l, 0.0f, resize_mode_str.c_str(), nearest_mode_str.c_str()); size_t size = 0; void *ptr_ort = tensor_buffer(output_ort, &size); @@ -134,187 +164,29 @@ TEST_P(ResizeImageTest, ResizeImage) { // compare EXPECT_TRUE(result); - - // actual - - // actual - int64_t new_shape_array1[] = {1, 3, 112, 112}; - auto new_shape1 = - hrt::create(dt_int64, {4}, - {reinterpret_cast(new_shape_array1), - sizeof(new_shape_array1)}, - true, host_runtime_tensor::pool_cpu_only) - .expect("create tensor failed"); - - float roi_array1[1]; - auto roi1 = hrt::create(dt_float32, {1}, - {reinterpret_cast(roi_array1), - sizeof(roi_array1)}, - true, host_runtime_tensor::pool_cpu_only) - .expect("create tensor failed"); - int32_t exclude_outside_array1[] = {0}; - - auto exclude_outside1 = - hrt::create(dt_int32, {1}, - {reinterpret_cast(exclude_outside_array1), - sizeof(exclude_outside_array1)}, - true, host_runtime_tensor::pool_cpu_only) - .expect("create tensor failed"); - - float cubic_coeff_a_array1[] = {-0.75f}; - auto cubic_coeff_a1 = - hrt::create(dt_float32, {1}, - {reinterpret_cast(cubic_coeff_a_array1), - sizeof(cubic_coeff_a_array1)}, - true, host_runtime_tensor::pool_cpu_only) - .expect("create tensor failed"); - - float_t extrapolation_value_array1[] = {0.0f}; - auto extrapolation_value1 = - hrt::create(dt_float32, {1}, - {reinterpret_cast(extrapolation_value_array1), - sizeof(extrapolation_value_array1)}, - true, host_runtime_tensor::pool_cpu_only) - .expect("create tensor failed"); - - auto output1 = - kernels::stackvm::resize_image( - runtime::stackvm::image_resize_mode_t::bilinear, - runtime::stackvm::image_resize_transformation_mode_t:: - pytorch_half_pixel, - runtime::stackvm::image_resize_nearest_mode_t::round_prefer_ceil, - false, lhs.impl(), roi1.impl(), new_shape1.impl(), - cubic_coeff_a1.impl(), exclude_outside1.impl(), - extrapolation_value1.impl()) - .expect("resize_image failed"); - runtime_tensor actual1(output1.as().expect("as tensor failed")); - - const char *transformation_mode1 = "pytorch_half_pixel"; - const char *resize_mode_t1 = "linear"; - const char *nearest_mode_t1 = "round_prefer_floor"; - - // expected - auto output_ort1 = ortki_ResizeWithSizes( - runtime_tensor_2_ort_tensor(lhs), runtime_tensor_2_ort_tensor(roi1), - runtime_tensor_2_ort_tensor(new_shape1), transformation_mode1, -0.75f, - 0l, 0.0f, resize_mode_t1, nearest_mode_t1); - - size_t size1 = 0; - void *ptr_ort1 = tensor_buffer(output_ort1, &size1); - dims_t shape1(tensor_rank(output_ort1)); - tensor_shape(output_ort1, reinterpret_cast(shape1.data())); - auto expected1 = - hrt::create(lhs.datatype(), shape1, - {reinterpret_cast(ptr_ort1), size1}, true, - host_runtime_tensor::pool_cpu_only) - .expect("create tensor failed"); - bool result1 = is_same_tensor(expected1, actual1) || - cosine_similarity_tensor(expected1, actual1); - - if (!result1) { - std::cout << "actual "; - print_runtime_tensor(actual1); - std::cout << "expected "; - print_runtime_tensor(expected1); - } - - // compare - EXPECT_TRUE(result1); - - // actual - int64_t new_shape_array2[] = {1, 3, 112, 112}; - auto new_shape2 = - hrt::create(dt_int64, {4}, - {reinterpret_cast(new_shape_array2), - sizeof(new_shape_array2)}, - true, host_runtime_tensor::pool_cpu_only) - .expect("create tensor failed"); - - float_t roi_array2[1]; - auto roi2 = hrt::create(dt_float32, {1}, - {reinterpret_cast(roi_array2), - sizeof(roi_array2)}, - true, host_runtime_tensor::pool_cpu_only) - .expect("create tensor failed"); - int32_t exclude_outside_array2[] = {0}; - - auto exclude_outside2 = - hrt::create(dt_int32, {1}, - {reinterpret_cast(exclude_outside_array2), - sizeof(exclude_outside_array2)}, - true, host_runtime_tensor::pool_cpu_only) - .expect("create tensor failed"); - - float_t cubic_coeff_a_array2[] = {-0.75f}; - auto cubic_coeff_a2 = - hrt::create(dt_float32, {1}, - {reinterpret_cast(cubic_coeff_a_array2), - sizeof(cubic_coeff_a_array2)}, - true, host_runtime_tensor::pool_cpu_only) - .expect("create tensor failed"); - - float_t extrapolation_value_array2[] = {0.0f}; - auto extrapolation_value2 = - hrt::create(dt_float32, {1}, - {reinterpret_cast(extrapolation_value_array2), - sizeof(extrapolation_value_array2)}, - true, host_runtime_tensor::pool_cpu_only) - .expect("create tensor failed"); - - auto output2 = - kernels::stackvm::resize_image( - runtime::stackvm::image_resize_mode_t::bilinear, - runtime::stackvm::image_resize_transformation_mode_t:: - pytorch_half_pixel, - runtime::stackvm::image_resize_nearest_mode_t::round_prefer_ceil, - false, lhs.impl(), roi2.impl(), new_shape2.impl(), - cubic_coeff_a2.impl(), exclude_outside2.impl(), - extrapolation_value2.impl()) - .expect("resize_image failed"); - runtime_tensor actual2(output2.as().expect("as tensor failed")); - - const char *transformation_mode2 = "pytorch_half_pixel"; - const char *resize_mode_t2 = "linear"; - const char *nearest_mode_t2 = "round_prefer_ceil"; - - // expected - auto output_ort2 = ortki_ResizeWithSizes( - runtime_tensor_2_ort_tensor(lhs), runtime_tensor_2_ort_tensor(roi2), - runtime_tensor_2_ort_tensor(new_shape2), transformation_mode2, -0.75f, - 0l, 0.0f, resize_mode_t2, nearest_mode_t2); - - size_t size2 = 0; - void *ptr_ort2 = tensor_buffer(output_ort2, &size2); - dims_t shape2(tensor_rank(output_ort2)); - tensor_shape(output_ort2, reinterpret_cast(shape2.data())); - auto expected2 = - hrt::create(lhs.datatype(), shape2, - {reinterpret_cast(ptr_ort2), size2}, true, - host_runtime_tensor::pool_cpu_only) - .expect("create tensor failed"); - bool result2 = is_same_tensor(expected2, actual2) || - cosine_similarity_tensor(expected2, actual2); - - if (!result2) { - std::cout << "actual "; - print_runtime_tensor(actual2); - std::cout << "expected "; - print_runtime_tensor(expected2); - } - - // compare - EXPECT_TRUE(result2); } int main(int argc, char *argv[]) { READY_TEST_CASE_GENERATE() FOR_LOOP(lhs_type, i) FOR_LOOP(i_shape, j) + FOR_LOOP(o_shape, p) + FOR_LOOP(resize_mode, k) + FOR_LOOP(transform_mode, m) + FOR_LOOP(nearest_mode, n) SPLIT_ELEMENT(lhs_type, i) SPLIT_ELEMENT(i_shape, j) + SPLIT_ELEMENT(o_shape, p) + SPLIT_ELEMENT(resize_mode, k) + SPLIT_ELEMENT(transform_mode, m) + SPLIT_ELEMENT(nearest_mode, n) WRITE_SUB_CASE() FOR_LOOP_END() FOR_LOOP_END() + FOR_LOOP_END() + FOR_LOOP_END() + FOR_LOOP_END() + FOR_LOOP_END() ::testing::InitGoogleTest(&argc, argv); return RUN_ALL_TESTS(); diff --git a/tests/kernels/test_resize_image.json b/tests/kernels/test_resize_image.json index 8dcce05246..aa9952d8f3 100644 --- a/tests/kernels/test_resize_image.json +++ b/tests/kernels/test_resize_image.json @@ -1,4 +1,8 @@ { - "i_shape":[[1, 3, 224, 224]], - "lhs_type":["dt_float32"] + "i_shape":[[1, 3, 224, 224], [1, 3, 55, 56], [1, 3, 224, 55]], + "o_shape":[[1, 3, 112, 112]], + "lhs_type":["dt_float32"], + "resize_mode": ["linear", "nearest"], + "transform_mode": ["half_pixel", "pytorch_half_pixel", "asymmetric", "align_corners"], + "nearest_mode": ["ceil", "floor", "round_prefer_ceil", "round_prefer_floor"] } \ No newline at end of file From aaf05655456f08b32988a00bdb1dcb2084858263 Mon Sep 17 00:00:00 2001 From: HeJunchao <73169088+HeJunchao100813@users.noreply.github.com> Date: Mon, 28 Aug 2023 17:02:06 +0800 Subject: [PATCH 02/25] fix test_celu (#1069) * fix test_celu * format * fix celu's input * fix celu's alpha * fix * fix celu's test&&cosine fun --------- Co-authored-by: hejunchao --- tests/kernels/test_broadcast.cpp | 6 ++-- tests/kernels/test_cast.cpp | 2 +- tests/kernels/test_celu.cpp | 47 +++++++++++++++++++++++++++++++- tests/kernels/test_celu.json | 2 +- tests/kernels/test_clamp.json | 4 +-- 5 files changed, 53 insertions(+), 8 deletions(-) diff --git a/tests/kernels/test_broadcast.cpp b/tests/kernels/test_broadcast.cpp index 7e8eb4e7ca..3c63d308a8 100644 --- a/tests/kernels/test_broadcast.cpp +++ b/tests/kernels/test_broadcast.cpp @@ -34,9 +34,9 @@ class BroadCastTest : public KernelTest, void SetUp() override { READY_SUBCASE() - auto typecode = GetDataType("lhs_type"); auto l_shape = GetShapeArray("lhs_shape"); auto r_shape = GetShapeArray("rhs_shape"); + auto typecode = GetDataType("lhs_type"); input = hrt::create(typecode, r_shape, host_runtime_tensor::pool_cpu_only) @@ -219,12 +219,12 @@ TEST_P(BroadCastTest, BroadCast) { int main(int argc, char *argv[]) { READY_TEST_CASE_GENERATE() - FOR_LOOP(lhs_type, i) FOR_LOOP(lhs_shape, j) FOR_LOOP(rhs_shape, k) - SPLIT_ELEMENT(lhs_type, i) + FOR_LOOP(lhs_type, i) SPLIT_ELEMENT(lhs_shape, j) SPLIT_ELEMENT(rhs_shape, k) + SPLIT_ELEMENT(lhs_type, i) WRITE_SUB_CASE() FOR_LOOP_END() FOR_LOOP_END() diff --git a/tests/kernels/test_cast.cpp b/tests/kernels/test_cast.cpp index adcec1f2f1..cea9bee37c 100644 --- a/tests/kernels/test_cast.cpp +++ b/tests/kernels/test_cast.cpp @@ -37,7 +37,7 @@ class CastTest : public KernelTest, auto typecode_input = GetDataType("lhs_type"); auto typecode_output = GetDataType("rhs_type"); - auto l_shape = GetShapeArray("i_shape"); + auto l_shape = GetShapeArray("lhs_shape"); input = hrt::create(typecode_input, l_shape, host_runtime_tensor::pool_cpu_only) diff --git a/tests/kernels/test_celu.cpp b/tests/kernels/test_celu.cpp index 8727460204..63f8c2ac5c 100644 --- a/tests/kernels/test_celu.cpp +++ b/tests/kernels/test_celu.cpp @@ -44,11 +44,56 @@ class CeluTest : public KernelTest, alpha = hrt::create(typecode, {1}, host_runtime_tensor::pool_cpu_only) .expect("create tensor failed"); - init_tensor(alpha); + init_tensor_alpha(alpha); } void TearDown() override {} + virtual void init_tensor_alpha(runtime::runtime_tensor &tensor) { + auto dtype = tensor.datatype(); + switch (dtype) { + case dt_float16: { + std::random_device rd; + std::mt19937 gen(rd()); + std::uniform_real_distribution dis(-5.0f, 5.0f); + NNCASE_UNUSED auto res = kernels::stackvm::apply( + tensor.shape(), + [&](gsl::span index) -> result { + get(tensor, index) = static_cast(dis(gen)); + return ok(); + }); + break; + } + case dt_float32: { + std::random_device rd; + std::mt19937 gen(rd()); + std::uniform_real_distribution dis(-5.0f, 5.0f); + NNCASE_UNUSED auto res = kernels::stackvm::apply( + tensor.shape(), + [&](gsl::span index) -> result { + get(tensor, index) = static_cast(dis(gen)); + return ok(); + }); + break; + } + case dt_bfloat16: { + std::random_device rd; + std::mt19937 gen(rd()); + std::uniform_real_distribution<> dis(-5.0f, 5.0); + NNCASE_UNUSED auto res = kernels::stackvm::apply( + tensor.shape(), + [&](gsl::span index) -> result { + get(tensor, index) = + static_cast(dis(gen)); + return ok(); + }); + break; + } + default: { + } + } + } + protected: runtime_tensor input; runtime_tensor alpha; diff --git a/tests/kernels/test_celu.json b/tests/kernels/test_celu.json index c6ec765242..2333343d9c 100644 --- a/tests/kernels/test_celu.json +++ b/tests/kernels/test_celu.json @@ -1,4 +1,4 @@ { - "lhs_shape":[[1], [1, 2], [1, 3, 16, 16], [16, 16], [1, 16], [1, 3, 16, 1], []], + "lhs_shape":[[1], [1, 2], [1, 3, 16, 16], [16, 16], [1, 16], [1, 3, 16, 1], [1, 3, 16], []], "lhs_type":["dt_float32"] } \ No newline at end of file diff --git a/tests/kernels/test_clamp.json b/tests/kernels/test_clamp.json index 6c62ab02d6..0651a6fee4 100644 --- a/tests/kernels/test_clamp.json +++ b/tests/kernels/test_clamp.json @@ -1,6 +1,6 @@ { "lhs_shape":[[1, 3, 16, 16], [1], [1, 3], [8, 8], [1, 3, 8], [16, 16], [16], []], "lhs_type":["dt_float32"], - "min": [-1, -2, -3, -4, -5, -6], - "max": [0, 1, 2, 3, 4, 5, 6] + "min": [-1.0, -2.0, -3.0, -4.0, -5.0, -6.0], + "max": [0.0, 1.0, 2.0, 3.0, 4.0, 5.0, 6.0] } \ No newline at end of file From 1dce12c3828caeef3d903fdb00e28cfe4831d5a1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E4=B9=90=E4=BB=81=E5=8D=8E?= <31504341+lerenhua@users.noreply.github.com> Date: Tue, 29 Aug 2023 10:04:55 +0800 Subject: [PATCH 03/25] GNNE-1904 Fix instance norm error when batchsize != 1 (#1072) * Fix instance norm cos score error when batchsize != 1 --------- Co-authored-by: lerenhua --- src/Native/src/kernels/stackvm/reference/instance_norm.cpp | 4 +++- tests/kernels/test_instance_normalization.cpp | 5 +++-- 2 files changed, 6 insertions(+), 3 deletions(-) diff --git a/src/Native/src/kernels/stackvm/reference/instance_norm.cpp b/src/Native/src/kernels/stackvm/reference/instance_norm.cpp index 60fed78cbd..682bf49e45 100644 --- a/src/Native/src/kernels/stackvm/reference/instance_norm.cpp +++ b/src/Native/src/kernels/stackvm/reference/instance_norm.cpp @@ -35,10 +35,12 @@ result instance_norm_impl(const float *input, const float *scale, float epsilon) { return apply(in_shape, [&](gsl::span index) -> result { auto c = index[1]; + auto offi = index[0] * in_shape[1] + index[1]; auto off = offset(in_strides, index); const auto x = input[off]; output[offset(out_strides, index)] = - scale[c] * (x - input_mean[c]) / std::sqrt(input_var[c] + epsilon) + + scale[c] * (x - input_mean[offi]) / + std::sqrt(input_var[offi] + epsilon) + bias[c]; return ok(); }); diff --git a/tests/kernels/test_instance_normalization.cpp b/tests/kernels/test_instance_normalization.cpp index 14af095e7a..0f0d6efaaa 100644 --- a/tests/kernels/test_instance_normalization.cpp +++ b/tests/kernels/test_instance_normalization.cpp @@ -60,8 +60,9 @@ class InstanceNormalizationTest INSTANTIATE_TEST_SUITE_P( instance_normalization, InstanceNormalizationTest, testing::Combine(testing::Values(dt_float32), - testing::Values(dims_t{1, 3, 16, 16}, dims_t{1, 2, 4, 8}, - dims_t{1, 3, + testing::Values(dims_t{3, 3, 16, 16}, dims_t{64, 2, 4, 8}, + dims_t{1, 2, 4, 8}, + dims_t{24, 3, 16} /*, dims_t{24, 16, 16}*/))); // todo when in_shape[0] is not 1,cos is about 0.96 From 6544a5c13ca55e2dd2754727193356d706013a9e Mon Sep 17 00:00:00 2001 From: HeJunchao <73169088+HeJunchao100813@users.noreply.github.com> Date: Tue, 29 Aug 2023 13:26:12 +0800 Subject: [PATCH 04/25] fix test_shape_of (#1073) Co-authored-by: hejunchao --- tests/kernels/test_shape_of.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/kernels/test_shape_of.cpp b/tests/kernels/test_shape_of.cpp index fb509d5ac4..ce0290c2f7 100644 --- a/tests/kernels/test_shape_of.cpp +++ b/tests/kernels/test_shape_of.cpp @@ -36,7 +36,7 @@ class ShapeOfTest : public KernelTest, READY_SUBCASE() auto typecode = GetDataType("lhs_type"); - auto shape = GetShapeArray("i_shape"); + auto shape = GetShapeArray("input_shape"); lhs = hrt::create(typecode, shape, host_runtime_tensor::pool_cpu_only) .expect("create tensor failed"); From e5f39af68c0ec59e676001c708030e61d4e54f91 Mon Sep 17 00:00:00 2001 From: HeJunchao <73169088+HeJunchao100813@users.noreply.github.com> Date: Wed, 30 Aug 2023 09:53:07 +0800 Subject: [PATCH 05/25] Feature/json (#1074) * fix topK --------- Co-authored-by: hejunchao Co-authored-by: HeJunchao100813 --- tests/kernels/test_bucket_pad.cpp | 2 +- tests/kernels/test_celu.cpp | 2 +- tests/kernels/test_clamp.cpp | 2 +- tests/kernels/test_conv2d.cpp | 64 +++++++++----- tests/kernels/test_conv2d.json | 10 +++ tests/kernels/test_conv2d_transpose.cpp | 87 +++++++++++-------- tests/kernels/test_conv2d_transpose.json | 12 ++- tests/kernels/test_elu.cpp | 2 +- tests/kernels/test_erf.cpp | 2 +- tests/kernels/test_gather.cpp | 52 ++++++----- tests/kernels/test_gather.json | 5 ++ tests/kernels/test_gather_elements.cpp | 46 +++++----- tests/kernels/test_gather_elements.json | 5 ++ tests/kernels/test_gather_nd.cpp | 44 ++++++---- tests/kernels/test_gather_nd.json | 5 ++ tests/kernels/test_gelu.cpp | 2 +- tests/kernels/test_get_item.cpp | 36 ++++---- tests/kernels/test_get_item.json | 4 + tests/kernels/test_hard_sigmoid.cpp | 2 +- tests/kernels/test_hard_swish.cpp | 2 +- tests/kernels/test_hardmax.cpp | 2 +- tests/kernels/test_instance_normalization.cpp | 30 ++++--- .../kernels/test_instance_normalization.json | 4 + tests/kernels/test_leaky_relu.cpp | 2 +- tests/kernels/test_prelu.cpp | 2 +- tests/kernels/test_relu.cpp | 2 +- tests/kernels/test_selu.cpp | 2 +- tests/kernels/test_sigmoid.cpp | 2 +- tests/kernels/test_size_of.cpp | 2 +- tests/kernels/test_slice.cpp | 2 +- tests/kernels/test_softplus.cpp | 2 +- tests/kernels/test_softsign.cpp | 2 +- tests/kernels/test_space_to_batch.cpp | 2 +- tests/kernels/test_swish.cpp | 2 +- tests/kernels/test_topK.cpp | 12 +-- tests/kernels/test_topk.json | 4 +- 36 files changed, 284 insertions(+), 176 deletions(-) create mode 100644 tests/kernels/test_conv2d.json create mode 100644 tests/kernels/test_gather.json create mode 100644 tests/kernels/test_gather_elements.json create mode 100644 tests/kernels/test_gather_nd.json create mode 100644 tests/kernels/test_get_item.json create mode 100644 tests/kernels/test_instance_normalization.json diff --git a/tests/kernels/test_bucket_pad.cpp b/tests/kernels/test_bucket_pad.cpp index 2f9f2a38de..593464918d 100644 --- a/tests/kernels/test_bucket_pad.cpp +++ b/tests/kernels/test_bucket_pad.cpp @@ -50,7 +50,7 @@ class BucketPadTest : public KernelTest, .expect("create tensor failed"); } - void TearDown() override {} + void TearDown() override { CLEAR_SUBCASE() } protected: runtime_tensor input; diff --git a/tests/kernels/test_celu.cpp b/tests/kernels/test_celu.cpp index 63f8c2ac5c..45a0cb72df 100644 --- a/tests/kernels/test_celu.cpp +++ b/tests/kernels/test_celu.cpp @@ -47,7 +47,7 @@ class CeluTest : public KernelTest, init_tensor_alpha(alpha); } - void TearDown() override {} + void TearDown() override { CLEAR_SUBCASE() } virtual void init_tensor_alpha(runtime::runtime_tensor &tensor) { auto dtype = tensor.datatype(); diff --git a/tests/kernels/test_clamp.cpp b/tests/kernels/test_clamp.cpp index 94807ce2f5..7e6cd78b04 100644 --- a/tests/kernels/test_clamp.cpp +++ b/tests/kernels/test_clamp.cpp @@ -49,7 +49,7 @@ class ClampTest : public KernelTest, max_value = value2; } - void TearDown() override {} + void TearDown() override { CLEAR_SUBCASE() } protected: runtime_tensor input; diff --git a/tests/kernels/test_conv2d.cpp b/tests/kernels/test_conv2d.cpp index 3d4cf62f78..e20ac27a4f 100644 --- a/tests/kernels/test_conv2d.cpp +++ b/tests/kernels/test_conv2d.cpp @@ -22,18 +22,26 @@ #include #include +#define TEST_CASE_NAME "test_conv2d" + using namespace nncase; using namespace nncase::runtime; using namespace ortki; class Conv2DTest : public KernelTest, - public ::testing::TestWithParam< - std::tuple> { + public ::testing::TestWithParam> { public: void SetUp() override { - auto &&[typecode, input_shape, weight_shape, bias_shape, value1, value2, - value3, value4] = GetParam(); + READY_SUBCASE() + + auto typecode = GetDataType("lhs_type"); + auto input_shape = GetShapeArray("lhs_shape"); + auto weight_shape = GetShapeArray("weight_shape"); + auto bias_shape = GetShapeArray("bias_shape"); + dilations_value = GetShapeArray("dilations_value"); + pad_value = GetShapeArray("pad_value"); + strides_value = GetShapeArray("strides_value"); + group_value = GetNumber("group_value"); input = hrt::create(typecode, input_shape, host_runtime_tensor::pool_cpu_only) @@ -49,14 +57,9 @@ class Conv2DTest : public KernelTest, host_runtime_tensor::pool_cpu_only) .expect("create tensor failed"); init_tensor(bais); - - dilations_value = value1; - pad_value = value2; - strides_value = value3; - group_value = value4; } - void TearDown() override {} + void TearDown() override { CLEAR_SUBCASE() } protected: runtime_tensor input; @@ -68,16 +71,8 @@ class Conv2DTest : public KernelTest, int64_t group_value; }; -INSTANTIATE_TEST_SUITE_P( - conv2d, Conv2DTest, - testing::Combine( - testing::Values(dt_float32), - testing::Values(dims_t{1, 4, 5, 5}, dims_t{1, 4, 16, 16}), - testing::Values(dims_t{8, 4, 3, 3}, dims_t{8, 4, 1, 1}), - testing::Values(dims_t{8}), testing::Values(dims_t{2, 2}, dims_t{1, 1}), - testing::Values(dims_t{1, 1, 1, 1} /*, dims_t{0, 0, 1, 0}*/), - testing::Values(dims_t{1, 1}, dims_t{2, 2}), - testing::Values(1 /*, 2*/))); // todo result error +INSTANTIATE_TEST_SUITE_P(conv2d, Conv2DTest, + testing::Combine(testing::Range(0, MAX_CASE_NUM))); TEST_P(Conv2DTest, conv2d) { auto input_ort = runtime_tensor_2_ort_tensor(input); @@ -181,6 +176,33 @@ TEST_P(Conv2DTest, conv2d) { } int main(int argc, char *argv[]) { + READY_TEST_CASE_GENERATE() + FOR_LOOP(lhs_type, i) + FOR_LOOP(lhs_shape, j) + FOR_LOOP(weight_shape, k) + FOR_LOOP(bias_shape, l) + FOR_LOOP(dilations_value, m) + FOR_LOOP(pad_value, n) + FOR_LOOP(strides_value, o) + FOR_LOOP(group_value, p) + SPLIT_ELEMENT(lhs_type, i) + SPLIT_ELEMENT(lhs_shape, j) + SPLIT_ELEMENT(weight_shape, k) + SPLIT_ELEMENT(bias_shape, l) + SPLIT_ELEMENT(dilations_value, m) + SPLIT_ELEMENT(pad_value, n) + SPLIT_ELEMENT(strides_value, o) + SPLIT_ELEMENT(group_value, p) + WRITE_SUB_CASE() + FOR_LOOP_END() + FOR_LOOP_END() + FOR_LOOP_END() + FOR_LOOP_END() + FOR_LOOP_END() + FOR_LOOP_END() + FOR_LOOP_END() + FOR_LOOP_END() + ::testing::InitGoogleTest(&argc, argv); return RUN_ALL_TESTS(); } \ No newline at end of file diff --git a/tests/kernels/test_conv2d.json b/tests/kernels/test_conv2d.json new file mode 100644 index 0000000000..ccba39b078 --- /dev/null +++ b/tests/kernels/test_conv2d.json @@ -0,0 +1,10 @@ +{ + "lhs_type":["dt_float32"], + "lhs_shape":[[1, 4, 5, 5], [1, 4, 16, 16]], + "weight_shape":[[8, 4, 3, 3], [8, 4, 1, 1]], + "bias_shape":[[8]], + "dilations_value":[[2, 2], [1, 1]], + "pad_value":[[1, 1, 1, 1]], + "strides_value":[[1, 1], [2, 2]], + "group_value":[1] +} \ No newline at end of file diff --git a/tests/kernels/test_conv2d_transpose.cpp b/tests/kernels/test_conv2d_transpose.cpp index 96e60a1d86..24331e757c 100644 --- a/tests/kernels/test_conv2d_transpose.cpp +++ b/tests/kernels/test_conv2d_transpose.cpp @@ -22,19 +22,28 @@ #include #include +#define TEST_CASE_NAME "test_conv2d_transpose" + using namespace nncase; using namespace nncase::runtime; using namespace ortki; -class Conv2DTransposeTest - : public KernelTest, - public ::testing::TestWithParam< - std::tuple> { +class Conv2DTransposeTest : public KernelTest, + public ::testing::TestWithParam> { public: void SetUp() override { - auto &&[typecode, input_shape, weight_shape, bias_shape, value1, value2, - value3, value4, value5, value6] = GetParam(); + READY_SUBCASE() + + auto typecode = GetDataType("lhs_type"); + auto input_shape = GetShapeArray("lhs_shape"); + auto weight_shape = GetShapeArray("weight_shape"); + auto bias_shape = GetShapeArray("bias_shape"); + dilations_value = GetShapeArray("dilations_value"); + pad_value = GetShapeArray("pad_value"); + strides_value = GetShapeArray("strides_value"); + group_value = GetNumber("group_value"); + output_padding_value = GetShapeArray("output_padding_value"); + output_shape_value = GetShapeArray("output_shape_value"); input = hrt::create(typecode, input_shape, host_runtime_tensor::pool_cpu_only) @@ -50,16 +59,9 @@ class Conv2DTransposeTest host_runtime_tensor::pool_cpu_only) .expect("create tensor failed"); init_tensor(bais); - - dilations_value = value1; - pad_value = value2; - strides_value = value3; - group_value = value4; - output_padding_value = value5; - output_shape_value = value6; } - void TearDown() override {} + void TearDown() override { CLEAR_SUBCASE() } protected: runtime_tensor input; @@ -73,16 +75,8 @@ class Conv2DTransposeTest int64_t group_value; }; -INSTANTIATE_TEST_SUITE_P( - conv2d_transpose, Conv2DTransposeTest, - testing::Combine( - testing::Values(dt_float32), testing::Values(dims_t{1, 1, 5, 5}), - testing::Values(dims_t{1, 2, 3, 3}), testing::Values(dims_t{2}), - testing::Values(/*dims_t{2, 2} ,*/ dims_t{1, 1}), - testing::Values(dims_t{1, 1, 1, 1} /*, dims_t{0, 0, 1, 0}*/), - testing::Values(dims_t{1, 1} /*, dims_t{2, 2}*/), - testing::Values(1 /*, 2*/), testing::Values(dims_t{0, 0}), - testing::Values(dims_t{1, 2, 5, 5}))); +INSTANTIATE_TEST_SUITE_P(conv2d_transpose, Conv2DTransposeTest, + testing::Combine(testing::Range(0, MAX_CASE_NUM))); TEST_P(Conv2DTransposeTest, conv2d_transpose) { auto input_ort = runtime_tensor_2_ort_tensor(input); @@ -210,17 +204,38 @@ TEST_P(Conv2DTransposeTest, conv2d_transpose) { } int main(int argc, char *argv[]) { - // READY_TEST_CASE_GENERATE() - // FOR_LOOP(lhs_shape, i) - // FOR_LOOP(lhs_type, j) - // FOR_LOOP(rhs_type, k) - // SPLIT_ELEMENT(lhs_shape, i) - // SPLIT_ELEMENT(lhs_type, j) - // SPLIT_ELEMENT(rhs_type, k) - // WRITE_SUB_CASE() - // FOR_LOOP_END() - // FOR_LOOP_END() - // FOR_LOOP_END() + READY_TEST_CASE_GENERATE() + FOR_LOOP(lhs_type, i) + FOR_LOOP(lhs_shape, j) + FOR_LOOP(weight_shape, k) + FOR_LOOP(bias_shape, l) + FOR_LOOP(dilations_value, m) + FOR_LOOP(pad_value, n) + FOR_LOOP(strides_value, o) + FOR_LOOP(group_value, p) + FOR_LOOP(output_padding_value, r) + FOR_LOOP(output_shape_value, s) + SPLIT_ELEMENT(lhs_type, i) + SPLIT_ELEMENT(lhs_shape, j) + SPLIT_ELEMENT(weight_shape, k) + SPLIT_ELEMENT(bias_shape, l) + SPLIT_ELEMENT(dilations_value, m) + SPLIT_ELEMENT(pad_value, n) + SPLIT_ELEMENT(strides_value, o) + SPLIT_ELEMENT(group_value, p) + SPLIT_ELEMENT(output_padding_value, r) + SPLIT_ELEMENT(output_shape_value, s) + WRITE_SUB_CASE() + FOR_LOOP_END() + FOR_LOOP_END() + FOR_LOOP_END() + FOR_LOOP_END() + FOR_LOOP_END() + FOR_LOOP_END() + FOR_LOOP_END() + FOR_LOOP_END() + FOR_LOOP_END() + FOR_LOOP_END() ::testing::InitGoogleTest(&argc, argv); return RUN_ALL_TESTS(); diff --git a/tests/kernels/test_conv2d_transpose.json b/tests/kernels/test_conv2d_transpose.json index 8ddf991217..89b32ebb48 100644 --- a/tests/kernels/test_conv2d_transpose.json +++ b/tests/kernels/test_conv2d_transpose.json @@ -1,4 +1,12 @@ { - "lhs_shape":[[1, 8, 24, 24], [1, 3, 3, 16], [2, 4, 8, 8], [8, 8], [1, 3, 16, 1], [1, 1], [16]], - "lhs_type":["dt_int32"] + "lhs_type":["dt_float32"], + "lhs_shape":[[1, 1, 5, 5]], + "weight_shape":[[1, 2, 3, 3]], + "bias_shape":[[2]], + "dilations_value":[[1, 1]], + "pad_value":[[1, 1, 1, 1]], + "strides_value":[[1, 1]], + "group_value":[1], + "output_padding_value":[[0, 0]], + "output_shape_value":[[1, 2, 5, 5]] } \ No newline at end of file diff --git a/tests/kernels/test_elu.cpp b/tests/kernels/test_elu.cpp index b7d51de804..0e3002509b 100644 --- a/tests/kernels/test_elu.cpp +++ b/tests/kernels/test_elu.cpp @@ -47,7 +47,7 @@ class EluTest : public KernelTest, init_tensor(alpha); } - void TearDown() override {} + void TearDown() override { CLEAR_SUBCASE() } protected: runtime_tensor input; diff --git a/tests/kernels/test_erf.cpp b/tests/kernels/test_erf.cpp index 2bf6f994e6..504f87cc87 100644 --- a/tests/kernels/test_erf.cpp +++ b/tests/kernels/test_erf.cpp @@ -43,7 +43,7 @@ class ErfTest : public KernelTest, init_tensor(input); } - void TearDown() override {} + void TearDown() override { CLEAR_SUBCASE() } protected: runtime_tensor input; diff --git a/tests/kernels/test_gather.cpp b/tests/kernels/test_gather.cpp index 09632db6d2..15a3dbc797 100644 --- a/tests/kernels/test_gather.cpp +++ b/tests/kernels/test_gather.cpp @@ -22,30 +22,39 @@ #include #include +#define TEST_CASE_NAME "test_gather" + using namespace nncase; using namespace nncase::runtime; using namespace ortki; class GatherTest : public KernelTest, - public ::testing::TestWithParam< - std::tuple> { + public ::testing::TestWithParam> { public: void SetUp() override { - auto &&[typecode, shape, value] = GetParam(); + READY_SUBCASE() + + auto shape = GetShapeArray("lhs_shape"); + auto value = GetNumber("axis"); + auto typecode = GetDataType("lhs_type"); input = hrt::create(typecode, shape, host_runtime_tensor::pool_cpu_only) .expect("create tensor failed"); init_tensor(input); - int64_t indices_array[] = {0, 0, 1, 1}; - indices = hrt::create(dt_int64, {2, 2}, + int64_t indices_array[] = {0, 0, -1, -1}; + indices = hrt::create(dt_int64, {4}, {reinterpret_cast(indices_array), sizeof(indices_array)}, true, host_runtime_tensor::pool_cpu_only) .expect("create tensor failed"); - batchDims_value = value; - int64_t batchDims_array[1] = {value}; + batchDims_value = value >= 0 + ? (size_t)value >= shape.size() ? -1 : value + : -(size_t)value > shape.size() ? -1 + : value; + + int64_t batchDims_array[1] = {batchDims_value}; batchDims = hrt::create(dt_int64, dims_t{1}, {reinterpret_cast(batchDims_array), sizeof(batchDims_array)}, @@ -53,7 +62,7 @@ class GatherTest : public KernelTest, .expect("create tensor failed"); } - void TearDown() override {} + void TearDown() override { CLEAR_SUBCASE() } protected: runtime_tensor input; @@ -62,19 +71,8 @@ class GatherTest : public KernelTest, int64_t batchDims_value; }; -INSTANTIATE_TEST_SUITE_P( - gather, GatherTest, - testing::Combine(testing::Values(dt_int32, dt_int64, dt_float32, dt_uint64, - dt_int8, dt_int16, dt_uint8, dt_uint16, - dt_uint32, dt_float16, dt_float64, - dt_bfloat16, dt_boolean), - testing::Values(dims_t{ - 2, - 2} /*, dims_t{3, 5}, - dims_t{2, 3, 1}, dims_t{5, 7, 5}, - dims_t{5, 4, 3, 2}, dims_t{5, 5, 7, 7}, - dims_t{2, 3, 3, 5}*/), - testing::Values(-1, 0, 1))); +INSTANTIATE_TEST_SUITE_P(gather, GatherTest, + testing::Combine(testing::Range(0, MAX_CASE_NUM))); TEST_P(GatherTest, gather) { auto input_ort = runtime_tensor_2_ort_tensor(input); @@ -112,6 +110,18 @@ TEST_P(GatherTest, gather) { } int main(int argc, char *argv[]) { + READY_TEST_CASE_GENERATE() + FOR_LOOP(lhs_shape, i) + FOR_LOOP(axis, j) + FOR_LOOP(lhs_type, k) + SPLIT_ELEMENT(lhs_shape, i) + SPLIT_ELEMENT(axis, j) + SPLIT_ELEMENT(lhs_type, k) + WRITE_SUB_CASE() + FOR_LOOP_END() + FOR_LOOP_END() + FOR_LOOP_END() + ::testing::InitGoogleTest(&argc, argv); return RUN_ALL_TESTS(); } \ No newline at end of file diff --git a/tests/kernels/test_gather.json b/tests/kernels/test_gather.json new file mode 100644 index 0000000000..b39845f716 --- /dev/null +++ b/tests/kernels/test_gather.json @@ -0,0 +1,5 @@ +{ + "lhs_shape":[[2, 3, 5, 7], [2, 2], [2, 3, 1], [5, 5, 7, 7], [11]], + "axis":[0, 1, -1, 2, 3, -2, -3, -4], + "lhs_type":["dt_float32", "dt_int8", "dt_int32", "dt_uint8", "dt_int16", "dt_uint16", "dt_uint32", "dt_uint64", "dt_int64", "dt_float16", "dt_float64", "dt_bfloat16", "dt_boolean"] +} \ No newline at end of file diff --git a/tests/kernels/test_gather_elements.cpp b/tests/kernels/test_gather_elements.cpp index 1a17edaecf..9535851933 100644 --- a/tests/kernels/test_gather_elements.cpp +++ b/tests/kernels/test_gather_elements.cpp @@ -22,17 +22,21 @@ #include #include +#define TEST_CASE_NAME "test_gather_elements" + using namespace nncase; using namespace nncase::runtime; using namespace ortki; -class GatherElementsTest - : public KernelTest, - public ::testing::TestWithParam< - std::tuple> { +class GatherElementsTest : public KernelTest, + public ::testing::TestWithParam> { public: void SetUp() override { - auto &&[typecode, shape, value] = GetParam(); + READY_SUBCASE() + + auto shape = GetShapeArray("lhs_shape"); + auto value = GetNumber("axis"); + auto typecode = GetDataType("lhs_type"); input = hrt::create(typecode, shape, host_runtime_tensor::pool_cpu_only) .expect("create tensor failed"); @@ -46,7 +50,8 @@ class GatherElementsTest .expect("create tensor failed"); batchDims_value = value; - int64_t batchDims_array[1] = {value}; + + int64_t batchDims_array[1] = {batchDims_value}; batchDims = hrt::create(dt_int64, dims_t{1}, {reinterpret_cast(batchDims_array), sizeof(batchDims_array)}, @@ -54,7 +59,7 @@ class GatherElementsTest .expect("create tensor failed"); } - void TearDown() override {} + void TearDown() override { CLEAR_SUBCASE() } protected: runtime_tensor input; @@ -63,19 +68,8 @@ class GatherElementsTest int64_t batchDims_value; }; -INSTANTIATE_TEST_SUITE_P( - gather_elements, GatherElementsTest, - testing::Combine(testing::Values(dt_int32, dt_int64, dt_float32, dt_uint64, - dt_int8, dt_int16, dt_uint8, dt_uint16, - dt_uint32, dt_float16, dt_float64, - dt_bfloat16, dt_boolean), - testing::Values(dims_t{ - 2, - 2} /*, dims_t{3, 5}, - dims_t{2, 3, 1}, dims_t{5, 7, 5}, - dims_t{5, 4, 3, 2}, dims_t{5, 5, 7, 7}, - dims_t{2, 3, 3, 5}*/), - testing::Values(-1, 0, 1))); +INSTANTIATE_TEST_SUITE_P(gather_elements, GatherElementsTest, + testing::Combine(testing::Range(0, MAX_CASE_NUM))); TEST_P(GatherElementsTest, gather_elements) { auto input_ort = runtime_tensor_2_ort_tensor(input); @@ -114,6 +108,18 @@ TEST_P(GatherElementsTest, gather_elements) { } int main(int argc, char *argv[]) { + READY_TEST_CASE_GENERATE() + FOR_LOOP(lhs_shape, i) + FOR_LOOP(axis, j) + FOR_LOOP(lhs_type, k) + SPLIT_ELEMENT(lhs_shape, i) + SPLIT_ELEMENT(axis, j) + SPLIT_ELEMENT(lhs_type, k) + WRITE_SUB_CASE() + FOR_LOOP_END() + FOR_LOOP_END() + FOR_LOOP_END() + ::testing::InitGoogleTest(&argc, argv); return RUN_ALL_TESTS(); } \ No newline at end of file diff --git a/tests/kernels/test_gather_elements.json b/tests/kernels/test_gather_elements.json new file mode 100644 index 0000000000..b12b58e166 --- /dev/null +++ b/tests/kernels/test_gather_elements.json @@ -0,0 +1,5 @@ +{ + "lhs_shape":[[2, 2]], + "axis":[0], + "lhs_type":["dt_float32", "dt_int8", "dt_int32", "dt_uint8", "dt_int16", "dt_uint16", "dt_uint32", "dt_uint64", "dt_int64", "dt_float16", "dt_float64", "dt_bfloat16", "dt_boolean"] +} \ No newline at end of file diff --git a/tests/kernels/test_gather_nd.cpp b/tests/kernels/test_gather_nd.cpp index fb4687f5f7..8e95c443d7 100644 --- a/tests/kernels/test_gather_nd.cpp +++ b/tests/kernels/test_gather_nd.cpp @@ -22,30 +22,36 @@ #include #include +#define TEST_CASE_NAME "test_gather_nd" + using namespace nncase; using namespace nncase::runtime; using namespace ortki; class GatherNDTest : public KernelTest, - public ::testing::TestWithParam< - std::tuple> { + public ::testing::TestWithParam> { public: void SetUp() override { - auto &&[typecode, shape, value] = GetParam(); + READY_SUBCASE() + + auto shape = GetShapeArray("lhs_shape"); + auto value = GetNumber("axis"); + auto typecode = GetDataType("lhs_type"); input = hrt::create(typecode, shape, host_runtime_tensor::pool_cpu_only) .expect("create tensor failed"); init_tensor(input); - int64_t indices_array[] = {0, 0, 1, 1}; - indices = hrt::create(dt_int64, shape, + int64_t indices_array[] = {0, 0, 0, 0}; + indices = hrt::create(dt_int64, {2, 2}, {reinterpret_cast(indices_array), sizeof(indices_array)}, true, host_runtime_tensor::pool_cpu_only) .expect("create tensor failed"); batchDims_value = value; - int64_t batchDims_array[1] = {value}; + + int64_t batchDims_array[1] = {batchDims_value}; batchDims = hrt::create(dt_int64, dims_t{1}, {reinterpret_cast(batchDims_array), sizeof(batchDims_array)}, @@ -53,7 +59,7 @@ class GatherNDTest : public KernelTest, .expect("create tensor failed"); } - void TearDown() override {} + void TearDown() override { CLEAR_SUBCASE() } protected: runtime_tensor input; @@ -62,16 +68,8 @@ class GatherNDTest : public KernelTest, int64_t batchDims_value; }; -INSTANTIATE_TEST_SUITE_P( - gather_nd, GatherNDTest, - testing::Combine(testing::Values(dt_int32, dt_int64, dt_float32, dt_uint64, - dt_int8, dt_int16, dt_uint8, dt_uint16, - dt_uint32, dt_float16, dt_float64, - dt_bfloat16, dt_boolean), - testing::Values(dims_t{2, 2} /*, dims_t{3, 5}, - dims_t{2, 3, 1}, dims_t{5, 7, 5}, - dims_t{5, 4, 3, 2}, dims_t{5, 5, 7, 7}, - dims_t{2, 3, 3, 5}*/), testing::Values(0 /*, -1, 1*/))); +INSTANTIATE_TEST_SUITE_P(gather_nd, GatherNDTest, + testing::Combine(testing::Range(0, MAX_CASE_NUM))); TEST_P(GatherNDTest, gather_nd) { auto input_ort = runtime_tensor_2_ort_tensor(input); @@ -109,6 +107,18 @@ TEST_P(GatherNDTest, gather_nd) { } int main(int argc, char *argv[]) { + READY_TEST_CASE_GENERATE() + FOR_LOOP(lhs_shape, i) + FOR_LOOP(axis, j) + FOR_LOOP(lhs_type, k) + SPLIT_ELEMENT(lhs_shape, i) + SPLIT_ELEMENT(axis, j) + SPLIT_ELEMENT(lhs_type, k) + WRITE_SUB_CASE() + FOR_LOOP_END() + FOR_LOOP_END() + FOR_LOOP_END() + ::testing::InitGoogleTest(&argc, argv); return RUN_ALL_TESTS(); } \ No newline at end of file diff --git a/tests/kernels/test_gather_nd.json b/tests/kernels/test_gather_nd.json new file mode 100644 index 0000000000..64c54990be --- /dev/null +++ b/tests/kernels/test_gather_nd.json @@ -0,0 +1,5 @@ +{ + "lhs_shape":[[3, 5], [2, 2], [2, 3, 1], [5, 5, 7, 7]], + "axis":[0], + "lhs_type":["dt_float32", "dt_int8", "dt_int32", "dt_uint8", "dt_int16", "dt_uint16", "dt_uint32", "dt_uint64", "dt_int64", "dt_float16", "dt_float64", "dt_bfloat16", "dt_boolean"] +} \ No newline at end of file diff --git a/tests/kernels/test_gelu.cpp b/tests/kernels/test_gelu.cpp index a3e0ee0594..04ee0f9216 100644 --- a/tests/kernels/test_gelu.cpp +++ b/tests/kernels/test_gelu.cpp @@ -47,7 +47,7 @@ class GeluTest : public KernelTest, init_tensor_alpha(alpha); } - void TearDown() override {} + void TearDown() override { CLEAR_SUBCASE() } virtual void init_tensor_alpha(runtime::runtime_tensor &tensor) { auto dtype = tensor.datatype(); diff --git a/tests/kernels/test_get_item.cpp b/tests/kernels/test_get_item.cpp index 6ad5403cf8..009044becb 100644 --- a/tests/kernels/test_get_item.cpp +++ b/tests/kernels/test_get_item.cpp @@ -22,16 +22,20 @@ #include #include +#define TEST_CASE_NAME "test_get_item" + using namespace nncase; using namespace nncase::runtime; using namespace ortki; -class GetItemTest - : public KernelTest, - public ::testing::TestWithParam> { +class GetItemTest : public KernelTest, + public ::testing::TestWithParam> { public: void SetUp() override { - auto &&[typecode, l_shape] = GetParam(); + READY_SUBCASE() + + auto l_shape = GetShapeArray("lhs_shape"); + auto typecode = GetDataType("lhs_type"); input = hrt::create(typecode, l_shape, host_runtime_tensor::pool_cpu_only) @@ -39,15 +43,14 @@ class GetItemTest init_tensor(input); } - void TearDown() override {} + void TearDown() override { CLEAR_SUBCASE() } protected: runtime_tensor input; }; INSTANTIATE_TEST_SUITE_P(get_item, GetItemTest, - testing::Combine(testing::Values(dt_float32), - testing::Values(dims_t{1}))); + testing::Combine(testing::Range(0, MAX_CASE_NUM))); TEST_P(GetItemTest, get_item) { @@ -62,19 +65,11 @@ TEST_P(GetItemTest, get_item) { true, host_runtime_tensor::pool_cpu_only) .expect("create tensor failed"); - int64_t shape_ort[] = {1}; - auto shape = hrt::create(dt_int64, {1}, - {reinterpret_cast(shape_ort), - sizeof(shape_ort)}, - true, host_runtime_tensor::pool_cpu_only) - .expect("create tensor failed"); - auto get_item_output = kernels::stackvm::get_item(input.impl(), index.impl()) .expect("get_item failed"); - auto output = kernels::stackvm::reshape(get_item_output, shape.impl()) - .expect("get_item failed"); + auto output = get_item_output; runtime_tensor actual(output.as().expect("as tensor failed")); bool result = is_same_tensor(expected, actual) || @@ -92,6 +87,15 @@ TEST_P(GetItemTest, get_item) { } int main(int argc, char *argv[]) { + READY_TEST_CASE_GENERATE() + FOR_LOOP(lhs_shape, j) + FOR_LOOP(lhs_type, i) + SPLIT_ELEMENT(lhs_shape, j) + SPLIT_ELEMENT(lhs_type, i) + WRITE_SUB_CASE() + FOR_LOOP_END() + FOR_LOOP_END() + ::testing::InitGoogleTest(&argc, argv); return RUN_ALL_TESTS(); } \ No newline at end of file diff --git a/tests/kernels/test_get_item.json b/tests/kernels/test_get_item.json new file mode 100644 index 0000000000..b981385e1c --- /dev/null +++ b/tests/kernels/test_get_item.json @@ -0,0 +1,4 @@ +{ + "lhs_shape":[[1]], + "lhs_type":["dt_float32"] +} \ No newline at end of file diff --git a/tests/kernels/test_hard_sigmoid.cpp b/tests/kernels/test_hard_sigmoid.cpp index 1b96601fff..29827f1a05 100644 --- a/tests/kernels/test_hard_sigmoid.cpp +++ b/tests/kernels/test_hard_sigmoid.cpp @@ -48,7 +48,7 @@ class HardSigmoidTest : public KernelTest, gamma_value = value2; } - void TearDown() override {} + void TearDown() override { CLEAR_SUBCASE() } protected: runtime_tensor input; diff --git a/tests/kernels/test_hard_swish.cpp b/tests/kernels/test_hard_swish.cpp index 23c591bc4e..f629c16ad0 100644 --- a/tests/kernels/test_hard_swish.cpp +++ b/tests/kernels/test_hard_swish.cpp @@ -42,7 +42,7 @@ class HardSwishTest : public KernelTest, .expect("create tensor failed"); } - void TearDown() override {} + void TearDown() override { CLEAR_SUBCASE() } protected: runtime_tensor input; diff --git a/tests/kernels/test_hardmax.cpp b/tests/kernels/test_hardmax.cpp index b8190f8499..5df077694b 100644 --- a/tests/kernels/test_hardmax.cpp +++ b/tests/kernels/test_hardmax.cpp @@ -48,7 +48,7 @@ class HardmaxTest : public KernelTest, : 0; } - void TearDown() override {} + void TearDown() override { CLEAR_SUBCASE() } protected: runtime_tensor input; diff --git a/tests/kernels/test_instance_normalization.cpp b/tests/kernels/test_instance_normalization.cpp index 0f0d6efaaa..d4fb672f8a 100644 --- a/tests/kernels/test_instance_normalization.cpp +++ b/tests/kernels/test_instance_normalization.cpp @@ -22,16 +22,21 @@ #include #include +#define TEST_CASE_NAME "test_instance_normalization" + using namespace nncase; using namespace nncase::runtime; using namespace ortki; class InstanceNormalizationTest : public KernelTest, - public ::testing::TestWithParam> { + public ::testing::TestWithParam> { public: void SetUp() override { - auto &&[typecode, l_shape] = GetParam(); + READY_SUBCASE() + + auto l_shape = GetShapeArray("lhs_shape"); + auto typecode = GetDataType("lhs_type"); input = hrt::create(typecode, l_shape, host_runtime_tensor::pool_cpu_only) @@ -49,7 +54,7 @@ class InstanceNormalizationTest init_tensor(b); } - void TearDown() override {} + void TearDown() override { CLEAR_SUBCASE() } protected: runtime_tensor input; @@ -57,14 +62,8 @@ class InstanceNormalizationTest runtime_tensor b; }; -INSTANTIATE_TEST_SUITE_P( - instance_normalization, InstanceNormalizationTest, - testing::Combine(testing::Values(dt_float32), - testing::Values(dims_t{3, 3, 16, 16}, dims_t{64, 2, 4, 8}, - dims_t{1, 2, 4, 8}, - dims_t{24, 3, - 16} /*, dims_t{24, 16, 16}*/))); -// todo when in_shape[0] is not 1,cos is about 0.96 +INSTANTIATE_TEST_SUITE_P(instance_normalization, InstanceNormalizationTest, + testing::Combine(testing::Range(0, MAX_CASE_NUM))); TEST_P(InstanceNormalizationTest, instance_normalization) { auto l_ort = runtime_tensor_2_ort_tensor(input); @@ -110,6 +109,15 @@ TEST_P(InstanceNormalizationTest, instance_normalization) { } int main(int argc, char *argv[]) { + READY_TEST_CASE_GENERATE() + FOR_LOOP(lhs_shape, i) + FOR_LOOP(lhs_type, j) + SPLIT_ELEMENT(lhs_shape, i) + SPLIT_ELEMENT(lhs_type, j) + WRITE_SUB_CASE() + FOR_LOOP_END() + FOR_LOOP_END() + ::testing::InitGoogleTest(&argc, argv); return RUN_ALL_TESTS(); } \ No newline at end of file diff --git a/tests/kernels/test_instance_normalization.json b/tests/kernels/test_instance_normalization.json new file mode 100644 index 0000000000..e8478a0f2d --- /dev/null +++ b/tests/kernels/test_instance_normalization.json @@ -0,0 +1,4 @@ +{ + "lhs_shape":[[3, 3, 16, 16], [64, 2, 4, 8], [1, 2, 4, 8], [24, 16, 16], [24, 3, 16]], + "lhs_type":["dt_float32"], +} \ No newline at end of file diff --git a/tests/kernels/test_leaky_relu.cpp b/tests/kernels/test_leaky_relu.cpp index 035263d2a5..cb2a8c23e7 100644 --- a/tests/kernels/test_leaky_relu.cpp +++ b/tests/kernels/test_leaky_relu.cpp @@ -47,7 +47,7 @@ class LeakyReluTest : public KernelTest, init_tensor(alpha); } - void TearDown() override {} + void TearDown() override { CLEAR_SUBCASE() } protected: runtime_tensor input; diff --git a/tests/kernels/test_prelu.cpp b/tests/kernels/test_prelu.cpp index b5d1df3ef4..3c75e59533 100644 --- a/tests/kernels/test_prelu.cpp +++ b/tests/kernels/test_prelu.cpp @@ -52,7 +52,7 @@ class PreluTest : public KernelTest, } } - void TearDown() override {} + void TearDown() override{CLEAR_SUBCASE()} slope_t GetSlopeArray(const char *key) { assert(_document[key].IsArray()); diff --git a/tests/kernels/test_relu.cpp b/tests/kernels/test_relu.cpp index 90e8c2bfc1..d2c7d2906d 100644 --- a/tests/kernels/test_relu.cpp +++ b/tests/kernels/test_relu.cpp @@ -43,7 +43,7 @@ class ReluTest : public KernelTest, init_tensor(input); } - void TearDown() override {} + void TearDown() override { CLEAR_SUBCASE() } protected: runtime_tensor input; diff --git a/tests/kernels/test_selu.cpp b/tests/kernels/test_selu.cpp index 76abef35d6..fe8ba873e5 100644 --- a/tests/kernels/test_selu.cpp +++ b/tests/kernels/test_selu.cpp @@ -48,7 +48,7 @@ class SeluTest : public KernelTest, gamma_value = value2; } - void TearDown() override {} + void TearDown() override { CLEAR_SUBCASE() } protected: runtime_tensor input; diff --git a/tests/kernels/test_sigmoid.cpp b/tests/kernels/test_sigmoid.cpp index c9d5b1180d..a6b2399465 100644 --- a/tests/kernels/test_sigmoid.cpp +++ b/tests/kernels/test_sigmoid.cpp @@ -43,7 +43,7 @@ class SigmoidTest : public KernelTest, init_tensor(input); } - void TearDown() override {} + void TearDown() override { CLEAR_SUBCASE() } protected: runtime_tensor input; diff --git a/tests/kernels/test_size_of.cpp b/tests/kernels/test_size_of.cpp index 3f81183f63..2c27ce0df0 100644 --- a/tests/kernels/test_size_of.cpp +++ b/tests/kernels/test_size_of.cpp @@ -44,7 +44,7 @@ class SizeOfTest : public KernelTest, init_tensor(input); } - void TearDown() override {} + void TearDown() override { CLEAR_SUBCASE() } protected: runtime_tensor input; diff --git a/tests/kernels/test_slice.cpp b/tests/kernels/test_slice.cpp index 62723b84ad..c97a1e27b0 100644 --- a/tests/kernels/test_slice.cpp +++ b/tests/kernels/test_slice.cpp @@ -91,7 +91,7 @@ class SliceTest : public KernelTest, .expect("create4 tensor failed"); } - void TearDown() override {} + void TearDown() override { CLEAR_SUBCASE() } protected: runtime_tensor input; diff --git a/tests/kernels/test_softplus.cpp b/tests/kernels/test_softplus.cpp index 5b2bd8b06b..f1257a3cf2 100644 --- a/tests/kernels/test_softplus.cpp +++ b/tests/kernels/test_softplus.cpp @@ -43,7 +43,7 @@ class SoftplusTest : public KernelTest, init_tensor(input); } - void TearDown() override {} + void TearDown() override { CLEAR_SUBCASE() } protected: runtime_tensor input; diff --git a/tests/kernels/test_softsign.cpp b/tests/kernels/test_softsign.cpp index 6ab4ee32ca..1e4d76809b 100644 --- a/tests/kernels/test_softsign.cpp +++ b/tests/kernels/test_softsign.cpp @@ -43,7 +43,7 @@ class SoftsignTest : public KernelTest, init_tensor(input); } - void TearDown() override {} + void TearDown() override { CLEAR_SUBCASE() } protected: runtime_tensor input; diff --git a/tests/kernels/test_space_to_batch.cpp b/tests/kernels/test_space_to_batch.cpp index e195be82f1..072cb8d493 100644 --- a/tests/kernels/test_space_to_batch.cpp +++ b/tests/kernels/test_space_to_batch.cpp @@ -58,7 +58,7 @@ class SpaceToBatchTest : public KernelTest, } } - void TearDown() override {} + void TearDown() override { CLEAR_SUBCASE() } protected: runtime_tensor expected; diff --git a/tests/kernels/test_swish.cpp b/tests/kernels/test_swish.cpp index b8815527fe..870744ae3b 100644 --- a/tests/kernels/test_swish.cpp +++ b/tests/kernels/test_swish.cpp @@ -43,7 +43,7 @@ class SwishTest : public KernelTest, init_tensor(input); } - void TearDown() override {} + void TearDown() override { CLEAR_SUBCASE() } protected: runtime_tensor input; diff --git a/tests/kernels/test_topK.cpp b/tests/kernels/test_topK.cpp index ecf0ed9ff5..de519de96b 100644 --- a/tests/kernels/test_topK.cpp +++ b/tests/kernels/test_topK.cpp @@ -49,7 +49,7 @@ class TopKTest : public KernelTest, axis_value = value1 > 0 ? value1 >= (int64_t)l_shape.size() ? 0 : value1 : -value1 > (int64_t)l_shape.size() ? 0 : value1; - int64_t axis_array[] = {value1}; + int64_t axis_array[] = {axis_value}; axis = hrt::create(dt_int64, {1}, {reinterpret_cast(axis_array), sizeof(axis_array)}, @@ -75,7 +75,7 @@ class TopKTest : public KernelTest, k_value = value4; } - void TearDown() override {} + void TearDown() override { CLEAR_SUBCASE() } protected: runtime_tensor input; @@ -91,14 +91,6 @@ class TopKTest : public KernelTest, INSTANTIATE_TEST_SUITE_P(TopK, TopKTest, testing::Combine(testing::Range(0, MAX_CASE_NUM))); -// testing::Combine(testing::Values(dt_float32), -// testing::Values(dims_t{1, 2, 4, 8}, dims_t{1, 3, 16, 16}, -// dims_t{3, 3, 6}, dims_t{16, 16}, -// dims_t{1}, dims_t{1, 3}), -// testing::Values(0, -1 /*, 1, 2, 3*/), -// testing::Values(0, 1), testing::Values(0, 1), -// testing::Values(1 /*, 2, 4, 16*/))); - TEST_P(TopKTest, TopK) { auto l_ort = runtime_tensor_2_ort_tensor(input); diff --git a/tests/kernels/test_topk.json b/tests/kernels/test_topk.json index e81402d777..38dcf435b3 100644 --- a/tests/kernels/test_topk.json +++ b/tests/kernels/test_topk.json @@ -1,7 +1,7 @@ { - "lhs_shape":[[1, 2, 4, 8], [1, 3, 16, 16], [3, 3, 6], [16, 16], [1], [1, 3]], + "lhs_shape":[[2, 3, 16, 16], [2, 3, 16], [16, 16], [6], [1, 3, 16, 16]], "lhs_type":["dt_float32"], - "value1": [0, -1], + "value1": [0, 1, 2, 3, -1, -2, -3, -4], "value2": [0, 1], "value3": [0, 1], "value4": [1] From 6f1445c40432d0a0816cf702263ceab3623bff19 Mon Sep 17 00:00:00 2001 From: Curio Yang Date: Wed, 30 Aug 2023 18:37:06 +0800 Subject: [PATCH 06/25] Feature/add colab link (#1075) * enable jupyter test * link colab --------- Co-authored-by: yanghaoqi --- .github/workflows/jupyter-test.yml | 60 +++++++++++++++--------------- README.md | 1 + 2 files changed, 31 insertions(+), 30 deletions(-) diff --git a/.github/workflows/jupyter-test.yml b/.github/workflows/jupyter-test.yml index f12cf6ad9b..1d2ee23550 100755 --- a/.github/workflows/jupyter-test.yml +++ b/.github/workflows/jupyter-test.yml @@ -1,31 +1,31 @@ -# on: -# push: -# tags: -# - '*' +on: + push: + tags: + - '*' -# jobs: -# test: -# name: test-notebook-${{matrix.config.name}} -# runs-on: ${{matrix.config.os}} -# strategy: -# matrix: -# config: -# - {name: x86_64-macos, os: macos-latest} -# - {name: x86_64-linux, os: ubuntu-latest} -# - {name: x86_64-windows, os: windows-latest} - -# steps: -# - uses: actions/checkout@v2 - -# - name: Setup Python -# uses: actions/setup-python@v2 -# with: -# python-version: 3.7 - -# - name: Install dependencies -# run: pip install --upgrade pip && pip install jupyterlab pytest nbmake - -# - name: Run tests -# run: pytest --nbmake examples/user_guide -# env: -# PROTOCOL_BUFFERS_PYTHON_IMPLEMENTATION: python \ No newline at end of file +jobs: + test: + name: test-notebook-${{matrix.config.name}} + runs-on: ${{matrix.config.os}} + strategy: + matrix: + config: + - {name: x86_64-macos, os: macos-latest} + - {name: x86_64-linux, os: ubuntu-latest} + - {name: x86_64-windows, os: windows-latest} + + steps: + - uses: actions/checkout@v2 + + - name: Setup Python + uses: actions/setup-python@v2 + with: + python-version: 3.7 + + - name: Install dependencies + run: pip install --upgrade pip && pip install jupyterlab pytest nbmake + + - name: Run tests + run: pytest --nbmake examples/user_guide + env: + PROTOCOL_BUFFERS_PYTHON_IMPLEMENTATION: python \ No newline at end of file diff --git a/README.md b/README.md index 89f05f8ef4..7243bcbffe 100644 --- a/README.md +++ b/README.md @@ -52,6 +52,7 @@ Download prebuilt binaries from [Release](https://github.com/kendryte/nncase/rel - [使用说明](./docs/USAGE_v2.md) - [常见问题](./docs/FAQ_ZH.md) - [示例](./examples/user_guide/k230_simulate-ZH.ipynb) +- [Colab run](https://colab.research.google.com/drive/1m8TTree096m5VHmq-Uc60gXyltVCgnRb?usp=sharing) ## Resources From 169b1ee33afcb266cb24ac1ac4566188b7a586a6 Mon Sep 17 00:00:00 2001 From: zhangyang2057 Date: Thu, 31 Aug 2023 09:20:30 +0800 Subject: [PATCH 07/25] Test runner supports dynamic shape model running on evb. (#1076) * Test runner supports dynamic shape model running on evb. - support dynamic model test on evb. - config dump file in config.toml * fix dump_kmodel_desc. --- tests/config.toml | 3 +++ tests/inference.py | 45 ++++++++++++++++++++++++++++---------------- tests/nuc_proxy.py | 5 +++-- tests/test_runner.py | 2 +- tests/test_utils.py | 4 ++-- 5 files changed, 38 insertions(+), 21 deletions(-) diff --git a/tests/config.toml b/tests/config.toml index 1e4ec50d67..604a745df6 100644 --- a/tests/config.toml +++ b/tests/config.toml @@ -1,5 +1,8 @@ name = 'default_config' root = 'tests_output' +kmodel_name = 'test.kmodel' +desc_name = 'kmodel.desc' +infer_name = 'infer_report.json' dump_hist = false dump_infer = false diff --git a/tests/inference.py b/tests/inference.py index 603e73d674..52e9deecd2 100644 --- a/tests/inference.py +++ b/tests/inference.py @@ -14,15 +14,6 @@ def data_shape_list_string(data): return '\n'.join(map(lambda d: ' '.join(map(lambda x: str(x), d['model_shape'])), data)) -def generate_kmodel_data_info(inputs, outputs, infer_dir): - input_shapes = data_shape_list_string(inputs) - output_shapes = data_shape_list_string(outputs) -# input_shapes = '\n'.join(map(lambda input: ' '.join(map(lambda x: str(x), input['model_shape'])), inputs)) - s = f"{len(inputs)} {len(outputs)}\n{input_shapes}\n{output_shapes}" - with open(os.path.join(infer_dir, "kmodel.desc"), "w+") as f: - f.write(s) - - class Inference: def run_inference(self, compiler, target, ptq_enabled, infer_dir): in_ci = test_utils.in_ci() @@ -30,7 +21,7 @@ def run_inference(self, compiler, target, ptq_enabled, infer_dir): nuc_ip = test_utils.nuc_ip() nuc_port = test_utils.nuc_port() test_executable = test_utils.test_executable(target) - running_on_evb = in_ci and target in kpu_targets and nuc_ip is not None and nuc_port is not None and test_executable is not None and len( + running_on_evb = target in kpu_targets and nuc_ip is not None and nuc_port is not None and test_executable is not None and len( self.inputs) > 0 and len(self.outputs) > 0 if self.cfg['dump_infer']: @@ -46,16 +37,16 @@ def run_inference(self, compiler, target, ptq_enabled, infer_dir): compiler.compile() kmodel = compiler.gencode_tobytes() - if self.dynamic: - generate_kmodel_data_info(self.inputs, self.outputs, infer_dir) os.makedirs(infer_dir, exist_ok=True) + if self.dynamic: + self.dump_kmodel_desc(os.path.join(infer_dir, self.cfg['desc_name'])) if not in_ci: - with open(os.path.join(infer_dir, 'test.kmodel'), 'wb') as f: + with open(os.path.join(infer_dir, self.cfg['kmodel_name']), 'wb') as f: f.write(kmodel) compile_opt = self.cfg['compile_opt'] if running_on_evb: - outputs = self.run_evb(target, kmodel, compile_opt) + outputs = self.run_evb(target, kmodel, compile_opt, infer_dir) else: sim = nncase.Simulator() sim.load_model(kmodel) @@ -86,6 +77,13 @@ def set_infer_input(self, sim, compile_opt): sim.set_input_tensor(idx, nncase.RuntimeTensor.from_numpy(data)) + def dump_kmodel_desc(self, file): + input_shapes = data_shape_list_string(self.inputs) + output_shapes = data_shape_list_string(self.outputs) + s = f"{len(self.inputs)} {len(self.outputs)}\n{input_shapes}\n{output_shapes}" + with open(file, "w+") as f: + f.write(s) + def dump_infer_output(self, sim, compile_opt, infer_dir): outputs = [] for i in range(sim.outputs_size): @@ -105,7 +103,7 @@ def dump_infer_output(self, sim, compile_opt, infer_dir): dump_txt_file(os.path.join(infer_dir, f'nncase_result_{i}.txt'), output) return outputs - def run_evb(self, target, kmodel, compile_opt): + def run_evb(self, target, kmodel, compile_opt, infer_dir): ip = test_utils.nuc_ip() port = test_utils.nuc_port() test_executable = test_utils.test_executable(target) @@ -127,6 +125,7 @@ def run_evb(self, target, kmodel, compile_opt): header_dict['app'] = 1 header_dict['kmodel'] = 1 header_dict['inputs'] = len(self.inputs) + header_dict['description'] = 1 if self.dynamic else 0 header_dict['outputs'] = len(self.outputs) client_socket.sendall(json.dumps(header_dict).encode()) @@ -142,7 +141,7 @@ def run_evb(self, target, kmodel, compile_opt): # send kmodel dummy = client_socket.recv(1024) - file_dict['file_name'] = 'test.kmodel' + file_dict['file_name'] = self.cfg['kmodel_name'] file_dict['file_size'] = len(kmodel) client_socket.sendall(json.dumps(file_dict).encode()) dummy = client_socket.recv(1024) @@ -159,6 +158,17 @@ def run_evb(self, target, kmodel, compile_opt): dummy = client_socket.recv(1024) client_socket.sendall(data.tobytes()) + # send kmodel.desc + if self.dynamic: + dummy = client_socket.recv(1024) + desc_file = os.path.join(infer_dir, self.cfg['desc_name']) + file_dict['file_name'] = os.path.basename(desc_file) + file_dict['file_size'] = os.path.getsize(desc_file) + client_socket.sendall(json.dumps(file_dict).encode()) + dummy = client_socket.recv(1024) + with open(desc_file, 'rb') as f: + client_socket.sendall(f.read()) + # get infer result outputs = [] result_dict = {} @@ -187,6 +197,9 @@ def run_evb(self, target, kmodel, compile_opt): output = np.frombuffer(buffer, dtype=self.outputs[i]['dtype']) outputs.append(output) + if not test_utils.in_ci(): + dump_bin_file(os.path.join(infer_dir, f'nncase_result_{i}.bin'), output) + dump_txt_file(os.path.join(infer_dir, f'nncase_result_{i}.txt'), output) client_socket.sendall(f"recv nncase_result_{i}.bin succeed".encode()) client_socket.close() diff --git a/tests/nuc_proxy.py b/tests/nuc_proxy.py index f2ffdac1fa..408bdc6141 100644 --- a/tests/nuc_proxy.py +++ b/tests/nuc_proxy.py @@ -117,7 +117,8 @@ def recv_worker(conn, target): target.logger.info("test case = {0}".format(new_case)) case_dir = os.path.join(target.nfs_dir, new_case) os.makedirs(case_dir) - file_num = header_dict['app'] + header_dict['kmodel'] + header_dict['inputs'] + file_num = header_dict['app'] + header_dict['kmodel'] + \ + header_dict['inputs'] + header_dict['description'] # recv all kinds of files(app + kmodel + inputs) cmds = f'cd {target.working_dir}/{target.name}/{new_case};./' @@ -166,7 +167,7 @@ def infer_worker(target): target.s0.run_cmd('reboot') time.sleep(20) else: - dict['time'] = float(ret.split('\n')[1].split()[1]) + dict['time'] = float(ret.split('\n')[-2].split()[1]) conn.sendall(json.dumps(dict).encode()) dummy = conn.recv(1024) diff --git a/tests/test_runner.py b/tests/test_runner.py index 2e0b89055e..1b52dd1ad2 100644 --- a/tests/test_runner.py +++ b/tests/test_runner.py @@ -56,7 +56,7 @@ def __init__(self, case_name, override_cfg: str = None) -> None: self.dynamic = False if self.cfg['dump_infer']: - self.infer_file = test_utils.infer_file() + self.infer_file = test_utils.infer_file(self.cfg['infer_name']) self.infer_dict = { 'case': 'unknown', 'target': 'cpu', diff --git a/tests/test_utils.py b/tests/test_utils.py index 3cd04c54bd..c2d3894868 100644 --- a/tests/test_utils.py +++ b/tests/test_utils.py @@ -65,5 +65,5 @@ def test_executable(target): return os.getenv('TEST_EXECUTABLE_{0}'.format(target.upper())) -def infer_file(): - return os.getenv('INFER_FILE', 'infer_report.json') +def infer_file(file): + return os.getenv('INFER_FILE', file) From 3f92e3e144a703f9d8c675798e2b7532ff69b87d Mon Sep 17 00:00:00 2001 From: zhangyang2057 Date: Fri, 1 Sep 2023 09:24:47 +0800 Subject: [PATCH 08/25] Fix newline in test_result.txt and markdown. (#1080) --- tests/compare_util.py | 2 +- tests/test_runner.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/compare_util.py b/tests/compare_util.py index 9395cbca21..93f19d8827 100644 --- a/tests/compare_util.py +++ b/tests/compare_util.py @@ -95,7 +95,7 @@ def compare_ndarray(expected: np.ndarray, if dump_hist: y, x = np.histogram(expected - actual, 100) np.savetxt(dump_file, np.stack((x[:-1], y)).T, fmt='%f', delimiter=',') - similarity_info = f"{similarity_name} similarity = {similarity}, threshold = {threshold}" + similarity_info = f"{similarity_name} similarity = {similarity}, threshold = {threshold}\n" if similarity_name in ['cosine', 'euclidean', 'segment']: compare_op = lt diff --git a/tests/test_runner.py b/tests/test_runner.py index 1b52dd1ad2..f793c7b0a5 100644 --- a/tests/test_runner.py +++ b/tests/test_runner.py @@ -267,7 +267,7 @@ def run(self, model_file: Union[List[str], str]): if stage == 'infer' and self.cfg['dump_infer']: self.infer_dict['result'] = 'Pass' if judge else 'Fail' - self.infer_dict['remark'] = result.replace('\n', ' ') + self.infer_dict['remark'] = result.replace('\n', '
') dump_dict_to_json(self.infer_dict, self.infer_file) if not judge: if test_utils.in_ci(): From f67d6b51e439b352e29f53ee3268f0b31a0ec3fa Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E4=B9=90=E4=BB=81=E5=8D=8E?= <31504341+lerenhua@users.noreply.github.com> Date: Fri, 1 Sep 2023 10:51:36 +0800 Subject: [PATCH 09/25] Fix/fix resize image compile error on xuantie (#1077) * Add limit for pad * Fix compile error in xuantie * Fix pad test --- .../nncase/kernels/stackvm/resize_image.h | 4 +- .../src/kernels/stackvm/reference/pad.cpp | 13 ++-- src/Native/src/kernels/stackvm/tensor_ops.cpp | 13 ++++ .../kernels/test_instance_normalization.json | 2 +- tests/kernels/test_pad.cpp | 66 +++++++++++++++---- tests/kernels/test_pad.json | 11 +++- 6 files changed, 90 insertions(+), 19 deletions(-) diff --git a/src/Native/include/nncase/kernels/stackvm/resize_image.h b/src/Native/include/nncase/kernels/stackvm/resize_image.h index 72ff9a69d9..820a05feca 100644 --- a/src/Native/include/nncase/kernels/stackvm/resize_image.h +++ b/src/Native/include/nncase/kernels/stackvm/resize_image.h @@ -72,7 +72,7 @@ get_nearest_pixel_from_origin(image_resize_nearest_mode_t nearest_mode) { switch (nearest_mode) { case image_resize_nearest_mode_t::round_prefer_ceil: return [](float x_original) { - return static_cast(std::round(x_original)); + return static_cast(roundf(x_original)); }; case image_resize_nearest_mode_t::floor: return [](float x_original) { @@ -88,7 +88,7 @@ get_nearest_pixel_from_origin(image_resize_nearest_mode_t nearest_mode) { if (x_original == static_cast(x_original) + 0.5f) { return static_cast(std::floor(x_original)); } - return static_cast(std::round(x_original)); + return static_cast(roundf(x_original)); }; } } \ No newline at end of file diff --git a/src/Native/src/kernels/stackvm/reference/pad.cpp b/src/Native/src/kernels/stackvm/reference/pad.cpp index 0f11590fb4..6186101e8a 100644 --- a/src/Native/src/kernels/stackvm/reference/pad.cpp +++ b/src/Native/src/kernels/stackvm/reference/pad.cpp @@ -56,10 +56,15 @@ dims_t get_in_index(gsl::span index, auto cnt_idx = (int32_t)index[i] - padding.before; if (cnt_idx > (int32_t)in_shape[i] - 1) { pad_element = true; - if (mode == pad_mode_t::reflect) - in_index[i] = - in_shape[i] - 2 - ((size_t)cnt_idx - in_shape[i]); - else if (mode == pad_mode_t::symmetric) + if (mode == pad_mode_t::reflect) { + auto idx = (int32_t)in_shape[i] - 2 - + (cnt_idx - (int32_t)in_shape[i]); + if (idx < 0) { + in_index[i] = std::abs(idx); + } else { + in_index[i] = idx; + } + } else if (mode == pad_mode_t::symmetric) in_index[i] = in_shape[i] - 1 - ((size_t)cnt_idx - in_shape[i]); else if (mode == pad_mode_t::edge) diff --git a/src/Native/src/kernels/stackvm/tensor_ops.cpp b/src/Native/src/kernels/stackvm/tensor_ops.cpp index ea5726d8cb..5357771fb5 100644 --- a/src/Native/src/kernels/stackvm/tensor_ops.cpp +++ b/src/Native/src/kernels/stackvm/tensor_ops.cpp @@ -590,6 +590,19 @@ nncase::kernels::stackvm::pad(runtime::stackvm::pad_mode_t pad_mode, if (is_nop_pad(paddings)) { return ok(input); } + if (pad_mode == runtime::stackvm::pad_mode_t::reflect) { + // 在tensorflow和onnxruntime中,pad在reflect mode下 + // 当before_pad/after_pad > in_dim - 1时 + // 均会出现未定义的行为,因此需要约束输入pad大小 + // 针对in_dim-1 < after_pad <= in_dim-1+before_pad的情况 + // 此处实现结果与onnxruntime对齐 + for (size_t i = 0; i < paddings.size(); ++i) { + if (paddings[i].before > (input_tensor->shape()[i] - 1) || + (paddings[i].after > + (input_tensor->shape()[i] + paddings[i].before - 1))) + return err(std::errc::invalid_argument); + } + } auto out_shape = pad_infer_shape(input_tensor->shape(), paddings); try_output(out_mem, output, input_tensor->dtype(), out_shape); diff --git a/tests/kernels/test_instance_normalization.json b/tests/kernels/test_instance_normalization.json index e8478a0f2d..2a14fe66b3 100644 --- a/tests/kernels/test_instance_normalization.json +++ b/tests/kernels/test_instance_normalization.json @@ -1,4 +1,4 @@ { "lhs_shape":[[3, 3, 16, 16], [64, 2, 4, 8], [1, 2, 4, 8], [24, 16, 16], [24, 3, 16]], - "lhs_type":["dt_float32"], + "lhs_type":["dt_float32"] } \ No newline at end of file diff --git a/tests/kernels/test_pad.cpp b/tests/kernels/test_pad.cpp index c4f1ed7930..0d7d26639b 100644 --- a/tests/kernels/test_pad.cpp +++ b/tests/kernels/test_pad.cpp @@ -36,7 +36,10 @@ class PadTest : public KernelTest, auto l_shape = GetShapeArray("lhs_shape"); auto typecode = GetDataType("lhs_type"); - + mode_str = GetString("mode"); + mode = Str2Mode(mode_str, str_2_padmode); + padding = GetDataArray("padding"); + padding_nncaseformat = ToNncaseFormat(padding); input = hrt::create(typecode, l_shape, host_runtime_tensor::pool_cpu_only) .expect("create tensor failed"); @@ -45,12 +48,41 @@ class PadTest : public KernelTest, .expect("create tensor failed"); init_tensor(value); } + template + T Str2Mode(std::string type, std::map &str_2_mode) { + std::cout << type << std::endl; + if (str_2_mode.find(type) != str_2_mode.end()) { + return str_2_mode[type]; + } else { + // should not be here + return static_cast(0); + } + } + + std::vector ToNncaseFormat(std::vector &padding) { + // int64_t before_pad; + // int64_t after_pad; + std::vector padding_nncase; + for (size_t i = 0; i < padding.size() / 2; ++i) { + padding_nncase.push_back(padding[i]); + padding_nncase.push_back(padding[i + padding.size() / 2]); + } + return padding_nncase; + } void TearDown() override { CLEAR_SUBCASE() } protected: runtime_tensor input; runtime_tensor value; + runtime::stackvm::pad_mode_t mode; + std::string mode_str; + std::vector padding; + std::vector padding_nncaseformat; + std::map str_2_padmode = { + {"constant", runtime::stackvm::pad_mode_t::constant}, + {"reflect", runtime::stackvm::pad_mode_t::reflect}, + {"edge", runtime::stackvm::pad_mode_t::edge}}; }; INSTANTIATE_TEST_SUITE_P(Pad, PadTest, @@ -60,17 +92,17 @@ TEST_P(PadTest, Pad) { // expected size_t size = 0; - int64_t pad_ptr[] = {1, 0, 0, 0, 0, 0, 0, 0}; - auto pad = - hrt::create(dt_int64, {8}, - {reinterpret_cast(pad_ptr), sizeof(pad_ptr)}, - true, host_runtime_tensor::pool_cpu_only) - .expect("create tensor failed"); + // int64_t pad_ptr[] = {1, 0, 0, 0, 0, 0, 0, 0}; + auto pad = hrt::create(dt_int64, {padding.size()}, + {reinterpret_cast(padding.data()), + sizeof(padding[0]) * padding.size()}, + true, host_runtime_tensor::pool_cpu_only) + .expect("create tensor failed"); auto l_ort = runtime_tensor_2_ort_tensor(input); auto pad_ort = runtime_tensor_2_ort_tensor(pad); auto value_ort = runtime_tensor_2_ort_tensor(value); - auto output_ort = ortki_Pad(l_ort, pad_ort, value_ort, "constant"); + auto output_ort = ortki_Pad(l_ort, pad_ort, value_ort, mode_str.c_str()); void *ptr_ort = tensor_buffer(output_ort, &size); dims_t shape(tensor_rank(output_ort)); tensor_shape(output_ort, reinterpret_cast(shape.data())); @@ -80,9 +112,15 @@ TEST_P(PadTest, Pad) { .expect("create tensor failed"); // actual - auto output = kernels::stackvm::pad(runtime::stackvm::pad_mode_t::constant, - input.impl(), pad.impl(), value.impl()) - .expect("pad failed"); + pad = hrt::create( + dt_int64, {padding_nncaseformat.size()}, + {reinterpret_cast(padding_nncaseformat.data()), + sizeof(padding_nncaseformat[0]) * padding_nncaseformat.size()}, + true, host_runtime_tensor::pool_cpu_only) + .expect("create tensor failed"); + auto output = + kernels::stackvm::pad(mode, input.impl(), pad.impl(), value.impl()) + .expect("pad failed"); runtime_tensor actual(output.as().expect("as tensor failed")); bool result = is_same_tensor(expected, actual) || @@ -103,11 +141,17 @@ int main(int argc, char *argv[]) { READY_TEST_CASE_GENERATE() FOR_LOOP(lhs_shape, i) FOR_LOOP(lhs_type, j) + FOR_LOOP(mode, k) + FOR_LOOP(padding, l) SPLIT_ELEMENT(lhs_shape, i) SPLIT_ELEMENT(lhs_type, j) + SPLIT_ELEMENT(mode, k) + SPLIT_ELEMENT(padding, l) WRITE_SUB_CASE() FOR_LOOP_END() FOR_LOOP_END() + FOR_LOOP_END() + FOR_LOOP_END() ::testing::InitGoogleTest(&argc, argv); return RUN_ALL_TESTS(); diff --git a/tests/kernels/test_pad.json b/tests/kernels/test_pad.json index 04e75eaadf..6a6857fd7a 100644 --- a/tests/kernels/test_pad.json +++ b/tests/kernels/test_pad.json @@ -1,4 +1,13 @@ { - "lhs_shape":[[1, 3, 24, 24], [1, 3, 16, 16]], + "lhs_shape":[[2, 3, 24, 24], [2, 3, 16, 16]], + "mode": ["constant", "reflect", "edge"], + "padding":[[1, 0, 0, 0, 1, 0, 0, 0], [1, 0, 0, 0, 2, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0, 0], + [0, 0, 1, 0, 0, 0, 0, 0], + [0, 0, 0, 0, 0, 0, 1, 0], + [0, 0, 0, 1, 0, 0, 0, 0], + [0, 0, 0, 0, 0, 0, 0, 1], + [0, 0, 1, 0, 0, 0, 1, 0], + [0, 0, 0, 1, 0, 0, 0, 1], + [0, 0, 1, 1, 0, 0, 1, 1]], "lhs_type":["dt_int32", "dt_int8", "dt_uint8", "dt_float64", "dt_uint64", "dt_int64", "dt_float32", "dt_float16", "dt_uint32"] } \ No newline at end of file From 68497ed65eb50de88e7b913ec6a2b2809e3b11dd Mon Sep 17 00:00:00 2001 From: zhangyang2057 Date: Tue, 5 Sep 2023 20:09:37 +0800 Subject: [PATCH 10/25] Use more compatible line break for confluence.md. (#1083) --- tests/test_runner.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/test_runner.py b/tests/test_runner.py index f793c7b0a5..7ac0613ffa 100644 --- a/tests/test_runner.py +++ b/tests/test_runner.py @@ -267,7 +267,7 @@ def run(self, model_file: Union[List[str], str]): if stage == 'infer' and self.cfg['dump_infer']: self.infer_dict['result'] = 'Pass' if judge else 'Fail' - self.infer_dict['remark'] = result.replace('\n', '
') + self.infer_dict['remark'] = result.replace('\n', '
') dump_dict_to_json(self.infer_dict, self.infer_file) if not judge: if test_utils.in_ci(): From 7d4c9a8cd42b23819374fcec29515b5fd3444e7a Mon Sep 17 00:00:00 2001 From: HeJunchao <73169088+HeJunchao100813@users.noreply.github.com> Date: Wed, 6 Sep 2023 15:01:03 +0800 Subject: [PATCH 11/25] Fix/kernel sqrt test (#1082) * fix unary_test * fix unary_sqrt_test probabilistic failed * fix json err process * fix sqrt test_case * fix case range&&shape * fix case range * fix * fix --------- Co-authored-by: hejunchao Co-authored-by: HeJunchao100813 --- tests/kernels/kernel_test.h | 42 ++++-- tests/kernels/test_unary.json | 2 +- tests/kernels/test_unary_abs.cpp | 148 ++++++++++++++++++++++ tests/kernels/test_unary_acos.cpp | 148 ++++++++++++++++++++++ tests/kernels/test_unary_acosh.cpp | 34 +++-- tests/kernels/test_unary_asin.cpp | 148 ++++++++++++++++++++++ tests/kernels/test_unary_asinh.cpp | 148 ++++++++++++++++++++++ tests/kernels/test_unary_ceil.cpp | 148 ++++++++++++++++++++++ tests/kernels/test_unary_cos.cpp | 148 ++++++++++++++++++++++ tests/kernels/test_unary_cosh.cpp | 148 ++++++++++++++++++++++ tests/kernels/test_unary_exp.cpp | 148 ++++++++++++++++++++++ tests/kernels/test_unary_floor.cpp | 148 ++++++++++++++++++++++ tests/kernels/test_unary_log.cpp | 34 +++-- tests/kernels/test_unary_logical_not.cpp | 148 ++++++++++++++++++++++ tests/kernels/test_unary_neg.cpp | 148 ++++++++++++++++++++++ tests/kernels/test_unary_other_type.json | 2 +- tests/kernels/test_unary_other_type1.json | 2 +- tests/kernels/test_unary_other_type2.json | 2 +- tests/kernels/test_unary_round.cpp | 147 +++++++++++++++++++++ tests/kernels/test_unary_rsqrt.cpp | 23 ++-- tests/kernels/test_unary_sign.cpp | 148 ++++++++++++++++++++++ tests/kernels/test_unary_sin.cpp | 148 ++++++++++++++++++++++ tests/kernels/test_unary_sinh.cpp | 148 ++++++++++++++++++++++ tests/kernels/test_unary_sqrt.cpp | 34 +++-- tests/kernels/test_unary_square.cpp | 34 +++-- tests/kernels/test_unary_tanh.cpp | 148 ++++++++++++++++++++++ 26 files changed, 2512 insertions(+), 64 deletions(-) diff --git a/tests/kernels/kernel_test.h b/tests/kernels/kernel_test.h index c0ba0ca2ea..c39bc1e77a 100644 --- a/tests/kernels/kernel_test.h +++ b/tests/kernels/kernel_test.h @@ -1080,7 +1080,10 @@ class KernelTest { << (unsigned)document.GetErrorOffset() << " " << GetParseError_En(document.GetParseError()) << std::endl; - assert(document.IsObject()); + + if (!document.IsObject()) { + throw std::runtime_error("type error! it should be Object."); + } } void ParseJson(std::string js_str) { @@ -1089,7 +1092,10 @@ class KernelTest { << (unsigned)_document.GetErrorOffset() << " " << GetParseError_En(_document.GetParseError()) << std::endl; - assert(_document.IsObject()); + + if (!_document.IsObject()) { + throw std::runtime_error("type error! it should be Object."); + } } typecode_t Str2DataType(std::string type) { @@ -1102,27 +1108,41 @@ class KernelTest { } int64_t GetNumber(const char *key) { - assert(_document[key].IsInt64()); + if (!_document[key].IsInt64()) { + throw std::runtime_error("type error! it should be int64."); + } + return _document[key].GetInt64(); } float GetFloatNumber(const char *key) { - assert(_document[key].IsDouble()); + if (!_document[key].IsDouble()) { + throw std::runtime_error("type error! it should be double."); + } + return _document[key].GetFloat(); } typecode_t GetDataType(const char *key) { - assert(_document[key].IsString()); + if (!_document[key].IsString()) { + throw std::runtime_error("type error! it should be string."); + } + return Str2DataType(_document[key].GetString()); } std::string GetString(const char *key) { - assert(_document[key].IsString()); + if (!_document[key].IsString()) { + throw std::runtime_error("type error! it should be string."); + } + return _document[key].GetString(); } dims_t GetShapeArray(const char *key) { - assert(_document[key].IsArray()); + if (!_document[key].IsArray()) { + throw std::runtime_error("type error! it should be array."); + } Value &array = _document[key]; size_t arraySize = array.Size(); @@ -1140,7 +1160,9 @@ class KernelTest { } std::vector GetDataArray(const char *key) { - assert(_document[key].IsArray()); + if (!_document[key].IsArray()) { + throw std::runtime_error("type error! it should be array."); + } Value &array = _document[key]; size_t arraySize = array.Size(); @@ -1158,7 +1180,9 @@ class KernelTest { } axes_t GetAxesArray(const char *key) { - assert(_document[key].IsArray()); + if (!_document[key].IsArray()) { + throw std::runtime_error("type error! it should be array."); + } Value &array = _document[key]; size_t arraySize = array.Size(); diff --git a/tests/kernels/test_unary.json b/tests/kernels/test_unary.json index 26585afb47..e642ca0349 100644 --- a/tests/kernels/test_unary.json +++ b/tests/kernels/test_unary.json @@ -1,4 +1,4 @@ { - "i_shape":[[1, 3, 16, 16], [3, 16, 16], [3, 16, 1], [16, 16], [16, 1], [1, 16, 1], [16], [1], []], + "i_shape":[[1, 3, 16, 16], [3, 16, 16], [3, 16, 1], [16, 16], [16, 1], [1, 16, 1], [16], [1], [], [1, 30, 288, 288], [1, 30, 288], [288, 288], [288]], "lhs_type":["dt_float32", "dt_int32", "dt_int64", "dt_float64", "dt_float16"] } \ No newline at end of file diff --git a/tests/kernels/test_unary_abs.cpp b/tests/kernels/test_unary_abs.cpp index ae12d4ed59..f68590d1bf 100644 --- a/tests/kernels/test_unary_abs.cpp +++ b/tests/kernels/test_unary_abs.cpp @@ -45,6 +45,152 @@ class UnaryTest : public KernelTest, void TearDown() override { CLEAR_SUBCASE() } + void init_tensor(runtime_tensor &tensor) override { + auto dtype = tensor.datatype(); + switch (dtype) { + case dt_int8: { + std::random_device rd; + std::mt19937 gen(rd()); + std::uniform_int_distribution<> dis(-100000, 100000); + NNCASE_UNUSED auto res = kernels::stackvm::apply( + tensor.shape(), + [&](gsl::span index) -> result { + get(tensor, index) = static_cast(dis(gen)); + return ok(); + }); + break; + } + case dt_int16: { + std::random_device rd; + std::mt19937 gen(rd()); + std::uniform_int_distribution<> dis(-100000, 100000); + NNCASE_UNUSED auto res = kernels::stackvm::apply( + tensor.shape(), + [&](gsl::span index) -> result { + get(tensor, index) = + static_cast(dis(gen)); + return ok(); + }); + break; + } + case dt_int32: { + std::random_device rd; + std::mt19937 gen(rd()); + std::uniform_int_distribution<> dis(-100000, 100000); + NNCASE_UNUSED auto res = kernels::stackvm::apply( + tensor.shape(), + [&](gsl::span index) -> result { + get(tensor, index) = dis(gen); + return ok(); + }); + break; + } + case dt_int64: { + std::random_device rd; + std::mt19937 gen(rd()); + std::uniform_int_distribution<> dis(-100000, 100000); + NNCASE_UNUSED auto res = kernels::stackvm::apply( + tensor.shape(), + [&](gsl::span index) -> result { + get(tensor, index) = + static_cast(dis(gen)); + return ok(); + }); + break; + } + case dt_uint8: { + std::random_device rd; + std::mt19937 gen(rd()); + std::uniform_int_distribution<> dis(-100000, 100000); + NNCASE_UNUSED auto res = kernels::stackvm::apply( + tensor.shape(), + [&](gsl::span index) -> result { + get(tensor, index) = + static_cast(dis(gen)); + return ok(); + }); + break; + } + case dt_uint16: { + std::random_device rd; + std::mt19937 gen(rd()); + std::uniform_int_distribution<> dis(-100000, 100000); + NNCASE_UNUSED auto res = kernels::stackvm::apply( + tensor.shape(), + [&](gsl::span index) -> result { + get(tensor, index) = + static_cast(dis(gen)); + return ok(); + }); + break; + } + case dt_uint32: { + std::random_device rd; + std::mt19937 gen(rd()); + std::uniform_int_distribution<> dis(-100000, 100000); + NNCASE_UNUSED auto res = kernels::stackvm::apply( + tensor.shape(), + [&](gsl::span index) -> result { + get(tensor, index) = + static_cast(dis(gen)); + return ok(); + }); + break; + } + case dt_uint64: { + std::random_device rd; + std::mt19937 gen(rd()); + std::uniform_int_distribution dis(-100000, 100000); + NNCASE_UNUSED auto res = kernels::stackvm::apply( + tensor.shape(), + [&](gsl::span index) -> result { + get(tensor, index) = + static_cast(dis(gen)); + return ok(); + }); + break; + } + case dt_float16: { + std::random_device rd; + std::mt19937 gen(rd()); + std::uniform_real_distribution dis(-10000.0f, 10000.0f); + NNCASE_UNUSED auto res = kernels::stackvm::apply( + tensor.shape(), + [&](gsl::span index) -> result { + get(tensor, index) = static_cast(dis(gen)); + return ok(); + }); + break; + } + case dt_float32: { + std::random_device rd; + std::mt19937 gen(rd()); + std::uniform_real_distribution dis(-100000.0f, 100000.0f); + NNCASE_UNUSED auto res = kernels::stackvm::apply( + tensor.shape(), + [&](gsl::span index) -> result { + get(tensor, index) = static_cast(dis(gen)); + return ok(); + }); + break; + } + case dt_float64: { + std::random_device rd; + std::mt19937 gen(rd()); + std::uniform_real_distribution dis(-100000.0, 100000.0); + NNCASE_UNUSED auto res = kernels::stackvm::apply( + tensor.shape(), + [&](gsl::span index) -> result { + get(tensor, index) = static_cast(dis(gen)); + return ok(); + }); + break; + } + default: { + } + } + } + protected: runtime_tensor input; }; @@ -77,6 +223,8 @@ TEST_P(UnaryTest, abs) { cosine_similarity_tensor(expected, actual); if (!result) { + std::cout << "input "; + print_runtime_tensor(input); std::cout << "actual "; print_runtime_tensor(actual); std::cout << "expected "; diff --git a/tests/kernels/test_unary_acos.cpp b/tests/kernels/test_unary_acos.cpp index cf406cd756..d642924876 100644 --- a/tests/kernels/test_unary_acos.cpp +++ b/tests/kernels/test_unary_acos.cpp @@ -45,6 +45,152 @@ class UnaryTest : public KernelTest, void TearDown() override { CLEAR_SUBCASE() } + void init_tensor(runtime_tensor &tensor) override { + auto dtype = tensor.datatype(); + switch (dtype) { + case dt_int8: { + std::random_device rd; + std::mt19937 gen(rd()); + std::uniform_int_distribution<> dis(-100000, 100000); + NNCASE_UNUSED auto res = kernels::stackvm::apply( + tensor.shape(), + [&](gsl::span index) -> result { + get(tensor, index) = static_cast(dis(gen)); + return ok(); + }); + break; + } + case dt_int16: { + std::random_device rd; + std::mt19937 gen(rd()); + std::uniform_int_distribution<> dis(-100000, 100000); + NNCASE_UNUSED auto res = kernels::stackvm::apply( + tensor.shape(), + [&](gsl::span index) -> result { + get(tensor, index) = + static_cast(dis(gen)); + return ok(); + }); + break; + } + case dt_int32: { + std::random_device rd; + std::mt19937 gen(rd()); + std::uniform_int_distribution<> dis(-100000, 100000); + NNCASE_UNUSED auto res = kernels::stackvm::apply( + tensor.shape(), + [&](gsl::span index) -> result { + get(tensor, index) = dis(gen); + return ok(); + }); + break; + } + case dt_int64: { + std::random_device rd; + std::mt19937 gen(rd()); + std::uniform_int_distribution<> dis(-100000, 100000); + NNCASE_UNUSED auto res = kernels::stackvm::apply( + tensor.shape(), + [&](gsl::span index) -> result { + get(tensor, index) = + static_cast(dis(gen)); + return ok(); + }); + break; + } + case dt_uint8: { + std::random_device rd; + std::mt19937 gen(rd()); + std::uniform_int_distribution<> dis(-100000, 100000); + NNCASE_UNUSED auto res = kernels::stackvm::apply( + tensor.shape(), + [&](gsl::span index) -> result { + get(tensor, index) = + static_cast(dis(gen)); + return ok(); + }); + break; + } + case dt_uint16: { + std::random_device rd; + std::mt19937 gen(rd()); + std::uniform_int_distribution<> dis(-100000, 100000); + NNCASE_UNUSED auto res = kernels::stackvm::apply( + tensor.shape(), + [&](gsl::span index) -> result { + get(tensor, index) = + static_cast(dis(gen)); + return ok(); + }); + break; + } + case dt_uint32: { + std::random_device rd; + std::mt19937 gen(rd()); + std::uniform_int_distribution<> dis(-100000, 100000); + NNCASE_UNUSED auto res = kernels::stackvm::apply( + tensor.shape(), + [&](gsl::span index) -> result { + get(tensor, index) = + static_cast(dis(gen)); + return ok(); + }); + break; + } + case dt_uint64: { + std::random_device rd; + std::mt19937 gen(rd()); + std::uniform_int_distribution dis(-100000, 100000); + NNCASE_UNUSED auto res = kernels::stackvm::apply( + tensor.shape(), + [&](gsl::span index) -> result { + get(tensor, index) = + static_cast(dis(gen)); + return ok(); + }); + break; + } + case dt_float16: { + std::random_device rd; + std::mt19937 gen(rd()); + std::uniform_real_distribution dis(-10000.0f, 10000.0f); + NNCASE_UNUSED auto res = kernels::stackvm::apply( + tensor.shape(), + [&](gsl::span index) -> result { + get(tensor, index) = static_cast(dis(gen)); + return ok(); + }); + break; + } + case dt_float32: { + std::random_device rd; + std::mt19937 gen(rd()); + std::uniform_real_distribution dis(-100000.0f, 100000.0f); + NNCASE_UNUSED auto res = kernels::stackvm::apply( + tensor.shape(), + [&](gsl::span index) -> result { + get(tensor, index) = static_cast(dis(gen)); + return ok(); + }); + break; + } + case dt_float64: { + std::random_device rd; + std::mt19937 gen(rd()); + std::uniform_real_distribution dis(-100000.0, 100000.0); + NNCASE_UNUSED auto res = kernels::stackvm::apply( + tensor.shape(), + [&](gsl::span index) -> result { + get(tensor, index) = static_cast(dis(gen)); + return ok(); + }); + break; + } + default: { + } + } + } + protected: runtime_tensor input; }; @@ -77,6 +223,8 @@ TEST_P(UnaryTest, acos) { cosine_similarity_tensor(expected, actual); if (!result) { + std::cout << "input "; + print_runtime_tensor(input); std::cout << "actual "; print_runtime_tensor(actual); std::cout << "expected "; diff --git a/tests/kernels/test_unary_acosh.cpp b/tests/kernels/test_unary_acosh.cpp index baefa786fd..8239ff6f25 100644 --- a/tests/kernels/test_unary_acosh.cpp +++ b/tests/kernels/test_unary_acosh.cpp @@ -51,7 +51,7 @@ class UnaryTest : public KernelTest, case dt_int8: { std::random_device rd; std::mt19937 gen(rd()); - std::uniform_int_distribution<> dis(1, 6); + std::uniform_int_distribution<> dis(1, 100000); NNCASE_UNUSED auto res = kernels::stackvm::apply( tensor.shape(), [&](gsl::span index) -> result { @@ -63,7 +63,7 @@ class UnaryTest : public KernelTest, case dt_int16: { std::random_device rd; std::mt19937 gen(rd()); - std::uniform_int_distribution<> dis(1, 6); + std::uniform_int_distribution<> dis(1, 100000); NNCASE_UNUSED auto res = kernels::stackvm::apply( tensor.shape(), [&](gsl::span index) -> result { @@ -76,7 +76,7 @@ class UnaryTest : public KernelTest, case dt_int32: { std::random_device rd; std::mt19937 gen(rd()); - std::uniform_int_distribution<> dis(1, 6); + std::uniform_int_distribution<> dis(1, 100000); NNCASE_UNUSED auto res = kernels::stackvm::apply( tensor.shape(), [&](gsl::span index) -> result { @@ -88,7 +88,7 @@ class UnaryTest : public KernelTest, case dt_int64: { std::random_device rd; std::mt19937 gen(rd()); - std::uniform_int_distribution<> dis(1, 6); + std::uniform_int_distribution<> dis(1, 100000); NNCASE_UNUSED auto res = kernels::stackvm::apply( tensor.shape(), [&](gsl::span index) -> result { @@ -101,7 +101,7 @@ class UnaryTest : public KernelTest, case dt_uint8: { std::random_device rd; std::mt19937 gen(rd()); - std::uniform_int_distribution<> dis(1, 127); + std::uniform_int_distribution<> dis(1, 100000); NNCASE_UNUSED auto res = kernels::stackvm::apply( tensor.shape(), [&](gsl::span index) -> result { @@ -114,7 +114,7 @@ class UnaryTest : public KernelTest, case dt_uint16: { std::random_device rd; std::mt19937 gen(rd()); - std::uniform_int_distribution<> dis(1, 127); + std::uniform_int_distribution<> dis(1, 100000); NNCASE_UNUSED auto res = kernels::stackvm::apply( tensor.shape(), [&](gsl::span index) -> result { @@ -127,7 +127,7 @@ class UnaryTest : public KernelTest, case dt_uint32: { std::random_device rd; std::mt19937 gen(rd()); - std::uniform_int_distribution<> dis(1, 127); + std::uniform_int_distribution<> dis(1, 100000); NNCASE_UNUSED auto res = kernels::stackvm::apply( tensor.shape(), [&](gsl::span index) -> result { @@ -140,7 +140,7 @@ class UnaryTest : public KernelTest, case dt_uint64: { std::random_device rd; std::mt19937 gen(rd()); - std::uniform_int_distribution dis(1, 127); + std::uniform_int_distribution dis(1, 100000); NNCASE_UNUSED auto res = kernels::stackvm::apply( tensor.shape(), [&](gsl::span index) -> result { @@ -150,10 +150,22 @@ class UnaryTest : public KernelTest, }); break; } + case dt_float16: { + std::random_device rd; + std::mt19937 gen(rd()); + std::uniform_real_distribution dis(1.0f, 10000.0f); + NNCASE_UNUSED auto res = kernels::stackvm::apply( + tensor.shape(), + [&](gsl::span index) -> result { + get(tensor, index) = static_cast(dis(gen)); + return ok(); + }); + break; + } case dt_float32: { std::random_device rd; std::mt19937 gen(rd()); - std::uniform_real_distribution dis(1.0f, 2.0f); + std::uniform_real_distribution dis(1.0f, 100000.0f); NNCASE_UNUSED auto res = kernels::stackvm::apply( tensor.shape(), [&](gsl::span index) -> result { @@ -165,7 +177,7 @@ class UnaryTest : public KernelTest, case dt_float64: { std::random_device rd; std::mt19937 gen(rd()); - std::uniform_real_distribution dis(1.0, 2.0); + std::uniform_real_distribution dis(1.0, 100000.0); NNCASE_UNUSED auto res = kernels::stackvm::apply( tensor.shape(), [&](gsl::span index) -> result { @@ -211,6 +223,8 @@ TEST_P(UnaryTest, acosh) { cosine_similarity_tensor(expected, actual); if (!result) { + std::cout << "input "; + print_runtime_tensor(input); std::cout << "actual "; print_runtime_tensor(actual); std::cout << "expected "; diff --git a/tests/kernels/test_unary_asin.cpp b/tests/kernels/test_unary_asin.cpp index a7841ee9f0..d31a244931 100644 --- a/tests/kernels/test_unary_asin.cpp +++ b/tests/kernels/test_unary_asin.cpp @@ -45,6 +45,152 @@ class UnaryTest : public KernelTest, void TearDown() override { CLEAR_SUBCASE() } + void init_tensor(runtime_tensor &tensor) override { + auto dtype = tensor.datatype(); + switch (dtype) { + case dt_int8: { + std::random_device rd; + std::mt19937 gen(rd()); + std::uniform_int_distribution<> dis(-100000, 100000); + NNCASE_UNUSED auto res = kernels::stackvm::apply( + tensor.shape(), + [&](gsl::span index) -> result { + get(tensor, index) = static_cast(dis(gen)); + return ok(); + }); + break; + } + case dt_int16: { + std::random_device rd; + std::mt19937 gen(rd()); + std::uniform_int_distribution<> dis(-100000, 100000); + NNCASE_UNUSED auto res = kernels::stackvm::apply( + tensor.shape(), + [&](gsl::span index) -> result { + get(tensor, index) = + static_cast(dis(gen)); + return ok(); + }); + break; + } + case dt_int32: { + std::random_device rd; + std::mt19937 gen(rd()); + std::uniform_int_distribution<> dis(-100000, 100000); + NNCASE_UNUSED auto res = kernels::stackvm::apply( + tensor.shape(), + [&](gsl::span index) -> result { + get(tensor, index) = dis(gen); + return ok(); + }); + break; + } + case dt_int64: { + std::random_device rd; + std::mt19937 gen(rd()); + std::uniform_int_distribution<> dis(-100000, 100000); + NNCASE_UNUSED auto res = kernels::stackvm::apply( + tensor.shape(), + [&](gsl::span index) -> result { + get(tensor, index) = + static_cast(dis(gen)); + return ok(); + }); + break; + } + case dt_uint8: { + std::random_device rd; + std::mt19937 gen(rd()); + std::uniform_int_distribution<> dis(-100000, 100000); + NNCASE_UNUSED auto res = kernels::stackvm::apply( + tensor.shape(), + [&](gsl::span index) -> result { + get(tensor, index) = + static_cast(dis(gen)); + return ok(); + }); + break; + } + case dt_uint16: { + std::random_device rd; + std::mt19937 gen(rd()); + std::uniform_int_distribution<> dis(-100000, 100000); + NNCASE_UNUSED auto res = kernels::stackvm::apply( + tensor.shape(), + [&](gsl::span index) -> result { + get(tensor, index) = + static_cast(dis(gen)); + return ok(); + }); + break; + } + case dt_uint32: { + std::random_device rd; + std::mt19937 gen(rd()); + std::uniform_int_distribution<> dis(-100000, 100000); + NNCASE_UNUSED auto res = kernels::stackvm::apply( + tensor.shape(), + [&](gsl::span index) -> result { + get(tensor, index) = + static_cast(dis(gen)); + return ok(); + }); + break; + } + case dt_uint64: { + std::random_device rd; + std::mt19937 gen(rd()); + std::uniform_int_distribution dis(-100000, 100000); + NNCASE_UNUSED auto res = kernels::stackvm::apply( + tensor.shape(), + [&](gsl::span index) -> result { + get(tensor, index) = + static_cast(dis(gen)); + return ok(); + }); + break; + } + case dt_float16: { + std::random_device rd; + std::mt19937 gen(rd()); + std::uniform_real_distribution dis(-10000.0f, 10000.0f); + NNCASE_UNUSED auto res = kernels::stackvm::apply( + tensor.shape(), + [&](gsl::span index) -> result { + get(tensor, index) = static_cast(dis(gen)); + return ok(); + }); + break; + } + case dt_float32: { + std::random_device rd; + std::mt19937 gen(rd()); + std::uniform_real_distribution dis(-100000.0f, 100000.0f); + NNCASE_UNUSED auto res = kernels::stackvm::apply( + tensor.shape(), + [&](gsl::span index) -> result { + get(tensor, index) = static_cast(dis(gen)); + return ok(); + }); + break; + } + case dt_float64: { + std::random_device rd; + std::mt19937 gen(rd()); + std::uniform_real_distribution dis(-100000.0, 100000.0); + NNCASE_UNUSED auto res = kernels::stackvm::apply( + tensor.shape(), + [&](gsl::span index) -> result { + get(tensor, index) = static_cast(dis(gen)); + return ok(); + }); + break; + } + default: { + } + } + } + protected: runtime_tensor input; }; @@ -77,6 +223,8 @@ TEST_P(UnaryTest, asin) { cosine_similarity_tensor(expected, actual); if (!result) { + std::cout << "input "; + print_runtime_tensor(input); std::cout << "actual "; print_runtime_tensor(actual); std::cout << "expected "; diff --git a/tests/kernels/test_unary_asinh.cpp b/tests/kernels/test_unary_asinh.cpp index 9a5fb65bf6..a2bb8d78a8 100644 --- a/tests/kernels/test_unary_asinh.cpp +++ b/tests/kernels/test_unary_asinh.cpp @@ -45,6 +45,152 @@ class UnaryTest : public KernelTest, void TearDown() override { CLEAR_SUBCASE() } + void init_tensor(runtime_tensor &tensor) override { + auto dtype = tensor.datatype(); + switch (dtype) { + case dt_int8: { + std::random_device rd; + std::mt19937 gen(rd()); + std::uniform_int_distribution<> dis(-100000, 100000); + NNCASE_UNUSED auto res = kernels::stackvm::apply( + tensor.shape(), + [&](gsl::span index) -> result { + get(tensor, index) = static_cast(dis(gen)); + return ok(); + }); + break; + } + case dt_int16: { + std::random_device rd; + std::mt19937 gen(rd()); + std::uniform_int_distribution<> dis(-100000, 100000); + NNCASE_UNUSED auto res = kernels::stackvm::apply( + tensor.shape(), + [&](gsl::span index) -> result { + get(tensor, index) = + static_cast(dis(gen)); + return ok(); + }); + break; + } + case dt_int32: { + std::random_device rd; + std::mt19937 gen(rd()); + std::uniform_int_distribution<> dis(-100000, 100000); + NNCASE_UNUSED auto res = kernels::stackvm::apply( + tensor.shape(), + [&](gsl::span index) -> result { + get(tensor, index) = dis(gen); + return ok(); + }); + break; + } + case dt_int64: { + std::random_device rd; + std::mt19937 gen(rd()); + std::uniform_int_distribution<> dis(-100000, 100000); + NNCASE_UNUSED auto res = kernels::stackvm::apply( + tensor.shape(), + [&](gsl::span index) -> result { + get(tensor, index) = + static_cast(dis(gen)); + return ok(); + }); + break; + } + case dt_uint8: { + std::random_device rd; + std::mt19937 gen(rd()); + std::uniform_int_distribution<> dis(-100000, 100000); + NNCASE_UNUSED auto res = kernels::stackvm::apply( + tensor.shape(), + [&](gsl::span index) -> result { + get(tensor, index) = + static_cast(dis(gen)); + return ok(); + }); + break; + } + case dt_uint16: { + std::random_device rd; + std::mt19937 gen(rd()); + std::uniform_int_distribution<> dis(-100000, 100000); + NNCASE_UNUSED auto res = kernels::stackvm::apply( + tensor.shape(), + [&](gsl::span index) -> result { + get(tensor, index) = + static_cast(dis(gen)); + return ok(); + }); + break; + } + case dt_uint32: { + std::random_device rd; + std::mt19937 gen(rd()); + std::uniform_int_distribution<> dis(-100000, 100000); + NNCASE_UNUSED auto res = kernels::stackvm::apply( + tensor.shape(), + [&](gsl::span index) -> result { + get(tensor, index) = + static_cast(dis(gen)); + return ok(); + }); + break; + } + case dt_uint64: { + std::random_device rd; + std::mt19937 gen(rd()); + std::uniform_int_distribution dis(-100000, 100000); + NNCASE_UNUSED auto res = kernels::stackvm::apply( + tensor.shape(), + [&](gsl::span index) -> result { + get(tensor, index) = + static_cast(dis(gen)); + return ok(); + }); + break; + } + case dt_float16: { + std::random_device rd; + std::mt19937 gen(rd()); + std::uniform_real_distribution dis(-10000.0f, 10000.0f); + NNCASE_UNUSED auto res = kernels::stackvm::apply( + tensor.shape(), + [&](gsl::span index) -> result { + get(tensor, index) = static_cast(dis(gen)); + return ok(); + }); + break; + } + case dt_float32: { + std::random_device rd; + std::mt19937 gen(rd()); + std::uniform_real_distribution dis(-100000.0f, 100000.0f); + NNCASE_UNUSED auto res = kernels::stackvm::apply( + tensor.shape(), + [&](gsl::span index) -> result { + get(tensor, index) = static_cast(dis(gen)); + return ok(); + }); + break; + } + case dt_float64: { + std::random_device rd; + std::mt19937 gen(rd()); + std::uniform_real_distribution dis(-100000.0, 100000.0); + NNCASE_UNUSED auto res = kernels::stackvm::apply( + tensor.shape(), + [&](gsl::span index) -> result { + get(tensor, index) = static_cast(dis(gen)); + return ok(); + }); + break; + } + default: { + } + } + } + protected: runtime_tensor input; }; @@ -77,6 +223,8 @@ TEST_P(UnaryTest, asinh) { cosine_similarity_tensor(expected, actual); if (!result) { + std::cout << "input "; + print_runtime_tensor(input); std::cout << "actual "; print_runtime_tensor(actual); std::cout << "expected "; diff --git a/tests/kernels/test_unary_ceil.cpp b/tests/kernels/test_unary_ceil.cpp index 043850ddc5..3bdeff05fd 100644 --- a/tests/kernels/test_unary_ceil.cpp +++ b/tests/kernels/test_unary_ceil.cpp @@ -45,6 +45,152 @@ class UnaryTest : public KernelTest, void TearDown() override { CLEAR_SUBCASE() } + void init_tensor(runtime_tensor &tensor) override { + auto dtype = tensor.datatype(); + switch (dtype) { + case dt_int8: { + std::random_device rd; + std::mt19937 gen(rd()); + std::uniform_int_distribution<> dis(-100000, 100000); + NNCASE_UNUSED auto res = kernels::stackvm::apply( + tensor.shape(), + [&](gsl::span index) -> result { + get(tensor, index) = static_cast(dis(gen)); + return ok(); + }); + break; + } + case dt_int16: { + std::random_device rd; + std::mt19937 gen(rd()); + std::uniform_int_distribution<> dis(-100000, 100000); + NNCASE_UNUSED auto res = kernels::stackvm::apply( + tensor.shape(), + [&](gsl::span index) -> result { + get(tensor, index) = + static_cast(dis(gen)); + return ok(); + }); + break; + } + case dt_int32: { + std::random_device rd; + std::mt19937 gen(rd()); + std::uniform_int_distribution<> dis(-100000, 100000); + NNCASE_UNUSED auto res = kernels::stackvm::apply( + tensor.shape(), + [&](gsl::span index) -> result { + get(tensor, index) = dis(gen); + return ok(); + }); + break; + } + case dt_int64: { + std::random_device rd; + std::mt19937 gen(rd()); + std::uniform_int_distribution<> dis(-100000, 100000); + NNCASE_UNUSED auto res = kernels::stackvm::apply( + tensor.shape(), + [&](gsl::span index) -> result { + get(tensor, index) = + static_cast(dis(gen)); + return ok(); + }); + break; + } + case dt_uint8: { + std::random_device rd; + std::mt19937 gen(rd()); + std::uniform_int_distribution<> dis(-100000, 100000); + NNCASE_UNUSED auto res = kernels::stackvm::apply( + tensor.shape(), + [&](gsl::span index) -> result { + get(tensor, index) = + static_cast(dis(gen)); + return ok(); + }); + break; + } + case dt_uint16: { + std::random_device rd; + std::mt19937 gen(rd()); + std::uniform_int_distribution<> dis(-100000, 100000); + NNCASE_UNUSED auto res = kernels::stackvm::apply( + tensor.shape(), + [&](gsl::span index) -> result { + get(tensor, index) = + static_cast(dis(gen)); + return ok(); + }); + break; + } + case dt_uint32: { + std::random_device rd; + std::mt19937 gen(rd()); + std::uniform_int_distribution<> dis(-100000, 100000); + NNCASE_UNUSED auto res = kernels::stackvm::apply( + tensor.shape(), + [&](gsl::span index) -> result { + get(tensor, index) = + static_cast(dis(gen)); + return ok(); + }); + break; + } + case dt_uint64: { + std::random_device rd; + std::mt19937 gen(rd()); + std::uniform_int_distribution dis(-100000, 100000); + NNCASE_UNUSED auto res = kernels::stackvm::apply( + tensor.shape(), + [&](gsl::span index) -> result { + get(tensor, index) = + static_cast(dis(gen)); + return ok(); + }); + break; + } + case dt_float16: { + std::random_device rd; + std::mt19937 gen(rd()); + std::uniform_real_distribution dis(-10000.0f, 10000.0f); + NNCASE_UNUSED auto res = kernels::stackvm::apply( + tensor.shape(), + [&](gsl::span index) -> result { + get(tensor, index) = static_cast(dis(gen)); + return ok(); + }); + break; + } + case dt_float32: { + std::random_device rd; + std::mt19937 gen(rd()); + std::uniform_real_distribution dis(-100000.0f, 100000.0f); + NNCASE_UNUSED auto res = kernels::stackvm::apply( + tensor.shape(), + [&](gsl::span index) -> result { + get(tensor, index) = static_cast(dis(gen)); + return ok(); + }); + break; + } + case dt_float64: { + std::random_device rd; + std::mt19937 gen(rd()); + std::uniform_real_distribution dis(-100000.0, 100000.0); + NNCASE_UNUSED auto res = kernels::stackvm::apply( + tensor.shape(), + [&](gsl::span index) -> result { + get(tensor, index) = static_cast(dis(gen)); + return ok(); + }); + break; + } + default: { + } + } + } + protected: runtime_tensor input; }; @@ -77,6 +223,8 @@ TEST_P(UnaryTest, ceil) { cosine_similarity_tensor(expected, actual); if (!result) { + std::cout << "input "; + print_runtime_tensor(input); std::cout << "actual "; print_runtime_tensor(actual); std::cout << "expected "; diff --git a/tests/kernels/test_unary_cos.cpp b/tests/kernels/test_unary_cos.cpp index 11de46cb33..94c9a36ce1 100644 --- a/tests/kernels/test_unary_cos.cpp +++ b/tests/kernels/test_unary_cos.cpp @@ -45,6 +45,152 @@ class UnaryTest : public KernelTest, void TearDown() override { CLEAR_SUBCASE() } + void init_tensor(runtime_tensor &tensor) override { + auto dtype = tensor.datatype(); + switch (dtype) { + case dt_int8: { + std::random_device rd; + std::mt19937 gen(rd()); + std::uniform_int_distribution<> dis(-100000, 100000); + NNCASE_UNUSED auto res = kernels::stackvm::apply( + tensor.shape(), + [&](gsl::span index) -> result { + get(tensor, index) = static_cast(dis(gen)); + return ok(); + }); + break; + } + case dt_int16: { + std::random_device rd; + std::mt19937 gen(rd()); + std::uniform_int_distribution<> dis(-100000, 100000); + NNCASE_UNUSED auto res = kernels::stackvm::apply( + tensor.shape(), + [&](gsl::span index) -> result { + get(tensor, index) = + static_cast(dis(gen)); + return ok(); + }); + break; + } + case dt_int32: { + std::random_device rd; + std::mt19937 gen(rd()); + std::uniform_int_distribution<> dis(-100000, 100000); + NNCASE_UNUSED auto res = kernels::stackvm::apply( + tensor.shape(), + [&](gsl::span index) -> result { + get(tensor, index) = dis(gen); + return ok(); + }); + break; + } + case dt_int64: { + std::random_device rd; + std::mt19937 gen(rd()); + std::uniform_int_distribution<> dis(-100000, 100000); + NNCASE_UNUSED auto res = kernels::stackvm::apply( + tensor.shape(), + [&](gsl::span index) -> result { + get(tensor, index) = + static_cast(dis(gen)); + return ok(); + }); + break; + } + case dt_uint8: { + std::random_device rd; + std::mt19937 gen(rd()); + std::uniform_int_distribution<> dis(-100000, 100000); + NNCASE_UNUSED auto res = kernels::stackvm::apply( + tensor.shape(), + [&](gsl::span index) -> result { + get(tensor, index) = + static_cast(dis(gen)); + return ok(); + }); + break; + } + case dt_uint16: { + std::random_device rd; + std::mt19937 gen(rd()); + std::uniform_int_distribution<> dis(-100000, 100000); + NNCASE_UNUSED auto res = kernels::stackvm::apply( + tensor.shape(), + [&](gsl::span index) -> result { + get(tensor, index) = + static_cast(dis(gen)); + return ok(); + }); + break; + } + case dt_uint32: { + std::random_device rd; + std::mt19937 gen(rd()); + std::uniform_int_distribution<> dis(-100000, 100000); + NNCASE_UNUSED auto res = kernels::stackvm::apply( + tensor.shape(), + [&](gsl::span index) -> result { + get(tensor, index) = + static_cast(dis(gen)); + return ok(); + }); + break; + } + case dt_uint64: { + std::random_device rd; + std::mt19937 gen(rd()); + std::uniform_int_distribution dis(-100000, 100000); + NNCASE_UNUSED auto res = kernels::stackvm::apply( + tensor.shape(), + [&](gsl::span index) -> result { + get(tensor, index) = + static_cast(dis(gen)); + return ok(); + }); + break; + } + case dt_float16: { + std::random_device rd; + std::mt19937 gen(rd()); + std::uniform_real_distribution dis(-10000.0f, 10000.0f); + NNCASE_UNUSED auto res = kernels::stackvm::apply( + tensor.shape(), + [&](gsl::span index) -> result { + get(tensor, index) = static_cast(dis(gen)); + return ok(); + }); + break; + } + case dt_float32: { + std::random_device rd; + std::mt19937 gen(rd()); + std::uniform_real_distribution dis(-100000.0f, 100000.0f); + NNCASE_UNUSED auto res = kernels::stackvm::apply( + tensor.shape(), + [&](gsl::span index) -> result { + get(tensor, index) = static_cast(dis(gen)); + return ok(); + }); + break; + } + case dt_float64: { + std::random_device rd; + std::mt19937 gen(rd()); + std::uniform_real_distribution dis(-100000.0, 100000.0); + NNCASE_UNUSED auto res = kernels::stackvm::apply( + tensor.shape(), + [&](gsl::span index) -> result { + get(tensor, index) = static_cast(dis(gen)); + return ok(); + }); + break; + } + default: { + } + } + } + protected: runtime_tensor input; }; @@ -77,6 +223,8 @@ TEST_P(UnaryTest, cos) { cosine_similarity_tensor(expected, actual); if (!result) { + std::cout << "input "; + print_runtime_tensor(input); std::cout << "actual "; print_runtime_tensor(actual); std::cout << "expected "; diff --git a/tests/kernels/test_unary_cosh.cpp b/tests/kernels/test_unary_cosh.cpp index 57f097f3d2..3f70240ff6 100644 --- a/tests/kernels/test_unary_cosh.cpp +++ b/tests/kernels/test_unary_cosh.cpp @@ -45,6 +45,152 @@ class UnaryTest : public KernelTest, void TearDown() override { CLEAR_SUBCASE() } + void init_tensor(runtime_tensor &tensor) override { + auto dtype = tensor.datatype(); + switch (dtype) { + case dt_int8: { + std::random_device rd; + std::mt19937 gen(rd()); + std::uniform_int_distribution<> dis(-100000, 100000); + NNCASE_UNUSED auto res = kernels::stackvm::apply( + tensor.shape(), + [&](gsl::span index) -> result { + get(tensor, index) = static_cast(dis(gen)); + return ok(); + }); + break; + } + case dt_int16: { + std::random_device rd; + std::mt19937 gen(rd()); + std::uniform_int_distribution<> dis(-100000, 100000); + NNCASE_UNUSED auto res = kernels::stackvm::apply( + tensor.shape(), + [&](gsl::span index) -> result { + get(tensor, index) = + static_cast(dis(gen)); + return ok(); + }); + break; + } + case dt_int32: { + std::random_device rd; + std::mt19937 gen(rd()); + std::uniform_int_distribution<> dis(-100000, 100000); + NNCASE_UNUSED auto res = kernels::stackvm::apply( + tensor.shape(), + [&](gsl::span index) -> result { + get(tensor, index) = dis(gen); + return ok(); + }); + break; + } + case dt_int64: { + std::random_device rd; + std::mt19937 gen(rd()); + std::uniform_int_distribution<> dis(-100000, 100000); + NNCASE_UNUSED auto res = kernels::stackvm::apply( + tensor.shape(), + [&](gsl::span index) -> result { + get(tensor, index) = + static_cast(dis(gen)); + return ok(); + }); + break; + } + case dt_uint8: { + std::random_device rd; + std::mt19937 gen(rd()); + std::uniform_int_distribution<> dis(-100000, 100000); + NNCASE_UNUSED auto res = kernels::stackvm::apply( + tensor.shape(), + [&](gsl::span index) -> result { + get(tensor, index) = + static_cast(dis(gen)); + return ok(); + }); + break; + } + case dt_uint16: { + std::random_device rd; + std::mt19937 gen(rd()); + std::uniform_int_distribution<> dis(-100000, 100000); + NNCASE_UNUSED auto res = kernels::stackvm::apply( + tensor.shape(), + [&](gsl::span index) -> result { + get(tensor, index) = + static_cast(dis(gen)); + return ok(); + }); + break; + } + case dt_uint32: { + std::random_device rd; + std::mt19937 gen(rd()); + std::uniform_int_distribution<> dis(-100000, 100000); + NNCASE_UNUSED auto res = kernels::stackvm::apply( + tensor.shape(), + [&](gsl::span index) -> result { + get(tensor, index) = + static_cast(dis(gen)); + return ok(); + }); + break; + } + case dt_uint64: { + std::random_device rd; + std::mt19937 gen(rd()); + std::uniform_int_distribution dis(-100000, 100000); + NNCASE_UNUSED auto res = kernels::stackvm::apply( + tensor.shape(), + [&](gsl::span index) -> result { + get(tensor, index) = + static_cast(dis(gen)); + return ok(); + }); + break; + } + case dt_float16: { + std::random_device rd; + std::mt19937 gen(rd()); + std::uniform_real_distribution dis(-10000.0f, 10000.0f); + NNCASE_UNUSED auto res = kernels::stackvm::apply( + tensor.shape(), + [&](gsl::span index) -> result { + get(tensor, index) = static_cast(dis(gen)); + return ok(); + }); + break; + } + case dt_float32: { + std::random_device rd; + std::mt19937 gen(rd()); + std::uniform_real_distribution dis(-100000.0f, 100000.0f); + NNCASE_UNUSED auto res = kernels::stackvm::apply( + tensor.shape(), + [&](gsl::span index) -> result { + get(tensor, index) = static_cast(dis(gen)); + return ok(); + }); + break; + } + case dt_float64: { + std::random_device rd; + std::mt19937 gen(rd()); + std::uniform_real_distribution dis(-100000.0, 100000.0); + NNCASE_UNUSED auto res = kernels::stackvm::apply( + tensor.shape(), + [&](gsl::span index) -> result { + get(tensor, index) = static_cast(dis(gen)); + return ok(); + }); + break; + } + default: { + } + } + } + protected: runtime_tensor input; }; @@ -77,6 +223,8 @@ TEST_P(UnaryTest, cosh) { cosine_similarity_tensor(expected, actual); if (!result) { + std::cout << "input "; + print_runtime_tensor(input); std::cout << "actual "; print_runtime_tensor(actual); std::cout << "expected "; diff --git a/tests/kernels/test_unary_exp.cpp b/tests/kernels/test_unary_exp.cpp index bc825c453a..56dc7a6a08 100644 --- a/tests/kernels/test_unary_exp.cpp +++ b/tests/kernels/test_unary_exp.cpp @@ -45,6 +45,152 @@ class UnaryTest : public KernelTest, void TearDown() override { CLEAR_SUBCASE() } + void init_tensor(runtime_tensor &tensor) override { + auto dtype = tensor.datatype(); + switch (dtype) { + case dt_int8: { + std::random_device rd; + std::mt19937 gen(rd()); + std::uniform_int_distribution<> dis(-10, 10); + NNCASE_UNUSED auto res = kernels::stackvm::apply( + tensor.shape(), + [&](gsl::span index) -> result { + get(tensor, index) = static_cast(dis(gen)); + return ok(); + }); + break; + } + case dt_int16: { + std::random_device rd; + std::mt19937 gen(rd()); + std::uniform_int_distribution<> dis(-10, 10); + NNCASE_UNUSED auto res = kernels::stackvm::apply( + tensor.shape(), + [&](gsl::span index) -> result { + get(tensor, index) = + static_cast(dis(gen)); + return ok(); + }); + break; + } + case dt_int32: { + std::random_device rd; + std::mt19937 gen(rd()); + std::uniform_int_distribution<> dis(-10, 10); + NNCASE_UNUSED auto res = kernels::stackvm::apply( + tensor.shape(), + [&](gsl::span index) -> result { + get(tensor, index) = dis(gen); + return ok(); + }); + break; + } + case dt_int64: { + std::random_device rd; + std::mt19937 gen(rd()); + std::uniform_int_distribution<> dis(-10, 10); + NNCASE_UNUSED auto res = kernels::stackvm::apply( + tensor.shape(), + [&](gsl::span index) -> result { + get(tensor, index) = + static_cast(dis(gen)); + return ok(); + }); + break; + } + case dt_uint8: { + std::random_device rd; + std::mt19937 gen(rd()); + std::uniform_int_distribution<> dis(-10, 10); + NNCASE_UNUSED auto res = kernels::stackvm::apply( + tensor.shape(), + [&](gsl::span index) -> result { + get(tensor, index) = + static_cast(dis(gen)); + return ok(); + }); + break; + } + case dt_uint16: { + std::random_device rd; + std::mt19937 gen(rd()); + std::uniform_int_distribution<> dis(-10, 10); + NNCASE_UNUSED auto res = kernels::stackvm::apply( + tensor.shape(), + [&](gsl::span index) -> result { + get(tensor, index) = + static_cast(dis(gen)); + return ok(); + }); + break; + } + case dt_uint32: { + std::random_device rd; + std::mt19937 gen(rd()); + std::uniform_int_distribution<> dis(-10, 10); + NNCASE_UNUSED auto res = kernels::stackvm::apply( + tensor.shape(), + [&](gsl::span index) -> result { + get(tensor, index) = + static_cast(dis(gen)); + return ok(); + }); + break; + } + case dt_uint64: { + std::random_device rd; + std::mt19937 gen(rd()); + std::uniform_int_distribution dis(-10, 10); + NNCASE_UNUSED auto res = kernels::stackvm::apply( + tensor.shape(), + [&](gsl::span index) -> result { + get(tensor, index) = + static_cast(dis(gen)); + return ok(); + }); + break; + } + case dt_float16: { + std::random_device rd; + std::mt19937 gen(rd()); + std::uniform_real_distribution dis(-10.0f, 10.0f); + NNCASE_UNUSED auto res = kernels::stackvm::apply( + tensor.shape(), + [&](gsl::span index) -> result { + get(tensor, index) = static_cast(dis(gen)); + return ok(); + }); + break; + } + case dt_float32: { + std::random_device rd; + std::mt19937 gen(rd()); + std::uniform_real_distribution dis(-10.0f, 10.0f); + NNCASE_UNUSED auto res = kernels::stackvm::apply( + tensor.shape(), + [&](gsl::span index) -> result { + get(tensor, index) = static_cast(dis(gen)); + return ok(); + }); + break; + } + case dt_float64: { + std::random_device rd; + std::mt19937 gen(rd()); + std::uniform_real_distribution dis(-10.0, 10.0); + NNCASE_UNUSED auto res = kernels::stackvm::apply( + tensor.shape(), + [&](gsl::span index) -> result { + get(tensor, index) = static_cast(dis(gen)); + return ok(); + }); + break; + } + default: { + } + } + } + protected: runtime_tensor input; }; @@ -77,6 +223,8 @@ TEST_P(UnaryTest, exp) { cosine_similarity_tensor(expected, actual); if (!result) { + std::cout << "input "; + print_runtime_tensor(input); std::cout << "actual "; print_runtime_tensor(actual); std::cout << "expected "; diff --git a/tests/kernels/test_unary_floor.cpp b/tests/kernels/test_unary_floor.cpp index 7ec8b089a6..4151e24edb 100644 --- a/tests/kernels/test_unary_floor.cpp +++ b/tests/kernels/test_unary_floor.cpp @@ -45,6 +45,152 @@ class UnaryTest : public KernelTest, void TearDown() override { CLEAR_SUBCASE() } + void init_tensor(runtime_tensor &tensor) override { + auto dtype = tensor.datatype(); + switch (dtype) { + case dt_int8: { + std::random_device rd; + std::mt19937 gen(rd()); + std::uniform_int_distribution<> dis(-100000, 100000); + NNCASE_UNUSED auto res = kernels::stackvm::apply( + tensor.shape(), + [&](gsl::span index) -> result { + get(tensor, index) = static_cast(dis(gen)); + return ok(); + }); + break; + } + case dt_int16: { + std::random_device rd; + std::mt19937 gen(rd()); + std::uniform_int_distribution<> dis(-100000, 100000); + NNCASE_UNUSED auto res = kernels::stackvm::apply( + tensor.shape(), + [&](gsl::span index) -> result { + get(tensor, index) = + static_cast(dis(gen)); + return ok(); + }); + break; + } + case dt_int32: { + std::random_device rd; + std::mt19937 gen(rd()); + std::uniform_int_distribution<> dis(-100000, 100000); + NNCASE_UNUSED auto res = kernels::stackvm::apply( + tensor.shape(), + [&](gsl::span index) -> result { + get(tensor, index) = dis(gen); + return ok(); + }); + break; + } + case dt_int64: { + std::random_device rd; + std::mt19937 gen(rd()); + std::uniform_int_distribution<> dis(-100000, 100000); + NNCASE_UNUSED auto res = kernels::stackvm::apply( + tensor.shape(), + [&](gsl::span index) -> result { + get(tensor, index) = + static_cast(dis(gen)); + return ok(); + }); + break; + } + case dt_uint8: { + std::random_device rd; + std::mt19937 gen(rd()); + std::uniform_int_distribution<> dis(-100000, 100000); + NNCASE_UNUSED auto res = kernels::stackvm::apply( + tensor.shape(), + [&](gsl::span index) -> result { + get(tensor, index) = + static_cast(dis(gen)); + return ok(); + }); + break; + } + case dt_uint16: { + std::random_device rd; + std::mt19937 gen(rd()); + std::uniform_int_distribution<> dis(-100000, 100000); + NNCASE_UNUSED auto res = kernels::stackvm::apply( + tensor.shape(), + [&](gsl::span index) -> result { + get(tensor, index) = + static_cast(dis(gen)); + return ok(); + }); + break; + } + case dt_uint32: { + std::random_device rd; + std::mt19937 gen(rd()); + std::uniform_int_distribution<> dis(-100000, 100000); + NNCASE_UNUSED auto res = kernels::stackvm::apply( + tensor.shape(), + [&](gsl::span index) -> result { + get(tensor, index) = + static_cast(dis(gen)); + return ok(); + }); + break; + } + case dt_uint64: { + std::random_device rd; + std::mt19937 gen(rd()); + std::uniform_int_distribution dis(-100000, 100000); + NNCASE_UNUSED auto res = kernels::stackvm::apply( + tensor.shape(), + [&](gsl::span index) -> result { + get(tensor, index) = + static_cast(dis(gen)); + return ok(); + }); + break; + } + case dt_float16: { + std::random_device rd; + std::mt19937 gen(rd()); + std::uniform_real_distribution dis(-10000.0f, 10000.0f); + NNCASE_UNUSED auto res = kernels::stackvm::apply( + tensor.shape(), + [&](gsl::span index) -> result { + get(tensor, index) = static_cast(dis(gen)); + return ok(); + }); + break; + } + case dt_float32: { + std::random_device rd; + std::mt19937 gen(rd()); + std::uniform_real_distribution dis(-100000.0f, 100000.0f); + NNCASE_UNUSED auto res = kernels::stackvm::apply( + tensor.shape(), + [&](gsl::span index) -> result { + get(tensor, index) = static_cast(dis(gen)); + return ok(); + }); + break; + } + case dt_float64: { + std::random_device rd; + std::mt19937 gen(rd()); + std::uniform_real_distribution dis(-100000.0, 100000.0); + NNCASE_UNUSED auto res = kernels::stackvm::apply( + tensor.shape(), + [&](gsl::span index) -> result { + get(tensor, index) = static_cast(dis(gen)); + return ok(); + }); + break; + } + default: { + } + } + } + protected: runtime_tensor input; }; @@ -77,6 +223,8 @@ TEST_P(UnaryTest, floor) { cosine_similarity_tensor(expected, actual); if (!result) { + std::cout << "input "; + print_runtime_tensor(input); std::cout << "actual "; print_runtime_tensor(actual); std::cout << "expected "; diff --git a/tests/kernels/test_unary_log.cpp b/tests/kernels/test_unary_log.cpp index 65c0c4e50c..1380adfaf7 100644 --- a/tests/kernels/test_unary_log.cpp +++ b/tests/kernels/test_unary_log.cpp @@ -51,7 +51,7 @@ class UnaryTest : public KernelTest, case dt_int8: { std::random_device rd; std::mt19937 gen(rd()); - std::uniform_int_distribution<> dis(1, 6); + std::uniform_int_distribution<> dis(1, 100000); NNCASE_UNUSED auto res = kernels::stackvm::apply( tensor.shape(), [&](gsl::span index) -> result { @@ -63,7 +63,7 @@ class UnaryTest : public KernelTest, case dt_int16: { std::random_device rd; std::mt19937 gen(rd()); - std::uniform_int_distribution<> dis(1, 6); + std::uniform_int_distribution<> dis(1, 100000); NNCASE_UNUSED auto res = kernels::stackvm::apply( tensor.shape(), [&](gsl::span index) -> result { @@ -76,7 +76,7 @@ class UnaryTest : public KernelTest, case dt_int32: { std::random_device rd; std::mt19937 gen(rd()); - std::uniform_int_distribution<> dis(1, 6); + std::uniform_int_distribution<> dis(1, 100000); NNCASE_UNUSED auto res = kernels::stackvm::apply( tensor.shape(), [&](gsl::span index) -> result { @@ -88,7 +88,7 @@ class UnaryTest : public KernelTest, case dt_int64: { std::random_device rd; std::mt19937 gen(rd()); - std::uniform_int_distribution<> dis(1, 6); + std::uniform_int_distribution<> dis(1, 100000); NNCASE_UNUSED auto res = kernels::stackvm::apply( tensor.shape(), [&](gsl::span index) -> result { @@ -101,7 +101,7 @@ class UnaryTest : public KernelTest, case dt_uint8: { std::random_device rd; std::mt19937 gen(rd()); - std::uniform_int_distribution<> dis(1, 127); + std::uniform_int_distribution<> dis(1, 100000); NNCASE_UNUSED auto res = kernels::stackvm::apply( tensor.shape(), [&](gsl::span index) -> result { @@ -114,7 +114,7 @@ class UnaryTest : public KernelTest, case dt_uint16: { std::random_device rd; std::mt19937 gen(rd()); - std::uniform_int_distribution<> dis(1, 127); + std::uniform_int_distribution<> dis(1, 100000); NNCASE_UNUSED auto res = kernels::stackvm::apply( tensor.shape(), [&](gsl::span index) -> result { @@ -127,7 +127,7 @@ class UnaryTest : public KernelTest, case dt_uint32: { std::random_device rd; std::mt19937 gen(rd()); - std::uniform_int_distribution<> dis(1, 127); + std::uniform_int_distribution<> dis(1, 100000); NNCASE_UNUSED auto res = kernels::stackvm::apply( tensor.shape(), [&](gsl::span index) -> result { @@ -140,7 +140,7 @@ class UnaryTest : public KernelTest, case dt_uint64: { std::random_device rd; std::mt19937 gen(rd()); - std::uniform_int_distribution dis(1, 127); + std::uniform_int_distribution dis(1, 200000); NNCASE_UNUSED auto res = kernels::stackvm::apply( tensor.shape(), [&](gsl::span index) -> result { @@ -150,10 +150,22 @@ class UnaryTest : public KernelTest, }); break; } + case dt_float16: { + std::random_device rd; + std::mt19937 gen(rd()); + std::uniform_real_distribution dis(0.1f, 20000.0f); + NNCASE_UNUSED auto res = kernels::stackvm::apply( + tensor.shape(), + [&](gsl::span index) -> result { + get(tensor, index) = static_cast(dis(gen)); + return ok(); + }); + break; + } case dt_float32: { std::random_device rd; std::mt19937 gen(rd()); - std::uniform_real_distribution dis(1.0f, 2.0f); + std::uniform_real_distribution dis(0.1f, 200000.0f); NNCASE_UNUSED auto res = kernels::stackvm::apply( tensor.shape(), [&](gsl::span index) -> result { @@ -165,7 +177,7 @@ class UnaryTest : public KernelTest, case dt_float64: { std::random_device rd; std::mt19937 gen(rd()); - std::uniform_real_distribution dis(1.0, 2.0); + std::uniform_real_distribution dis(0.1f, 200000.0); NNCASE_UNUSED auto res = kernels::stackvm::apply( tensor.shape(), [&](gsl::span index) -> result { @@ -211,6 +223,8 @@ TEST_P(UnaryTest, log) { cosine_similarity_tensor(expected, actual); if (!result) { + std::cout << "input "; + print_runtime_tensor(input); std::cout << "actual "; print_runtime_tensor(actual); std::cout << "expected "; diff --git a/tests/kernels/test_unary_logical_not.cpp b/tests/kernels/test_unary_logical_not.cpp index 5b957079a1..ea8408b71c 100644 --- a/tests/kernels/test_unary_logical_not.cpp +++ b/tests/kernels/test_unary_logical_not.cpp @@ -45,6 +45,152 @@ class UnaryTest : public KernelTest, void TearDown() override { CLEAR_SUBCASE() } + void init_tensor(runtime_tensor &tensor) override { + auto dtype = tensor.datatype(); + switch (dtype) { + case dt_int8: { + std::random_device rd; + std::mt19937 gen(rd()); + std::uniform_int_distribution<> dis(-100000, 100000); + NNCASE_UNUSED auto res = kernels::stackvm::apply( + tensor.shape(), + [&](gsl::span index) -> result { + get(tensor, index) = static_cast(dis(gen)); + return ok(); + }); + break; + } + case dt_int16: { + std::random_device rd; + std::mt19937 gen(rd()); + std::uniform_int_distribution<> dis(-100000, 100000); + NNCASE_UNUSED auto res = kernels::stackvm::apply( + tensor.shape(), + [&](gsl::span index) -> result { + get(tensor, index) = + static_cast(dis(gen)); + return ok(); + }); + break; + } + case dt_int32: { + std::random_device rd; + std::mt19937 gen(rd()); + std::uniform_int_distribution<> dis(-100000, 100000); + NNCASE_UNUSED auto res = kernels::stackvm::apply( + tensor.shape(), + [&](gsl::span index) -> result { + get(tensor, index) = dis(gen); + return ok(); + }); + break; + } + case dt_int64: { + std::random_device rd; + std::mt19937 gen(rd()); + std::uniform_int_distribution<> dis(-100000, 100000); + NNCASE_UNUSED auto res = kernels::stackvm::apply( + tensor.shape(), + [&](gsl::span index) -> result { + get(tensor, index) = + static_cast(dis(gen)); + return ok(); + }); + break; + } + case dt_uint8: { + std::random_device rd; + std::mt19937 gen(rd()); + std::uniform_int_distribution<> dis(-100000, 100000); + NNCASE_UNUSED auto res = kernels::stackvm::apply( + tensor.shape(), + [&](gsl::span index) -> result { + get(tensor, index) = + static_cast(dis(gen)); + return ok(); + }); + break; + } + case dt_uint16: { + std::random_device rd; + std::mt19937 gen(rd()); + std::uniform_int_distribution<> dis(-100000, 100000); + NNCASE_UNUSED auto res = kernels::stackvm::apply( + tensor.shape(), + [&](gsl::span index) -> result { + get(tensor, index) = + static_cast(dis(gen)); + return ok(); + }); + break; + } + case dt_uint32: { + std::random_device rd; + std::mt19937 gen(rd()); + std::uniform_int_distribution<> dis(-100000, 100000); + NNCASE_UNUSED auto res = kernels::stackvm::apply( + tensor.shape(), + [&](gsl::span index) -> result { + get(tensor, index) = + static_cast(dis(gen)); + return ok(); + }); + break; + } + case dt_uint64: { + std::random_device rd; + std::mt19937 gen(rd()); + std::uniform_int_distribution dis(-100000, 100000); + NNCASE_UNUSED auto res = kernels::stackvm::apply( + tensor.shape(), + [&](gsl::span index) -> result { + get(tensor, index) = + static_cast(dis(gen)); + return ok(); + }); + break; + } + case dt_float16: { + std::random_device rd; + std::mt19937 gen(rd()); + std::uniform_real_distribution dis(-10000.0f, 10000.0f); + NNCASE_UNUSED auto res = kernels::stackvm::apply( + tensor.shape(), + [&](gsl::span index) -> result { + get(tensor, index) = static_cast(dis(gen)); + return ok(); + }); + break; + } + case dt_float32: { + std::random_device rd; + std::mt19937 gen(rd()); + std::uniform_real_distribution dis(-100000.0f, 100000.0f); + NNCASE_UNUSED auto res = kernels::stackvm::apply( + tensor.shape(), + [&](gsl::span index) -> result { + get(tensor, index) = static_cast(dis(gen)); + return ok(); + }); + break; + } + case dt_float64: { + std::random_device rd; + std::mt19937 gen(rd()); + std::uniform_real_distribution dis(-100000.0, 100000.0); + NNCASE_UNUSED auto res = kernels::stackvm::apply( + tensor.shape(), + [&](gsl::span index) -> result { + get(tensor, index) = static_cast(dis(gen)); + return ok(); + }); + break; + } + default: { + } + } + } + protected: runtime_tensor input; }; @@ -78,6 +224,8 @@ TEST_P(UnaryTest, logical_not) { cosine_similarity_tensor(expected, actual); if (!result) { + std::cout << "input "; + print_runtime_tensor(input); std::cout << "actual "; print_runtime_tensor(actual); std::cout << "expected "; diff --git a/tests/kernels/test_unary_neg.cpp b/tests/kernels/test_unary_neg.cpp index c8631001b3..b2282bba00 100644 --- a/tests/kernels/test_unary_neg.cpp +++ b/tests/kernels/test_unary_neg.cpp @@ -45,6 +45,152 @@ class UnaryTest : public KernelTest, void TearDown() override { CLEAR_SUBCASE() } + void init_tensor(runtime_tensor &tensor) override { + auto dtype = tensor.datatype(); + switch (dtype) { + case dt_int8: { + std::random_device rd; + std::mt19937 gen(rd()); + std::uniform_int_distribution<> dis(-100000, 100000); + NNCASE_UNUSED auto res = kernels::stackvm::apply( + tensor.shape(), + [&](gsl::span index) -> result { + get(tensor, index) = static_cast(dis(gen)); + return ok(); + }); + break; + } + case dt_int16: { + std::random_device rd; + std::mt19937 gen(rd()); + std::uniform_int_distribution<> dis(-100000, 100000); + NNCASE_UNUSED auto res = kernels::stackvm::apply( + tensor.shape(), + [&](gsl::span index) -> result { + get(tensor, index) = + static_cast(dis(gen)); + return ok(); + }); + break; + } + case dt_int32: { + std::random_device rd; + std::mt19937 gen(rd()); + std::uniform_int_distribution<> dis(-100000, 100000); + NNCASE_UNUSED auto res = kernels::stackvm::apply( + tensor.shape(), + [&](gsl::span index) -> result { + get(tensor, index) = dis(gen); + return ok(); + }); + break; + } + case dt_int64: { + std::random_device rd; + std::mt19937 gen(rd()); + std::uniform_int_distribution<> dis(-100000, 100000); + NNCASE_UNUSED auto res = kernels::stackvm::apply( + tensor.shape(), + [&](gsl::span index) -> result { + get(tensor, index) = + static_cast(dis(gen)); + return ok(); + }); + break; + } + case dt_uint8: { + std::random_device rd; + std::mt19937 gen(rd()); + std::uniform_int_distribution<> dis(-100000, 100000); + NNCASE_UNUSED auto res = kernels::stackvm::apply( + tensor.shape(), + [&](gsl::span index) -> result { + get(tensor, index) = + static_cast(dis(gen)); + return ok(); + }); + break; + } + case dt_uint16: { + std::random_device rd; + std::mt19937 gen(rd()); + std::uniform_int_distribution<> dis(-100000, 100000); + NNCASE_UNUSED auto res = kernels::stackvm::apply( + tensor.shape(), + [&](gsl::span index) -> result { + get(tensor, index) = + static_cast(dis(gen)); + return ok(); + }); + break; + } + case dt_uint32: { + std::random_device rd; + std::mt19937 gen(rd()); + std::uniform_int_distribution<> dis(-100000, 100000); + NNCASE_UNUSED auto res = kernels::stackvm::apply( + tensor.shape(), + [&](gsl::span index) -> result { + get(tensor, index) = + static_cast(dis(gen)); + return ok(); + }); + break; + } + case dt_uint64: { + std::random_device rd; + std::mt19937 gen(rd()); + std::uniform_int_distribution dis(-100000, 100000); + NNCASE_UNUSED auto res = kernels::stackvm::apply( + tensor.shape(), + [&](gsl::span index) -> result { + get(tensor, index) = + static_cast(dis(gen)); + return ok(); + }); + break; + } + case dt_float16: { + std::random_device rd; + std::mt19937 gen(rd()); + std::uniform_real_distribution dis(-10000.0f, 10000.0f); + NNCASE_UNUSED auto res = kernels::stackvm::apply( + tensor.shape(), + [&](gsl::span index) -> result { + get(tensor, index) = static_cast(dis(gen)); + return ok(); + }); + break; + } + case dt_float32: { + std::random_device rd; + std::mt19937 gen(rd()); + std::uniform_real_distribution dis(-100000.0f, 100000.0f); + NNCASE_UNUSED auto res = kernels::stackvm::apply( + tensor.shape(), + [&](gsl::span index) -> result { + get(tensor, index) = static_cast(dis(gen)); + return ok(); + }); + break; + } + case dt_float64: { + std::random_device rd; + std::mt19937 gen(rd()); + std::uniform_real_distribution dis(-100000.0, 100000.0); + NNCASE_UNUSED auto res = kernels::stackvm::apply( + tensor.shape(), + [&](gsl::span index) -> result { + get(tensor, index) = static_cast(dis(gen)); + return ok(); + }); + break; + } + default: { + } + } + } + protected: runtime_tensor input; }; @@ -77,6 +223,8 @@ TEST_P(UnaryTest, neg) { cosine_similarity_tensor(expected, actual); if (!result) { + std::cout << "input "; + print_runtime_tensor(input); std::cout << "actual "; print_runtime_tensor(actual); std::cout << "expected "; diff --git a/tests/kernels/test_unary_other_type.json b/tests/kernels/test_unary_other_type.json index 5b84555925..fbb23995e4 100644 --- a/tests/kernels/test_unary_other_type.json +++ b/tests/kernels/test_unary_other_type.json @@ -1,4 +1,4 @@ { - "i_shape":[[1, 3, 16, 16], [3, 16, 16], [3, 16, 1], [16, 16], [16, 1], [1, 16, 1], [16], [1], []], + "i_shape":[[1, 3, 16, 16], [3, 16, 16], [3, 16, 1], [16, 16], [16, 1], [1, 16, 1], [16], [1], [], [1, 30, 288, 288], [1, 30, 288], [288, 288], [288]], "other_type": ["dt_float32", "dt_float16"] } \ No newline at end of file diff --git a/tests/kernels/test_unary_other_type1.json b/tests/kernels/test_unary_other_type1.json index ce8779a683..578e8812ec 100644 --- a/tests/kernels/test_unary_other_type1.json +++ b/tests/kernels/test_unary_other_type1.json @@ -1,4 +1,4 @@ { - "i_shape":[[1, 3, 16, 16], [3, 16, 16], [3, 16, 1], [16, 16], [16, 1], [1, 16, 1], [16], [1], []], + "i_shape":[[1, 3, 16, 16], [3, 16, 16], [3, 16, 1], [16, 16], [16, 1], [1, 16, 1], [16], [1], [], [1, 30, 288, 288], [1, 30, 288], [288, 288], [288]], "other_type": ["dt_float32", "dt_float16", "dt_float64"] } \ No newline at end of file diff --git a/tests/kernels/test_unary_other_type2.json b/tests/kernels/test_unary_other_type2.json index fa8b0fed1b..0b6e52c3e2 100644 --- a/tests/kernels/test_unary_other_type2.json +++ b/tests/kernels/test_unary_other_type2.json @@ -1,4 +1,4 @@ { - "i_shape":[[1, 3, 16, 16], [3, 16, 16], [3, 16, 1], [16, 16], [16, 1], [1, 16, 1], [16], [1], []], + "i_shape":[[1, 3, 16, 16], [3, 16, 16], [3, 16, 1], [16, 16], [16, 1], [1, 16, 1], [16], [1], [], [1, 30, 288, 288], [1, 30, 288], [288, 288], [288]], "other_type": ["dt_boolean"] } \ No newline at end of file diff --git a/tests/kernels/test_unary_round.cpp b/tests/kernels/test_unary_round.cpp index b5ab62aa01..83208fd063 100644 --- a/tests/kernels/test_unary_round.cpp +++ b/tests/kernels/test_unary_round.cpp @@ -45,6 +45,152 @@ class UnaryTest : public KernelTest, void TearDown() override { CLEAR_SUBCASE() } + void init_tensor(runtime_tensor &tensor) override { + auto dtype = tensor.datatype(); + switch (dtype) { + case dt_int8: { + std::random_device rd; + std::mt19937 gen(rd()); + std::uniform_int_distribution<> dis(-100000, 100000); + NNCASE_UNUSED auto res = kernels::stackvm::apply( + tensor.shape(), + [&](gsl::span index) -> result { + get(tensor, index) = static_cast(dis(gen)); + return ok(); + }); + break; + } + case dt_int16: { + std::random_device rd; + std::mt19937 gen(rd()); + std::uniform_int_distribution<> dis(-100000, 100000); + NNCASE_UNUSED auto res = kernels::stackvm::apply( + tensor.shape(), + [&](gsl::span index) -> result { + get(tensor, index) = + static_cast(dis(gen)); + return ok(); + }); + break; + } + case dt_int32: { + std::random_device rd; + std::mt19937 gen(rd()); + std::uniform_int_distribution<> dis(-100000, 100000); + NNCASE_UNUSED auto res = kernels::stackvm::apply( + tensor.shape(), + [&](gsl::span index) -> result { + get(tensor, index) = dis(gen); + return ok(); + }); + break; + } + case dt_int64: { + std::random_device rd; + std::mt19937 gen(rd()); + std::uniform_int_distribution<> dis(-100000, 100000); + NNCASE_UNUSED auto res = kernels::stackvm::apply( + tensor.shape(), + [&](gsl::span index) -> result { + get(tensor, index) = + static_cast(dis(gen)); + return ok(); + }); + break; + } + case dt_uint8: { + std::random_device rd; + std::mt19937 gen(rd()); + std::uniform_int_distribution<> dis(-100000, 100000); + NNCASE_UNUSED auto res = kernels::stackvm::apply( + tensor.shape(), + [&](gsl::span index) -> result { + get(tensor, index) = + static_cast(dis(gen)); + return ok(); + }); + break; + } + case dt_uint16: { + std::random_device rd; + std::mt19937 gen(rd()); + std::uniform_int_distribution<> dis(-100000, 100000); + NNCASE_UNUSED auto res = kernels::stackvm::apply( + tensor.shape(), + [&](gsl::span index) -> result { + get(tensor, index) = + static_cast(dis(gen)); + return ok(); + }); + break; + } + case dt_uint32: { + std::random_device rd; + std::mt19937 gen(rd()); + std::uniform_int_distribution<> dis(-100000, 100000); + NNCASE_UNUSED auto res = kernels::stackvm::apply( + tensor.shape(), + [&](gsl::span index) -> result { + get(tensor, index) = + static_cast(dis(gen)); + return ok(); + }); + break; + } + case dt_uint64: { + std::random_device rd; + std::mt19937 gen(rd()); + std::uniform_int_distribution dis(-100000, 100000); + NNCASE_UNUSED auto res = kernels::stackvm::apply( + tensor.shape(), + [&](gsl::span index) -> result { + get(tensor, index) = + static_cast(dis(gen)); + return ok(); + }); + break; + } + case dt_float16: { + std::random_device rd; + std::mt19937 gen(rd()); + std::uniform_real_distribution dis(-10000.0f, 10000.0f); + NNCASE_UNUSED auto res = kernels::stackvm::apply( + tensor.shape(), + [&](gsl::span index) -> result { + get(tensor, index) = static_cast(dis(gen)); + return ok(); + }); + break; + } + case dt_float32: { + std::random_device rd; + std::mt19937 gen(rd()); + std::uniform_real_distribution dis(-100000.0f, 100000.0f); + NNCASE_UNUSED auto res = kernels::stackvm::apply( + tensor.shape(), + [&](gsl::span index) -> result { + get(tensor, index) = static_cast(dis(gen)); + return ok(); + }); + break; + } + case dt_float64: { + std::random_device rd; + std::mt19937 gen(rd()); + std::uniform_real_distribution dis(-100000.0, 100000.0); + NNCASE_UNUSED auto res = kernels::stackvm::apply( + tensor.shape(), + [&](gsl::span index) -> result { + get(tensor, index) = static_cast(dis(gen)); + return ok(); + }); + break; + } + default: { + } + } + } + protected: runtime_tensor input; }; @@ -77,6 +223,7 @@ TEST_P(UnaryTest, round) { cosine_similarity_tensor(expected, actual); if (!result) { + std::cout << "input "; print_runtime_tensor(input); std::cout << "actual "; print_runtime_tensor(actual); diff --git a/tests/kernels/test_unary_rsqrt.cpp b/tests/kernels/test_unary_rsqrt.cpp index aa7fdd7d59..80c5e9fdfe 100644 --- a/tests/kernels/test_unary_rsqrt.cpp +++ b/tests/kernels/test_unary_rsqrt.cpp @@ -51,7 +51,7 @@ class UnaryTest : public KernelTest, case dt_int8: { std::random_device rd; std::mt19937 gen(rd()); - std::uniform_int_distribution<> dis(1, 6); + std::uniform_int_distribution<> dis(1, 200000); NNCASE_UNUSED auto res = kernels::stackvm::apply( tensor.shape(), [&](gsl::span index) -> result { @@ -63,7 +63,7 @@ class UnaryTest : public KernelTest, case dt_int16: { std::random_device rd; std::mt19937 gen(rd()); - std::uniform_int_distribution<> dis(1, 6); + std::uniform_int_distribution<> dis(1, 200000); NNCASE_UNUSED auto res = kernels::stackvm::apply( tensor.shape(), [&](gsl::span index) -> result { @@ -76,7 +76,7 @@ class UnaryTest : public KernelTest, case dt_int32: { std::random_device rd; std::mt19937 gen(rd()); - std::uniform_int_distribution<> dis(1, 6); + std::uniform_int_distribution<> dis(1, 200000); NNCASE_UNUSED auto res = kernels::stackvm::apply( tensor.shape(), [&](gsl::span index) -> result { @@ -88,7 +88,7 @@ class UnaryTest : public KernelTest, case dt_int64: { std::random_device rd; std::mt19937 gen(rd()); - std::uniform_int_distribution<> dis(1, 6); + std::uniform_int_distribution<> dis(1, 200000); NNCASE_UNUSED auto res = kernels::stackvm::apply( tensor.shape(), [&](gsl::span index) -> result { @@ -101,7 +101,7 @@ class UnaryTest : public KernelTest, case dt_uint8: { std::random_device rd; std::mt19937 gen(rd()); - std::uniform_int_distribution<> dis(1, 127); + std::uniform_int_distribution<> dis(1, 200000); NNCASE_UNUSED auto res = kernels::stackvm::apply( tensor.shape(), [&](gsl::span index) -> result { @@ -114,7 +114,7 @@ class UnaryTest : public KernelTest, case dt_uint16: { std::random_device rd; std::mt19937 gen(rd()); - std::uniform_int_distribution<> dis(1, 127); + std::uniform_int_distribution<> dis(1, 200000); NNCASE_UNUSED auto res = kernels::stackvm::apply( tensor.shape(), [&](gsl::span index) -> result { @@ -127,7 +127,7 @@ class UnaryTest : public KernelTest, case dt_uint32: { std::random_device rd; std::mt19937 gen(rd()); - std::uniform_int_distribution<> dis(1, 127); + std::uniform_int_distribution<> dis(100000, 200000); NNCASE_UNUSED auto res = kernels::stackvm::apply( tensor.shape(), [&](gsl::span index) -> result { @@ -140,7 +140,7 @@ class UnaryTest : public KernelTest, case dt_uint64: { std::random_device rd; std::mt19937 gen(rd()); - std::uniform_int_distribution dis(1, 127); + std::uniform_int_distribution dis(100000, 200000); NNCASE_UNUSED auto res = kernels::stackvm::apply( tensor.shape(), [&](gsl::span index) -> result { @@ -153,7 +153,7 @@ class UnaryTest : public KernelTest, case dt_float32: { std::random_device rd; std::mt19937 gen(rd()); - std::uniform_real_distribution dis(1.0f, 2.0f); + std::uniform_real_distribution dis(1.0f, 200000.0f); NNCASE_UNUSED auto res = kernels::stackvm::apply( tensor.shape(), [&](gsl::span index) -> result { @@ -165,7 +165,7 @@ class UnaryTest : public KernelTest, case dt_float16: { std::random_device rd; std::mt19937 gen(rd()); - std::uniform_real_distribution dis(1.0f, 2.0f); + std::uniform_real_distribution dis(1.0f, 20000.0f); NNCASE_UNUSED auto res = kernels::stackvm::apply( tensor.shape(), [&](gsl::span index) -> result { @@ -177,7 +177,7 @@ class UnaryTest : public KernelTest, case dt_float64: { std::random_device rd; std::mt19937 gen(rd()); - std::uniform_real_distribution dis(1.0, 2.0); + std::uniform_real_distribution dis(1.0, 200000.0); NNCASE_UNUSED auto res = kernels::stackvm::apply( tensor.shape(), [&](gsl::span index) -> result { @@ -242,6 +242,7 @@ TEST_P(UnaryTest, rsqrt) { cosine_similarity_tensor(expected, actual); if (!result) { + std::cout << "input "; print_runtime_tensor(input); std::cout << "actual "; print_runtime_tensor(actual); diff --git a/tests/kernels/test_unary_sign.cpp b/tests/kernels/test_unary_sign.cpp index 100178a35d..eda3180f8b 100644 --- a/tests/kernels/test_unary_sign.cpp +++ b/tests/kernels/test_unary_sign.cpp @@ -45,6 +45,152 @@ class UnaryTest : public KernelTest, void TearDown() override { CLEAR_SUBCASE() } + void init_tensor(runtime_tensor &tensor) override { + auto dtype = tensor.datatype(); + switch (dtype) { + case dt_int8: { + std::random_device rd; + std::mt19937 gen(rd()); + std::uniform_int_distribution<> dis(-100000, 100000); + NNCASE_UNUSED auto res = kernels::stackvm::apply( + tensor.shape(), + [&](gsl::span index) -> result { + get(tensor, index) = static_cast(dis(gen)); + return ok(); + }); + break; + } + case dt_int16: { + std::random_device rd; + std::mt19937 gen(rd()); + std::uniform_int_distribution<> dis(-100000, 100000); + NNCASE_UNUSED auto res = kernels::stackvm::apply( + tensor.shape(), + [&](gsl::span index) -> result { + get(tensor, index) = + static_cast(dis(gen)); + return ok(); + }); + break; + } + case dt_int32: { + std::random_device rd; + std::mt19937 gen(rd()); + std::uniform_int_distribution<> dis(-100000, 100000); + NNCASE_UNUSED auto res = kernels::stackvm::apply( + tensor.shape(), + [&](gsl::span index) -> result { + get(tensor, index) = dis(gen); + return ok(); + }); + break; + } + case dt_int64: { + std::random_device rd; + std::mt19937 gen(rd()); + std::uniform_int_distribution<> dis(-100000, 100000); + NNCASE_UNUSED auto res = kernels::stackvm::apply( + tensor.shape(), + [&](gsl::span index) -> result { + get(tensor, index) = + static_cast(dis(gen)); + return ok(); + }); + break; + } + case dt_uint8: { + std::random_device rd; + std::mt19937 gen(rd()); + std::uniform_int_distribution<> dis(-100000, 100000); + NNCASE_UNUSED auto res = kernels::stackvm::apply( + tensor.shape(), + [&](gsl::span index) -> result { + get(tensor, index) = + static_cast(dis(gen)); + return ok(); + }); + break; + } + case dt_uint16: { + std::random_device rd; + std::mt19937 gen(rd()); + std::uniform_int_distribution<> dis(-100000, 100000); + NNCASE_UNUSED auto res = kernels::stackvm::apply( + tensor.shape(), + [&](gsl::span index) -> result { + get(tensor, index) = + static_cast(dis(gen)); + return ok(); + }); + break; + } + case dt_uint32: { + std::random_device rd; + std::mt19937 gen(rd()); + std::uniform_int_distribution<> dis(-100000, 100000); + NNCASE_UNUSED auto res = kernels::stackvm::apply( + tensor.shape(), + [&](gsl::span index) -> result { + get(tensor, index) = + static_cast(dis(gen)); + return ok(); + }); + break; + } + case dt_uint64: { + std::random_device rd; + std::mt19937 gen(rd()); + std::uniform_int_distribution dis(-100000, 100000); + NNCASE_UNUSED auto res = kernels::stackvm::apply( + tensor.shape(), + [&](gsl::span index) -> result { + get(tensor, index) = + static_cast(dis(gen)); + return ok(); + }); + break; + } + case dt_float16: { + std::random_device rd; + std::mt19937 gen(rd()); + std::uniform_real_distribution dis(-10000.0f, 10000.0f); + NNCASE_UNUSED auto res = kernels::stackvm::apply( + tensor.shape(), + [&](gsl::span index) -> result { + get(tensor, index) = static_cast(dis(gen)); + return ok(); + }); + break; + } + case dt_float32: { + std::random_device rd; + std::mt19937 gen(rd()); + std::uniform_real_distribution dis(-100000.0f, 100000.0f); + NNCASE_UNUSED auto res = kernels::stackvm::apply( + tensor.shape(), + [&](gsl::span index) -> result { + get(tensor, index) = static_cast(dis(gen)); + return ok(); + }); + break; + } + case dt_float64: { + std::random_device rd; + std::mt19937 gen(rd()); + std::uniform_real_distribution dis(-100000.0, 100000.0); + NNCASE_UNUSED auto res = kernels::stackvm::apply( + tensor.shape(), + [&](gsl::span index) -> result { + get(tensor, index) = static_cast(dis(gen)); + return ok(); + }); + break; + } + default: { + } + } + } + protected: runtime_tensor input; }; @@ -77,6 +223,8 @@ TEST_P(UnaryTest, sign) { cosine_similarity_tensor(expected, actual); if (!result) { + std::cout << "input "; + print_runtime_tensor(input); std::cout << "actual "; print_runtime_tensor(actual); std::cout << "expected "; diff --git a/tests/kernels/test_unary_sin.cpp b/tests/kernels/test_unary_sin.cpp index 61cf2d165c..4408b31713 100644 --- a/tests/kernels/test_unary_sin.cpp +++ b/tests/kernels/test_unary_sin.cpp @@ -45,6 +45,152 @@ class UnaryTest : public KernelTest, void TearDown() override { CLEAR_SUBCASE() } + void init_tensor(runtime_tensor &tensor) override { + auto dtype = tensor.datatype(); + switch (dtype) { + case dt_int8: { + std::random_device rd; + std::mt19937 gen(rd()); + std::uniform_int_distribution<> dis(-100000, 100000); + NNCASE_UNUSED auto res = kernels::stackvm::apply( + tensor.shape(), + [&](gsl::span index) -> result { + get(tensor, index) = static_cast(dis(gen)); + return ok(); + }); + break; + } + case dt_int16: { + std::random_device rd; + std::mt19937 gen(rd()); + std::uniform_int_distribution<> dis(-100000, 100000); + NNCASE_UNUSED auto res = kernels::stackvm::apply( + tensor.shape(), + [&](gsl::span index) -> result { + get(tensor, index) = + static_cast(dis(gen)); + return ok(); + }); + break; + } + case dt_int32: { + std::random_device rd; + std::mt19937 gen(rd()); + std::uniform_int_distribution<> dis(-100000, 100000); + NNCASE_UNUSED auto res = kernels::stackvm::apply( + tensor.shape(), + [&](gsl::span index) -> result { + get(tensor, index) = dis(gen); + return ok(); + }); + break; + } + case dt_int64: { + std::random_device rd; + std::mt19937 gen(rd()); + std::uniform_int_distribution<> dis(-100000, 100000); + NNCASE_UNUSED auto res = kernels::stackvm::apply( + tensor.shape(), + [&](gsl::span index) -> result { + get(tensor, index) = + static_cast(dis(gen)); + return ok(); + }); + break; + } + case dt_uint8: { + std::random_device rd; + std::mt19937 gen(rd()); + std::uniform_int_distribution<> dis(-100000, 100000); + NNCASE_UNUSED auto res = kernels::stackvm::apply( + tensor.shape(), + [&](gsl::span index) -> result { + get(tensor, index) = + static_cast(dis(gen)); + return ok(); + }); + break; + } + case dt_uint16: { + std::random_device rd; + std::mt19937 gen(rd()); + std::uniform_int_distribution<> dis(-100000, 100000); + NNCASE_UNUSED auto res = kernels::stackvm::apply( + tensor.shape(), + [&](gsl::span index) -> result { + get(tensor, index) = + static_cast(dis(gen)); + return ok(); + }); + break; + } + case dt_uint32: { + std::random_device rd; + std::mt19937 gen(rd()); + std::uniform_int_distribution<> dis(-100000, 100000); + NNCASE_UNUSED auto res = kernels::stackvm::apply( + tensor.shape(), + [&](gsl::span index) -> result { + get(tensor, index) = + static_cast(dis(gen)); + return ok(); + }); + break; + } + case dt_uint64: { + std::random_device rd; + std::mt19937 gen(rd()); + std::uniform_int_distribution dis(-100000, 100000); + NNCASE_UNUSED auto res = kernels::stackvm::apply( + tensor.shape(), + [&](gsl::span index) -> result { + get(tensor, index) = + static_cast(dis(gen)); + return ok(); + }); + break; + } + case dt_float16: { + std::random_device rd; + std::mt19937 gen(rd()); + std::uniform_real_distribution dis(-10000.0f, 10000.0f); + NNCASE_UNUSED auto res = kernels::stackvm::apply( + tensor.shape(), + [&](gsl::span index) -> result { + get(tensor, index) = static_cast(dis(gen)); + return ok(); + }); + break; + } + case dt_float32: { + std::random_device rd; + std::mt19937 gen(rd()); + std::uniform_real_distribution dis(-100000.0f, 100000.0f); + NNCASE_UNUSED auto res = kernels::stackvm::apply( + tensor.shape(), + [&](gsl::span index) -> result { + get(tensor, index) = static_cast(dis(gen)); + return ok(); + }); + break; + } + case dt_float64: { + std::random_device rd; + std::mt19937 gen(rd()); + std::uniform_real_distribution dis(-100000.0, 100000.0); + NNCASE_UNUSED auto res = kernels::stackvm::apply( + tensor.shape(), + [&](gsl::span index) -> result { + get(tensor, index) = static_cast(dis(gen)); + return ok(); + }); + break; + } + default: { + } + } + } + protected: runtime_tensor input; }; @@ -77,6 +223,8 @@ TEST_P(UnaryTest, sin) { cosine_similarity_tensor(expected, actual); if (!result) { + std::cout << "input "; + print_runtime_tensor(input); std::cout << "actual "; print_runtime_tensor(actual); std::cout << "expected "; diff --git a/tests/kernels/test_unary_sinh.cpp b/tests/kernels/test_unary_sinh.cpp index a7c3c1b6d5..f45c515df4 100644 --- a/tests/kernels/test_unary_sinh.cpp +++ b/tests/kernels/test_unary_sinh.cpp @@ -45,6 +45,152 @@ class UnaryTest : public KernelTest, void TearDown() override { CLEAR_SUBCASE() } + void init_tensor(runtime_tensor &tensor) override { + auto dtype = tensor.datatype(); + switch (dtype) { + case dt_int8: { + std::random_device rd; + std::mt19937 gen(rd()); + std::uniform_int_distribution<> dis(-100000, 100000); + NNCASE_UNUSED auto res = kernels::stackvm::apply( + tensor.shape(), + [&](gsl::span index) -> result { + get(tensor, index) = static_cast(dis(gen)); + return ok(); + }); + break; + } + case dt_int16: { + std::random_device rd; + std::mt19937 gen(rd()); + std::uniform_int_distribution<> dis(-100000, 100000); + NNCASE_UNUSED auto res = kernels::stackvm::apply( + tensor.shape(), + [&](gsl::span index) -> result { + get(tensor, index) = + static_cast(dis(gen)); + return ok(); + }); + break; + } + case dt_int32: { + std::random_device rd; + std::mt19937 gen(rd()); + std::uniform_int_distribution<> dis(-100000, 100000); + NNCASE_UNUSED auto res = kernels::stackvm::apply( + tensor.shape(), + [&](gsl::span index) -> result { + get(tensor, index) = dis(gen); + return ok(); + }); + break; + } + case dt_int64: { + std::random_device rd; + std::mt19937 gen(rd()); + std::uniform_int_distribution<> dis(-100000, 100000); + NNCASE_UNUSED auto res = kernels::stackvm::apply( + tensor.shape(), + [&](gsl::span index) -> result { + get(tensor, index) = + static_cast(dis(gen)); + return ok(); + }); + break; + } + case dt_uint8: { + std::random_device rd; + std::mt19937 gen(rd()); + std::uniform_int_distribution<> dis(-100000, 100000); + NNCASE_UNUSED auto res = kernels::stackvm::apply( + tensor.shape(), + [&](gsl::span index) -> result { + get(tensor, index) = + static_cast(dis(gen)); + return ok(); + }); + break; + } + case dt_uint16: { + std::random_device rd; + std::mt19937 gen(rd()); + std::uniform_int_distribution<> dis(-100000, 100000); + NNCASE_UNUSED auto res = kernels::stackvm::apply( + tensor.shape(), + [&](gsl::span index) -> result { + get(tensor, index) = + static_cast(dis(gen)); + return ok(); + }); + break; + } + case dt_uint32: { + std::random_device rd; + std::mt19937 gen(rd()); + std::uniform_int_distribution<> dis(-100000, 100000); + NNCASE_UNUSED auto res = kernels::stackvm::apply( + tensor.shape(), + [&](gsl::span index) -> result { + get(tensor, index) = + static_cast(dis(gen)); + return ok(); + }); + break; + } + case dt_uint64: { + std::random_device rd; + std::mt19937 gen(rd()); + std::uniform_int_distribution dis(-100000, 100000); + NNCASE_UNUSED auto res = kernels::stackvm::apply( + tensor.shape(), + [&](gsl::span index) -> result { + get(tensor, index) = + static_cast(dis(gen)); + return ok(); + }); + break; + } + case dt_float16: { + std::random_device rd; + std::mt19937 gen(rd()); + std::uniform_real_distribution dis(-10000.0f, 10000.0f); + NNCASE_UNUSED auto res = kernels::stackvm::apply( + tensor.shape(), + [&](gsl::span index) -> result { + get(tensor, index) = static_cast(dis(gen)); + return ok(); + }); + break; + } + case dt_float32: { + std::random_device rd; + std::mt19937 gen(rd()); + std::uniform_real_distribution dis(-100000.0f, 100000.0f); + NNCASE_UNUSED auto res = kernels::stackvm::apply( + tensor.shape(), + [&](gsl::span index) -> result { + get(tensor, index) = static_cast(dis(gen)); + return ok(); + }); + break; + } + case dt_float64: { + std::random_device rd; + std::mt19937 gen(rd()); + std::uniform_real_distribution dis(-100000.0, 100000.0); + NNCASE_UNUSED auto res = kernels::stackvm::apply( + tensor.shape(), + [&](gsl::span index) -> result { + get(tensor, index) = static_cast(dis(gen)); + return ok(); + }); + break; + } + default: { + } + } + } + protected: runtime_tensor input; }; @@ -77,6 +223,8 @@ TEST_P(UnaryTest, sin) { cosine_similarity_tensor(expected, actual); if (!result) { + std::cout << "input "; + print_runtime_tensor(input); std::cout << "actual "; print_runtime_tensor(actual); std::cout << "expected "; diff --git a/tests/kernels/test_unary_sqrt.cpp b/tests/kernels/test_unary_sqrt.cpp index d0f19a3e23..24a313438a 100644 --- a/tests/kernels/test_unary_sqrt.cpp +++ b/tests/kernels/test_unary_sqrt.cpp @@ -49,7 +49,7 @@ class UnaryTest : public KernelTest, case dt_int8: { std::random_device rd; std::mt19937 gen(rd()); - std::uniform_int_distribution<> dis(1, 6); + std::uniform_int_distribution<> dis(0, 100000); NNCASE_UNUSED auto res = kernels::stackvm::apply( tensor.shape(), [&](gsl::span index) -> result { @@ -61,7 +61,7 @@ class UnaryTest : public KernelTest, case dt_int16: { std::random_device rd; std::mt19937 gen(rd()); - std::uniform_int_distribution<> dis(1, 6); + std::uniform_int_distribution<> dis(0, 100000); NNCASE_UNUSED auto res = kernels::stackvm::apply( tensor.shape(), [&](gsl::span index) -> result { @@ -74,7 +74,7 @@ class UnaryTest : public KernelTest, case dt_int32: { std::random_device rd; std::mt19937 gen(rd()); - std::uniform_int_distribution<> dis(1, 6); + std::uniform_int_distribution<> dis(0, 100000); NNCASE_UNUSED auto res = kernels::stackvm::apply( tensor.shape(), [&](gsl::span index) -> result { @@ -86,7 +86,7 @@ class UnaryTest : public KernelTest, case dt_int64: { std::random_device rd; std::mt19937 gen(rd()); - std::uniform_int_distribution<> dis(1, 6); + std::uniform_int_distribution<> dis(0, 100000); NNCASE_UNUSED auto res = kernels::stackvm::apply( tensor.shape(), [&](gsl::span index) -> result { @@ -99,7 +99,7 @@ class UnaryTest : public KernelTest, case dt_uint8: { std::random_device rd; std::mt19937 gen(rd()); - std::uniform_int_distribution<> dis(1, 127); + std::uniform_int_distribution<> dis(0, 100000); NNCASE_UNUSED auto res = kernels::stackvm::apply( tensor.shape(), [&](gsl::span index) -> result { @@ -112,7 +112,7 @@ class UnaryTest : public KernelTest, case dt_uint16: { std::random_device rd; std::mt19937 gen(rd()); - std::uniform_int_distribution<> dis(1, 127); + std::uniform_int_distribution<> dis(0, 100000); NNCASE_UNUSED auto res = kernels::stackvm::apply( tensor.shape(), [&](gsl::span index) -> result { @@ -125,7 +125,7 @@ class UnaryTest : public KernelTest, case dt_uint32: { std::random_device rd; std::mt19937 gen(rd()); - std::uniform_int_distribution<> dis(1, 127); + std::uniform_int_distribution<> dis(0, 100000); NNCASE_UNUSED auto res = kernels::stackvm::apply( tensor.shape(), [&](gsl::span index) -> result { @@ -138,7 +138,7 @@ class UnaryTest : public KernelTest, case dt_uint64: { std::random_device rd; std::mt19937 gen(rd()); - std::uniform_int_distribution dis(1, 127); + std::uniform_int_distribution dis(0, 100000); NNCASE_UNUSED auto res = kernels::stackvm::apply( tensor.shape(), [&](gsl::span index) -> result { @@ -148,10 +148,22 @@ class UnaryTest : public KernelTest, }); break; } + case dt_float16: { + std::random_device rd; + std::mt19937 gen(rd()); + std::uniform_real_distribution dis(0.0f, 10000.0f); + NNCASE_UNUSED auto res = kernels::stackvm::apply( + tensor.shape(), + [&](gsl::span index) -> result { + get(tensor, index) = static_cast(dis(gen)); + return ok(); + }); + break; + } case dt_float32: { std::random_device rd; std::mt19937 gen(rd()); - std::uniform_real_distribution dis(1.0f, 2.0f); + std::uniform_real_distribution dis(0.0f, 100000.0f); NNCASE_UNUSED auto res = kernels::stackvm::apply( tensor.shape(), [&](gsl::span index) -> result { @@ -163,7 +175,7 @@ class UnaryTest : public KernelTest, case dt_float64: { std::random_device rd; std::mt19937 gen(rd()); - std::uniform_real_distribution dis(1.0, 2.0); + std::uniform_real_distribution dis(0.0, 100000.0); NNCASE_UNUSED auto res = kernels::stackvm::apply( tensor.shape(), [&](gsl::span index) -> result { @@ -212,6 +224,8 @@ TEST_P(UnaryTest, sqrt) { cosine_similarity_tensor(expected, actual); if (!result) { + std::cout << "input "; + print_runtime_tensor(input); std::cout << "actual "; print_runtime_tensor(actual); std::cout << "expected "; diff --git a/tests/kernels/test_unary_square.cpp b/tests/kernels/test_unary_square.cpp index 30d3813b93..ef79aee0dd 100644 --- a/tests/kernels/test_unary_square.cpp +++ b/tests/kernels/test_unary_square.cpp @@ -51,7 +51,7 @@ class UnaryTest : public KernelTest, case dt_int8: { std::random_device rd; std::mt19937 gen(rd()); - std::uniform_int_distribution<> dis(1, 6); + std::uniform_int_distribution<> dis(-1000, 1000); NNCASE_UNUSED auto res = kernels::stackvm::apply( tensor.shape(), [&](gsl::span index) -> result { @@ -63,7 +63,7 @@ class UnaryTest : public KernelTest, case dt_int16: { std::random_device rd; std::mt19937 gen(rd()); - std::uniform_int_distribution<> dis(1, 6); + std::uniform_int_distribution<> dis(-1000, 1000); NNCASE_UNUSED auto res = kernels::stackvm::apply( tensor.shape(), [&](gsl::span index) -> result { @@ -76,7 +76,7 @@ class UnaryTest : public KernelTest, case dt_int32: { std::random_device rd; std::mt19937 gen(rd()); - std::uniform_int_distribution<> dis(1, 6); + std::uniform_int_distribution<> dis(-10000, 10000); NNCASE_UNUSED auto res = kernels::stackvm::apply( tensor.shape(), [&](gsl::span index) -> result { @@ -88,7 +88,7 @@ class UnaryTest : public KernelTest, case dt_int64: { std::random_device rd; std::mt19937 gen(rd()); - std::uniform_int_distribution<> dis(1, 6); + std::uniform_int_distribution<> dis(-100000, 100000); NNCASE_UNUSED auto res = kernels::stackvm::apply( tensor.shape(), [&](gsl::span index) -> result { @@ -101,7 +101,7 @@ class UnaryTest : public KernelTest, case dt_uint8: { std::random_device rd; std::mt19937 gen(rd()); - std::uniform_int_distribution<> dis(1, 127); + std::uniform_int_distribution<> dis(-1000, 1000); NNCASE_UNUSED auto res = kernels::stackvm::apply( tensor.shape(), [&](gsl::span index) -> result { @@ -114,7 +114,7 @@ class UnaryTest : public KernelTest, case dt_uint16: { std::random_device rd; std::mt19937 gen(rd()); - std::uniform_int_distribution<> dis(1, 127); + std::uniform_int_distribution<> dis(-1000, 1000); NNCASE_UNUSED auto res = kernels::stackvm::apply( tensor.shape(), [&](gsl::span index) -> result { @@ -127,7 +127,7 @@ class UnaryTest : public KernelTest, case dt_uint32: { std::random_device rd; std::mt19937 gen(rd()); - std::uniform_int_distribution<> dis(1, 127); + std::uniform_int_distribution<> dis(-100000, 100000); NNCASE_UNUSED auto res = kernels::stackvm::apply( tensor.shape(), [&](gsl::span index) -> result { @@ -140,7 +140,7 @@ class UnaryTest : public KernelTest, case dt_uint64: { std::random_device rd; std::mt19937 gen(rd()); - std::uniform_int_distribution dis(1, 127); + std::uniform_int_distribution dis(-100000, 100000); NNCASE_UNUSED auto res = kernels::stackvm::apply( tensor.shape(), [&](gsl::span index) -> result { @@ -150,10 +150,22 @@ class UnaryTest : public KernelTest, }); break; } + case dt_float16: { + std::random_device rd; + std::mt19937 gen(rd()); + std::uniform_real_distribution dis(-1000.0f, 1000.0f); + NNCASE_UNUSED auto res = kernels::stackvm::apply( + tensor.shape(), + [&](gsl::span index) -> result { + get(tensor, index) = static_cast(dis(gen)); + return ok(); + }); + break; + } case dt_float32: { std::random_device rd; std::mt19937 gen(rd()); - std::uniform_real_distribution dis(1.0f, 2.0f); + std::uniform_real_distribution dis(-100000.0f, 100000.0f); NNCASE_UNUSED auto res = kernels::stackvm::apply( tensor.shape(), [&](gsl::span index) -> result { @@ -165,7 +177,7 @@ class UnaryTest : public KernelTest, case dt_float64: { std::random_device rd; std::mt19937 gen(rd()); - std::uniform_real_distribution dis(1.0, 2.0); + std::uniform_real_distribution dis(-100000.0, 100000.0); NNCASE_UNUSED auto res = kernels::stackvm::apply( tensor.shape(), [&](gsl::span index) -> result { @@ -213,6 +225,8 @@ TEST_P(UnaryTest, sqrt) { cosine_similarity_tensor(expected, actual); if (!result) { + std::cout << "input "; + print_runtime_tensor(input); std::cout << "actual "; print_runtime_tensor(actual); std::cout << "expected "; diff --git a/tests/kernels/test_unary_tanh.cpp b/tests/kernels/test_unary_tanh.cpp index 10c8f1d67b..bc1a608a01 100644 --- a/tests/kernels/test_unary_tanh.cpp +++ b/tests/kernels/test_unary_tanh.cpp @@ -45,6 +45,152 @@ class UnaryTest : public KernelTest, void TearDown() override { CLEAR_SUBCASE() } + void init_tensor(runtime_tensor &tensor) override { + auto dtype = tensor.datatype(); + switch (dtype) { + case dt_int8: { + std::random_device rd; + std::mt19937 gen(rd()); + std::uniform_int_distribution<> dis(-100000, 100000); + NNCASE_UNUSED auto res = kernels::stackvm::apply( + tensor.shape(), + [&](gsl::span index) -> result { + get(tensor, index) = static_cast(dis(gen)); + return ok(); + }); + break; + } + case dt_int16: { + std::random_device rd; + std::mt19937 gen(rd()); + std::uniform_int_distribution<> dis(-100000, 100000); + NNCASE_UNUSED auto res = kernels::stackvm::apply( + tensor.shape(), + [&](gsl::span index) -> result { + get(tensor, index) = + static_cast(dis(gen)); + return ok(); + }); + break; + } + case dt_int32: { + std::random_device rd; + std::mt19937 gen(rd()); + std::uniform_int_distribution<> dis(-100000, 100000); + NNCASE_UNUSED auto res = kernels::stackvm::apply( + tensor.shape(), + [&](gsl::span index) -> result { + get(tensor, index) = dis(gen); + return ok(); + }); + break; + } + case dt_int64: { + std::random_device rd; + std::mt19937 gen(rd()); + std::uniform_int_distribution<> dis(-100000, 100000); + NNCASE_UNUSED auto res = kernels::stackvm::apply( + tensor.shape(), + [&](gsl::span index) -> result { + get(tensor, index) = + static_cast(dis(gen)); + return ok(); + }); + break; + } + case dt_uint8: { + std::random_device rd; + std::mt19937 gen(rd()); + std::uniform_int_distribution<> dis(-100000, 100000); + NNCASE_UNUSED auto res = kernels::stackvm::apply( + tensor.shape(), + [&](gsl::span index) -> result { + get(tensor, index) = + static_cast(dis(gen)); + return ok(); + }); + break; + } + case dt_uint16: { + std::random_device rd; + std::mt19937 gen(rd()); + std::uniform_int_distribution<> dis(-100000, 100000); + NNCASE_UNUSED auto res = kernels::stackvm::apply( + tensor.shape(), + [&](gsl::span index) -> result { + get(tensor, index) = + static_cast(dis(gen)); + return ok(); + }); + break; + } + case dt_uint32: { + std::random_device rd; + std::mt19937 gen(rd()); + std::uniform_int_distribution<> dis(-100000, 100000); + NNCASE_UNUSED auto res = kernels::stackvm::apply( + tensor.shape(), + [&](gsl::span index) -> result { + get(tensor, index) = + static_cast(dis(gen)); + return ok(); + }); + break; + } + case dt_uint64: { + std::random_device rd; + std::mt19937 gen(rd()); + std::uniform_int_distribution dis(-100000, 100000); + NNCASE_UNUSED auto res = kernels::stackvm::apply( + tensor.shape(), + [&](gsl::span index) -> result { + get(tensor, index) = + static_cast(dis(gen)); + return ok(); + }); + break; + } + case dt_float16: { + std::random_device rd; + std::mt19937 gen(rd()); + std::uniform_real_distribution dis(-10000.0f, 10000.0f); + NNCASE_UNUSED auto res = kernels::stackvm::apply( + tensor.shape(), + [&](gsl::span index) -> result { + get(tensor, index) = static_cast(dis(gen)); + return ok(); + }); + break; + } + case dt_float32: { + std::random_device rd; + std::mt19937 gen(rd()); + std::uniform_real_distribution dis(-100000.0f, 100000.0f); + NNCASE_UNUSED auto res = kernels::stackvm::apply( + tensor.shape(), + [&](gsl::span index) -> result { + get(tensor, index) = static_cast(dis(gen)); + return ok(); + }); + break; + } + case dt_float64: { + std::random_device rd; + std::mt19937 gen(rd()); + std::uniform_real_distribution dis(-100000.0, 100000.0); + NNCASE_UNUSED auto res = kernels::stackvm::apply( + tensor.shape(), + [&](gsl::span index) -> result { + get(tensor, index) = static_cast(dis(gen)); + return ok(); + }); + break; + } + default: { + } + } + } + protected: runtime_tensor input; }; @@ -78,6 +224,8 @@ TEST_P(UnaryTest, tanh) { cosine_similarity_tensor(expected, actual); if (!result) { + std::cout << "input "; + print_runtime_tensor(input); std::cout << "actual "; print_runtime_tensor(actual); std::cout << "expected "; From f828e43030392783b02ca8dbb85635453ac9a97a Mon Sep 17 00:00:00 2001 From: HeJunchao <73169088+HeJunchao100813@users.noreply.github.com> Date: Wed, 6 Sep 2023 16:18:24 +0800 Subject: [PATCH 12/25] fix test_gather.cpp&&test_gather.json (#1084) * fix test_gather.cpp&&test_gather.json * fix * fix * fix --------- Co-authored-by: hejunchao --- tests/kernels/test_gather.cpp | 17 ++++++++++++++--- tests/kernels/test_gather.json | 2 ++ tests/kernels/test_gather_elements.cpp | 17 ++++++++++++++--- tests/kernels/test_gather_elements.json | 2 ++ tests/kernels/test_gather_nd.cpp | 17 ++++++++++++++--- tests/kernels/test_gather_nd.json | 2 ++ 6 files changed, 48 insertions(+), 9 deletions(-) diff --git a/tests/kernels/test_gather.cpp b/tests/kernels/test_gather.cpp index 15a3dbc797..819f315c06 100644 --- a/tests/kernels/test_gather.cpp +++ b/tests/kernels/test_gather.cpp @@ -35,6 +35,8 @@ class GatherTest : public KernelTest, READY_SUBCASE() auto shape = GetShapeArray("lhs_shape"); + auto indices_shape = GetShapeArray("indices_shape"); + auto indices_value = GetDataArray("indices_value"); auto value = GetNumber("axis"); auto typecode = GetDataType("lhs_type"); @@ -42,10 +44,13 @@ class GatherTest : public KernelTest, .expect("create tensor failed"); init_tensor(input); - int64_t indices_array[] = {0, 0, -1, -1}; - indices = hrt::create(dt_int64, {4}, + size_t indices_value_size = indices_value.size(); + auto *indices_array = + (int64_t *)malloc(indices_value_size * sizeof(int64_t)); + std::copy(indices_value.begin(), indices_value.end(), indices_array); + indices = hrt::create(dt_int64, indices_shape, {reinterpret_cast(indices_array), - sizeof(indices_array)}, + indices_value_size * sizeof(int64_t)}, true, host_runtime_tensor::pool_cpu_only) .expect("create tensor failed"); @@ -112,15 +117,21 @@ TEST_P(GatherTest, gather) { int main(int argc, char *argv[]) { READY_TEST_CASE_GENERATE() FOR_LOOP(lhs_shape, i) + FOR_LOOP(indices_shape, l) + FOR_LOOP(indices_value, h) FOR_LOOP(axis, j) FOR_LOOP(lhs_type, k) SPLIT_ELEMENT(lhs_shape, i) + SPLIT_ELEMENT(indices_shape, l) + SPLIT_ELEMENT(indices_value, h) SPLIT_ELEMENT(axis, j) SPLIT_ELEMENT(lhs_type, k) WRITE_SUB_CASE() FOR_LOOP_END() FOR_LOOP_END() FOR_LOOP_END() + FOR_LOOP_END() + FOR_LOOP_END() ::testing::InitGoogleTest(&argc, argv); return RUN_ALL_TESTS(); diff --git a/tests/kernels/test_gather.json b/tests/kernels/test_gather.json index b39845f716..c294a31800 100644 --- a/tests/kernels/test_gather.json +++ b/tests/kernels/test_gather.json @@ -1,5 +1,7 @@ { "lhs_shape":[[2, 3, 5, 7], [2, 2], [2, 3, 1], [5, 5, 7, 7], [11]], + "indices_shape":[[4], [2, 2], [4, 1]], "axis":[0, 1, -1, 2, 3, -2, -3, -4], + "indices_value": [[0, 0, -1, -1]], "lhs_type":["dt_float32", "dt_int8", "dt_int32", "dt_uint8", "dt_int16", "dt_uint16", "dt_uint32", "dt_uint64", "dt_int64", "dt_float16", "dt_float64", "dt_bfloat16", "dt_boolean"] } \ No newline at end of file diff --git a/tests/kernels/test_gather_elements.cpp b/tests/kernels/test_gather_elements.cpp index 9535851933..748c06256e 100644 --- a/tests/kernels/test_gather_elements.cpp +++ b/tests/kernels/test_gather_elements.cpp @@ -35,6 +35,8 @@ class GatherElementsTest : public KernelTest, READY_SUBCASE() auto shape = GetShapeArray("lhs_shape"); + auto indices_shape = GetShapeArray("indices_shape"); + auto indices_value = GetDataArray("indices_value"); auto value = GetNumber("axis"); auto typecode = GetDataType("lhs_type"); @@ -42,10 +44,13 @@ class GatherElementsTest : public KernelTest, .expect("create tensor failed"); init_tensor(input); - int64_t indices_array[] = {0, 0, 1, 1}; - indices = hrt::create(dt_int64, {2, 2}, + size_t indices_value_size = indices_value.size(); + auto *indices_array = + (int64_t *)malloc(indices_value_size * sizeof(int64_t)); + std::copy(indices_value.begin(), indices_value.end(), indices_array); + indices = hrt::create(dt_int64, indices_shape, {reinterpret_cast(indices_array), - sizeof(indices_array)}, + indices_value_size * sizeof(int64_t)}, true, host_runtime_tensor::pool_cpu_only) .expect("create tensor failed"); @@ -110,15 +115,21 @@ TEST_P(GatherElementsTest, gather_elements) { int main(int argc, char *argv[]) { READY_TEST_CASE_GENERATE() FOR_LOOP(lhs_shape, i) + FOR_LOOP(indices_shape, l) + FOR_LOOP(indices_value, h) FOR_LOOP(axis, j) FOR_LOOP(lhs_type, k) SPLIT_ELEMENT(lhs_shape, i) + SPLIT_ELEMENT(indices_shape, l) + SPLIT_ELEMENT(indices_value, h) SPLIT_ELEMENT(axis, j) SPLIT_ELEMENT(lhs_type, k) WRITE_SUB_CASE() FOR_LOOP_END() FOR_LOOP_END() FOR_LOOP_END() + FOR_LOOP_END() + FOR_LOOP_END() ::testing::InitGoogleTest(&argc, argv); return RUN_ALL_TESTS(); diff --git a/tests/kernels/test_gather_elements.json b/tests/kernels/test_gather_elements.json index b12b58e166..810930883f 100644 --- a/tests/kernels/test_gather_elements.json +++ b/tests/kernels/test_gather_elements.json @@ -1,5 +1,7 @@ { "lhs_shape":[[2, 2]], "axis":[0], + "indices_shape":[[2, 2], [4, 1]], + "indices_value": [[0, 0, 1, 1]], "lhs_type":["dt_float32", "dt_int8", "dt_int32", "dt_uint8", "dt_int16", "dt_uint16", "dt_uint32", "dt_uint64", "dt_int64", "dt_float16", "dt_float64", "dt_bfloat16", "dt_boolean"] } \ No newline at end of file diff --git a/tests/kernels/test_gather_nd.cpp b/tests/kernels/test_gather_nd.cpp index 8e95c443d7..96706b62b4 100644 --- a/tests/kernels/test_gather_nd.cpp +++ b/tests/kernels/test_gather_nd.cpp @@ -35,6 +35,8 @@ class GatherNDTest : public KernelTest, READY_SUBCASE() auto shape = GetShapeArray("lhs_shape"); + auto indices_shape = GetShapeArray("indices_shape"); + auto indices_value = GetDataArray("indices_value"); auto value = GetNumber("axis"); auto typecode = GetDataType("lhs_type"); @@ -42,10 +44,13 @@ class GatherNDTest : public KernelTest, .expect("create tensor failed"); init_tensor(input); - int64_t indices_array[] = {0, 0, 0, 0}; - indices = hrt::create(dt_int64, {2, 2}, + size_t indices_value_size = indices_value.size(); + auto *indices_array = + (int64_t *)malloc(indices_value_size * sizeof(int64_t)); + std::copy(indices_value.begin(), indices_value.end(), indices_array); + indices = hrt::create(dt_int64, indices_shape, {reinterpret_cast(indices_array), - sizeof(indices_array)}, + indices_value_size * sizeof(int64_t)}, true, host_runtime_tensor::pool_cpu_only) .expect("create tensor failed"); @@ -109,15 +114,21 @@ TEST_P(GatherNDTest, gather_nd) { int main(int argc, char *argv[]) { READY_TEST_CASE_GENERATE() FOR_LOOP(lhs_shape, i) + FOR_LOOP(indices_shape, l) + FOR_LOOP(indices_value, h) FOR_LOOP(axis, j) FOR_LOOP(lhs_type, k) SPLIT_ELEMENT(lhs_shape, i) + SPLIT_ELEMENT(indices_shape, l) + SPLIT_ELEMENT(indices_value, h) SPLIT_ELEMENT(axis, j) SPLIT_ELEMENT(lhs_type, k) WRITE_SUB_CASE() FOR_LOOP_END() FOR_LOOP_END() FOR_LOOP_END() + FOR_LOOP_END() + FOR_LOOP_END() ::testing::InitGoogleTest(&argc, argv); return RUN_ALL_TESTS(); diff --git a/tests/kernels/test_gather_nd.json b/tests/kernels/test_gather_nd.json index 64c54990be..a9af374f7d 100644 --- a/tests/kernels/test_gather_nd.json +++ b/tests/kernels/test_gather_nd.json @@ -1,5 +1,7 @@ { "lhs_shape":[[3, 5], [2, 2], [2, 3, 1], [5, 5, 7, 7]], "axis":[0], + "indices_shape":[[2, 2], [4, 1]], + "indices_value": [[0, 0, 0, 0]], "lhs_type":["dt_float32", "dt_int8", "dt_int32", "dt_uint8", "dt_int16", "dt_uint16", "dt_uint32", "dt_uint64", "dt_int64", "dt_float16", "dt_float64", "dt_bfloat16", "dt_boolean"] } \ No newline at end of file From 94afeb4124d0f2a8b13d9b71ad63b342b019375e Mon Sep 17 00:00:00 2001 From: Curio Yang Date: Wed, 6 Sep 2023 19:53:57 +0800 Subject: [PATCH 13/25] ci cancle (#1078) * cancel old commit && avoid canceling other pr --------- Co-authored-by: yanghaoqi --- .github/workflows/compiler-build.yml | 5 +++++ .github/workflows/compiler-python-release.yml | 4 ++++ .github/workflows/runtime-build.yml | 4 ++++ .gitignore | 2 +- 4 files changed, 14 insertions(+), 1 deletion(-) diff --git a/.github/workflows/compiler-build.yml b/.github/workflows/compiler-build.yml index 038585ffdb..20f819393d 100644 --- a/.github/workflows/compiler-build.yml +++ b/.github/workflows/compiler-build.yml @@ -1,6 +1,11 @@ name: compiler-build on: [push, pull_request] + +concurrency: + group: ${{ github.ref }} + cancel-in-progress: true + env: NUGET_CERT_REVOCATION_MODE: offline NUGET_PACKAGES: ${{ github.workspace }}/.nuget/packages diff --git a/.github/workflows/compiler-python-release.yml b/.github/workflows/compiler-python-release.yml index e201cb8a48..65b9d8d450 100644 --- a/.github/workflows/compiler-python-release.yml +++ b/.github/workflows/compiler-python-release.yml @@ -2,6 +2,10 @@ name: compiler-python-release on: [push, pull_request] +concurrency: + group: ${{ github.ref }} + cancel-in-progress: true + jobs: build-compiler: name: build-${{matrix.config.name}} diff --git a/.github/workflows/runtime-build.yml b/.github/workflows/runtime-build.yml index 3330b05156..1b48c6fa77 100644 --- a/.github/workflows/runtime-build.yml +++ b/.github/workflows/runtime-build.yml @@ -2,6 +2,10 @@ name: runtime-build on: [push, pull_request] +concurrency: + group: ${{ github.ref }} + cancel-in-progress: true + jobs: build-native-runtime: name: build-runtime-${{matrix.config.name}} diff --git a/.gitignore b/.gitignore index b518626f74..e8d3ff9274 100644 --- a/.gitignore +++ b/.gitignore @@ -301,6 +301,6 @@ nupkg *.runsettings cmake-build-* *gmodel_dump_dir* - +*.ipynb_checkpoints* # Auto generated files # generated/ \ No newline at end of file From 5d42c343e70ef4bddc2ca90f250ce40c4a035351 Mon Sep 17 00:00:00 2001 From: HeJunchao <73169088+HeJunchao100813@users.noreply.github.com> Date: Thu, 7 Sep 2023 15:09:59 +0800 Subject: [PATCH 14/25] Fix/test cast (#1085) * fix * fix * fix * fix * fix * fix test_cast.cpp * fix test_cast.cpp * fix --------- Co-authored-by: hejunchao --- tests/kernels/test_cast.cpp | 1 - tests/kernels/test_cast.json | 4 ++-- 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/tests/kernels/test_cast.cpp b/tests/kernels/test_cast.cpp index cea9bee37c..be348ccb5d 100644 --- a/tests/kernels/test_cast.cpp +++ b/tests/kernels/test_cast.cpp @@ -113,7 +113,6 @@ TEST_P(CastTest, cast) { runtime_tensor actual1(output1.as().expect("as tensor failed")); // expected - // cast_copy_tensor(input, expected); auto output_ort1 = ortki_CastLike(runtime_tensor_2_ort_tensor(input1), runtime_tensor_2_ort_tensor(actual1)); size_t size1 = 0; diff --git a/tests/kernels/test_cast.json b/tests/kernels/test_cast.json index 174c15a235..d3b5c4ee04 100644 --- a/tests/kernels/test_cast.json +++ b/tests/kernels/test_cast.json @@ -1,5 +1,5 @@ { "lhs_shape":[[1, 8, 24, 24], [1, 3, 3, 16], [2, 4, 8, 8], [8, 8], [1, 3, 16, 1], [1, 1]], - "lhs_type":["dt_int16", "dt_float32", "dt_uint8", "dt_int8"], - "rhs_type":["dt_int16", "dt_float32", "dt_uint8", "dt_int8"] + "lhs_type":["dt_uint16", "dt_int16", "dt_uint32", "dt_int32", "dt_uint64", "dt_int64", "dt_boolean", "dt_float32", "dt_uint8", "dt_int8", "dt_float16", "dt_bfloat16"], + "rhs_type":["dt_uint16", "dt_int16", "dt_uint32", "dt_int32", "dt_uint64", "dt_int64", "dt_boolean", "dt_float32", "dt_uint8", "dt_int8"] } \ No newline at end of file From d3886297781b816d34429c37605a0f52006f33a1 Mon Sep 17 00:00:00 2001 From: sunnycase Date: Tue, 12 Sep 2023 10:31:50 +0800 Subject: [PATCH 15/25] Support large kmodel (#1079) * Support large kmodel * Fix build * Apply code-format changes * fix BinaryWriter Seek --------- Co-authored-by: sunnycase Co-authored-by: Curio Yang Co-authored-by: huochenghai --- Directory.Packages.props | 10 +- modules/Nncase.Modules.CPU/packages.lock.json | 295 ++++++++++++++++++ .../CodeGen/StackVM/StackVMFunctionBuilder.cs | 2 +- .../StackVM/StackVMLinkableFunction.cs | 4 +- .../CodeGen/StackVM/StackVMLinkableModule.cs | 2 +- .../CodeGen/StackVM/StackVMLinkedModule.cs | 2 +- src/Native/include/nncase/runtime/model.h | 20 +- src/Nncase.CodeGen/CodeGen/FunctionBuilder.cs | 4 +- .../CodeGen/ILinkableFunction.cs | 2 +- src/Nncase.CodeGen/CodeGen/KModelTypes.cs | 18 +- src/Nncase.CodeGen/CodeGen/LinkableModule.cs | 12 +- src/Nncase.CodeGen/CodeGen/LinkedFunction.cs | 6 +- src/Nncase.CodeGen/CodeGen/LinkedModel.cs | 8 +- src/Nncase.CodeGen/CodeGen/LinkedSection.cs | 13 +- src/Nncase.CodeGen/CodeGen/SectionManager.cs | 15 +- src/Nncase.CodeGen/CodeGenExtensions.cs | 11 +- src/Nncase.Core/CodeGen/CodeGenTypes.cs | 2 +- src/Nncase.Core/CodeGen/IModuleBuilder.cs | 8 +- .../packages.lock.json | 6 +- src/Nncase.Tests/Core/UnitTestTIR.cs | 2 +- src/Nncase.Tests/packages.lock.json | 32 +- 21 files changed, 392 insertions(+), 82 deletions(-) create mode 100644 modules/Nncase.Modules.CPU/packages.lock.json diff --git a/Directory.Packages.props b/Directory.Packages.props index 1aad575e5f..9f48677feb 100644 --- a/Directory.Packages.props +++ b/Directory.Packages.props @@ -54,15 +54,15 @@ - - - + + + 1.5.25 - + - + diff --git a/modules/Nncase.Modules.CPU/packages.lock.json b/modules/Nncase.Modules.CPU/packages.lock.json new file mode 100644 index 0000000000..5dd73e5bda --- /dev/null +++ b/modules/Nncase.Modules.CPU/packages.lock.json @@ -0,0 +1,295 @@ +{ + "version": 2, + "dependencies": { + "net7.0": { + "StyleCop.Analyzers": { + "type": "Direct", + "requested": "[1.2.0-beta.435, )", + "resolved": "1.2.0-beta.435", + "contentHash": "TADk7vdGXtfTnYCV7GyleaaRTQjfoSfZXprQrVMm7cSJtJbFc1QIbWPyLvrgrfGdfHbGmUPvaN4ODKNxg2jgPQ==", + "dependencies": { + "StyleCop.Analyzers.Unstable": "1.2.0.435" + } + }, + "Google.OrTools.runtime.linux-arm64": { + "type": "Transitive", + "resolved": "9.4.1874", + "contentHash": "Z46ndZcZa2Lt5b76xU9kxVYbPLg/LfuMufhUVsu3Qo3L7Bibf7WXd9j7RRldjnuv8RIHWTqb0b+2FwwMxs0c5A==" + }, + "Google.OrTools.runtime.linux-x64": { + "type": "Transitive", + "resolved": "9.4.1874", + "contentHash": "zGeDb8FuvP9HXjrsU7krVXtSDFpR+DUGNEsH51k94jL9tzf2vWYI8+WUBRHZ/cGe50dpLr+vIjfcNo3gFyOpkQ==" + }, + "Google.OrTools.runtime.osx-arm64": { + "type": "Transitive", + "resolved": "9.4.1874", + "contentHash": "Wo0ZfDaH6DhiQw0jZm4HWJm/oPGPpWNwOLUz+EYaoH3MLtocSxItHGQj/Ta3HyhXnYNOv+TliAH8L+8RCXu/2w==" + }, + "Google.OrTools.runtime.osx-x64": { + "type": "Transitive", + "resolved": "9.4.1874", + "contentHash": "IAfGgKR1og6vU87axK1d37Ak/4jy8B4NMoElovG/KZc/2UY+cJEAQDA709UMegtI4lBhuxTWFNUiHQYmRIB9yQ==" + }, + "Google.OrTools.runtime.win-x64": { + "type": "Transitive", + "resolved": "9.4.1874", + "contentHash": "fUs5qDnZA6itygolcX6nPuachQkY9CVvQbakIzIiRAWKcaj8umQAbFdGwbkyzp3qp34BKW5mtPVsmMyfQBBjOQ==" + }, + "libortki": { + "type": "Transitive", + "resolved": "0.0.2", + "contentHash": "svfuG5mxGY/QC/5DVheHOCELmdSP90RtxQ73j23KarPXZ9ZXW+7v1l5J77hGDyQbEh1BGrnGgKBlyn76RauGHg==", + "dependencies": { + "libortki-linux": "0.0.2", + "libortki-osx": "0.0.2", + "libortki-osx-arm64": "0.0.2", + "libortki-win": "0.0.2" + } + }, + "libortki-linux": { + "type": "Transitive", + "resolved": "0.0.2", + "contentHash": "b04LWD4lgGy60tys3hPFhnUpgWDM6dN5r1PI7GOcPj8VupXCaI70LKNQ5/5twbDE6rkowOGanVTw0S2wBGBqBQ==" + }, + "libortki-osx": { + "type": "Transitive", + "resolved": "0.0.2", + "contentHash": "O6Q9GLULkDkZEPAZJVKLPH0ROXGVOE7BxuddgOcHNK2oiTEM7wIRnzp2OIlYgLpaOLyxJMisbGOhtWgdzt2Wng==" + }, + "libortki-osx-arm64": { + "type": "Transitive", + "resolved": "0.0.2", + "contentHash": "4Qn2dirJmRicnUG945oWpq7HVGwgqCKKxYPMISv/MRvmpZBbXrZ1cVvRaF8WwTu4XXgfKTa1sLv+i8zLifUMeQ==" + }, + "libortki-win": { + "type": "Transitive", + "resolved": "0.0.2", + "contentHash": "HAoROgAKn8XBun11X43HZuspKlo5JGy8/OYw5IUPo7FVh5TCaPrLjGmyGYYZ2dqLlv31yv/b6s254PIRGn95cA==" + }, + "Microsoft.Extensions.Configuration.Abstractions": { + "type": "Transitive", + "resolved": "6.0.0", + "contentHash": "qWzV9o+ZRWq+pGm+1dF+R7qTgTYoXvbyowRoBxQJGfqTpqDun2eteerjRQhq5PQ/14S+lqto3Ft4gYaRyl4rdQ==", + "dependencies": { + "Microsoft.Extensions.Primitives": "6.0.0" + } + }, + "Microsoft.Extensions.DependencyInjection.Abstractions": { + "type": "Transitive", + "resolved": "6.0.0", + "contentHash": "xlzi2IYREJH3/m6+lUrQlujzX8wDitm4QGnUu6kUXTQAWPuZY8i+ticFJbzfqaetLA6KR/rO6Ew/HuYD+bxifg==" + }, + "Microsoft.Extensions.FileProviders.Abstractions": { + "type": "Transitive", + "resolved": "6.0.0", + "contentHash": "0pd4/fho0gC12rQswaGQxbU34jOS1TPS8lZPpkFCH68ppQjHNHYle9iRuHeev1LhrJ94YPvzcRd8UmIuFk23Qw==", + "dependencies": { + "Microsoft.Extensions.Primitives": "6.0.0" + } + }, + "Microsoft.Extensions.Primitives": { + "type": "Transitive", + "resolved": "6.0.0", + "contentHash": "9+PnzmQFfEFNR9J2aDTfJGGupShHjOuGw4VUv+JB044biSHrnmCIMD+mJHmb2H7YryrfBEXDurxQ47gJZdCKNQ==", + "dependencies": { + "System.Runtime.CompilerServices.Unsafe": "6.0.0" + } + }, + "NetFabric.Hyperlinq.Abstractions": { + "type": "Transitive", + "resolved": "1.3.0", + "contentHash": "WXnEcGwmXfa8gW9N2MlcaPNUzM3NLMwnAhacbtH554F8YcoXbIkTB+uGa1Aa+9gyb/9JZgYVHnmADgJUKP52nA==" + }, + "StyleCop.Analyzers.Unstable": { + "type": "Transitive", + "resolved": "1.2.0.435", + "contentHash": "ouwPWZxbOV3SmCZxIRqHvljkSzkCyi1tDoMzQtDb/bRP8ctASV/iRJr+A2Gdj0QLaLmWnqTWDrH82/iP+X80Lg==" + }, + "System.Buffers": { + "type": "Transitive", + "resolved": "4.5.1", + "contentHash": "Rw7ijyl1qqRS0YQD/WycNst8hUUMgrMH4FCn1nNm27M4VxchZ1js3fVjQaANHO5f3sN4isvP4a+Met9Y4YomAg==" + }, + "System.Runtime.CompilerServices.Unsafe": { + "type": "Transitive", + "resolved": "6.0.0", + "contentHash": "/iUeP3tq1S0XdNNoMz5C9twLSrM/TH+qElHkXWaPvuNOt+99G75NrV0OS2EqHx5wMN7popYjpc8oTjC1y16DLg==" + }, + "nncase.codegen": { + "type": "Project", + "dependencies": { + "Extension.Mathematics": "[1.2.12, )", + "Nncase.Core": "[1.0.0, )", + "Nncase.IO": "[1.0.0, )" + } + }, + "nncase.core": { + "type": "Project", + "dependencies": { + "DryIoc.dll": "[5.3.1, )", + "GiGraph.Dot": "[2.0.0, )", + "Microsoft.Extensions.Hosting.Abstractions": "[6.0.0, )", + "Microsoft.Extensions.Logging.Abstractions": "[6.0.0, )", + "Microsoft.Extensions.Options": "[6.0.0, )", + "Microsoft.Toolkit.HighPerformance": "[7.1.1, )", + "NetFabric.Hyperlinq": "[3.0.0-beta48, )", + "System.Reactive": "[5.0.0, )" + } + }, + "nncase.diagnostics": { + "type": "Project", + "dependencies": { + "Nncase.Core": "[1.0.0, )" + } + }, + "nncase.egraph": { + "type": "Project", + "dependencies": { + "GiGraph.Dot": "[2.0.0, )", + "Google.OrTools": "[9.4.1874, )", + "NetFabric.Hyperlinq": "[3.0.0-beta48, )", + "Nncase.Core": "[1.0.0, )", + "Nncase.Evaluator": "[1.0.0, )", + "Singulink.Collections.Weak": "[1.0.2, )" + } + }, + "nncase.evaluator": { + "type": "Project", + "dependencies": { + "Nncase.Core": "[1.0.0, )", + "OrtKISharp": "[0.0.2, )" + } + }, + "nncase.graph": { + "type": "Project", + "dependencies": { + "Nncase.Core": "[1.0.0, )", + "Nncase.Evaluator": "[1.0.0, )" + } + }, + "nncase.io": { + "type": "Project" + }, + "nncase.modules.stackvm": { + "type": "Project", + "dependencies": { + "Nncase.CodeGen": "[1.0.0, )", + "Nncase.Passes": "[1.0.0, )" + } + }, + "nncase.passes": { + "type": "Project", + "dependencies": { + "Nncase.Core": "[1.0.0, )", + "Nncase.EGraph": "[1.0.0, )", + "Nncase.Evaluator": "[1.0.0, )", + "Nncase.Graph": "[1.0.0, )" + } + }, + "DryIoc.dll": { + "type": "CentralTransitive", + "requested": "[5.3.1, )", + "resolved": "5.3.1", + "contentHash": "E3zclUh2CIBks1t2uBD1k18pyGFJ1YSKCrbCDbB7qCdl2RAB+k68AyDpjeplhF1ot2XPV82AgyCWBXMf0ggL1g==" + }, + "Extension.Mathematics": { + "type": "CentralTransitive", + "requested": "[1.2.12, )", + "resolved": "1.2.12", + "contentHash": "D4mn5Cab4ztPLJ0V8uMErDrO/Y61098nwrvyIOLZymVAYOQcwP1vomVWKbTagf1aPU3cX5Q7adZtQEQwOy6XEg==" + }, + "GiGraph.Dot": { + "type": "CentralTransitive", + "requested": "[2.0.0, )", + "resolved": "2.0.0", + "contentHash": "ThvS2mQVveSkTMUm04tMbRYzu1XFPV8xBHISrUMp02APjhv9IRbLu3v3upTPCywORx2Ds/c6AqEUL1WU6kPfuQ==" + }, + "Google.OrTools": { + "type": "CentralTransitive", + "requested": "[9.4.1874, )", + "resolved": "9.4.1874", + "contentHash": "jqRoI+pYlym+fhoU25u+13oti5h+772bllQ9zDitTVMclDXVTiG6pxzvmYO74wnADBMdpb2SQlgiNQxoNk5dlA==", + "dependencies": { + "Google.OrTools.runtime.linux-arm64": "9.4.1874", + "Google.OrTools.runtime.linux-x64": "9.4.1874", + "Google.OrTools.runtime.osx-arm64": "9.4.1874", + "Google.OrTools.runtime.osx-x64": "9.4.1874", + "Google.OrTools.runtime.win-x64": "9.4.1874", + "Google.Protobuf": "3.19.4" + } + }, + "Google.Protobuf": { + "type": "CentralTransitive", + "requested": "[3.19.4, )", + "resolved": "3.19.4", + "contentHash": "fd07/ykL4O4FhqrZIELm5lmiyOHfdPg9+o+hWr6tcfRdS7tHXnImg/2wtogLzlW2eEmr0J7j6ZrZvaWOLiJbxQ==" + }, + "Microsoft.Extensions.Hosting.Abstractions": { + "type": "CentralTransitive", + "requested": "[6.0.0, )", + "resolved": "6.0.0", + "contentHash": "GcT5l2CYXL6Sa27KCSh0TixsRfADUgth+ojQSD5EkzisZxmGFh7CwzkcYuGwvmXLjr27uWRNrJ2vuuEjMhU05Q==", + "dependencies": { + "Microsoft.Extensions.Configuration.Abstractions": "6.0.0", + "Microsoft.Extensions.DependencyInjection.Abstractions": "6.0.0", + "Microsoft.Extensions.FileProviders.Abstractions": "6.0.0" + } + }, + "Microsoft.Extensions.Logging.Abstractions": { + "type": "CentralTransitive", + "requested": "[6.0.0, )", + "resolved": "6.0.0", + "contentHash": "/HggWBbTwy8TgebGSX5DBZ24ndhzi93sHUBDvP1IxbZD7FDokYzdAr6+vbWGjw2XAfR2EJ1sfKUotpjHnFWPxA==" + }, + "Microsoft.Extensions.Options": { + "type": "CentralTransitive", + "requested": "[6.0.0, )", + "resolved": "6.0.0", + "contentHash": "dzXN0+V1AyjOe2xcJ86Qbo233KHuLEY0njf/P2Kw8SfJU+d45HNS2ctJdnEnrWbM9Ye2eFgaC5Mj9otRMU6IsQ==", + "dependencies": { + "Microsoft.Extensions.DependencyInjection.Abstractions": "6.0.0", + "Microsoft.Extensions.Primitives": "6.0.0" + } + }, + "Microsoft.Toolkit.HighPerformance": { + "type": "CentralTransitive", + "requested": "[7.1.1, )", + "resolved": "7.1.1", + "contentHash": "TRnvDpZPXO30hTOtjfLw6Y9BtTKtTpzk9lefeh4RMCaUihWrVKQR454nYH4/mMJAh+LXqfAPyk0kfkJs0Amopw==" + }, + "NetFabric.Hyperlinq": { + "type": "CentralTransitive", + "requested": "[3.0.0-beta48, )", + "resolved": "3.0.0-beta48", + "contentHash": "oYUhXvxNS8bBJWqNkvx5g8y0P/0LtyqS2pN0w4OWjVDNWEpLbdbvPy9w/9z1n2PrqIjX3jxUsEnoCmxxGnI3gw==", + "dependencies": { + "NetFabric.Hyperlinq.Abstractions": "1.3.0", + "System.Buffers": "4.5.1", + "System.Runtime.CompilerServices.Unsafe": "5.0.0" + } + }, + "OrtKISharp": { + "type": "CentralTransitive", + "requested": "[0.0.2, )", + "resolved": "0.0.2", + "contentHash": "q8j0yR5836Zhv9WB9BFkQt1UaEFyibq8bqJcTiULlILF6/sz8z7Wy2N8sgYdDKsdW25zncIz7j6IDbKM5ynePg==", + "dependencies": { + "libortki": "0.0.2" + } + }, + "Singulink.Collections.Weak": { + "type": "CentralTransitive", + "requested": "[1.0.2, )", + "resolved": "1.0.2", + "contentHash": "giLAHrjJe0Bh7yhNexR6pmcv02+Fi+lEPxQVdB8zvkuJCmy6rnqu8CZLIpxrUfLcWDuTCSiK0IfGmMhig3UDhA==" + }, + "System.Reactive": { + "type": "CentralTransitive", + "requested": "[5.0.0, )", + "resolved": "5.0.0", + "contentHash": "erBZjkQHWL9jpasCE/0qKAryzVBJFxGHVBAvgRN1bzM0q2s1S4oYREEEL0Vb+1kA/6BKb5FjUZMp5VXmy+gzkQ==" + } + } + } +} \ No newline at end of file diff --git a/modules/Nncase.Modules.StackVM/CodeGen/StackVM/StackVMFunctionBuilder.cs b/modules/Nncase.Modules.StackVM/CodeGen/StackVM/StackVMFunctionBuilder.cs index bae39f9655..ec04643dbf 100644 --- a/modules/Nncase.Modules.StackVM/CodeGen/StackVM/StackVMFunctionBuilder.cs +++ b/modules/Nncase.Modules.StackVM/CodeGen/StackVM/StackVMFunctionBuilder.cs @@ -33,7 +33,7 @@ public StackVMFunctionBuilder(uint id, SectionManager sectionManager) _textEmitter = new StackVMEmitter(TextWriter); } - protected override ILinkableFunction CreateLinkableFunction(uint id, BaseFunction callable, IReadOnlyList functionRefs, byte[] text) + protected override ILinkableFunction CreateLinkableFunction(uint id, BaseFunction callable, IReadOnlyList functionRefs, Stream text) { return new StackVMLinkableFunction(id, callable, functionRefs, _localsAllocator.MaxCount, text, _context.CustomCallModules); } diff --git a/modules/Nncase.Modules.StackVM/CodeGen/StackVM/StackVMLinkableFunction.cs b/modules/Nncase.Modules.StackVM/CodeGen/StackVM/StackVMLinkableFunction.cs index 0ffa2203f4..64947f8c25 100644 --- a/modules/Nncase.Modules.StackVM/CodeGen/StackVM/StackVMLinkableFunction.cs +++ b/modules/Nncase.Modules.StackVM/CodeGen/StackVM/StackVMLinkableFunction.cs @@ -12,7 +12,7 @@ namespace Nncase.CodeGen.StackVM; internal class StackVMLinkableFunction : ILinkableFunction { - public StackVMLinkableFunction(uint id, BaseFunction sourceFunction, IEnumerable functionRefs, ushort maxLocals, byte[] text, IReadOnlySet custom_call_modules) + public StackVMLinkableFunction(uint id, BaseFunction sourceFunction, IEnumerable functionRefs, ushort maxLocals, Stream text, IReadOnlySet custom_call_modules) { Id = id; SourceFunction = sourceFunction; @@ -30,7 +30,7 @@ public StackVMLinkableFunction(uint id, BaseFunction sourceFunction, IEnumerable public ushort MaxLocals { get; } - public byte[] Text { get; } + public Stream Text { get; } public IReadOnlyList Sections => Array.Empty(); diff --git a/modules/Nncase.Modules.StackVM/CodeGen/StackVM/StackVMLinkableModule.cs b/modules/Nncase.Modules.StackVM/CodeGen/StackVM/StackVMLinkableModule.cs index 4ade1d2a8c..0ca1549f14 100644 --- a/modules/Nncase.Modules.StackVM/CodeGen/StackVM/StackVMLinkableModule.cs +++ b/modules/Nncase.Modules.StackVM/CodeGen/StackVM/StackVMLinkableModule.cs @@ -30,7 +30,7 @@ public StackVMLinkableModule(IReadOnlyList functions, Section } } - protected override ILinkedModule CreateLinkedModule(IReadOnlyList linkedFunctions, byte[] text) + protected override ILinkedModule CreateLinkedModule(IReadOnlyList linkedFunctions, Stream text) { return new StackVMLinkedModule( linkedFunctions, diff --git a/modules/Nncase.Modules.StackVM/CodeGen/StackVM/StackVMLinkedModule.cs b/modules/Nncase.Modules.StackVM/CodeGen/StackVM/StackVMLinkedModule.cs index 06b554fb55..3bfb985fd8 100644 --- a/modules/Nncase.Modules.StackVM/CodeGen/StackVM/StackVMLinkedModule.cs +++ b/modules/Nncase.Modules.StackVM/CodeGen/StackVM/StackVMLinkedModule.cs @@ -12,7 +12,7 @@ namespace Nncase.CodeGen.StackVM; internal class StackVMLinkedModule : ILinkedModule { - public StackVMLinkedModule(IReadOnlyList functions, byte[] text, byte[]? rdata, byte[]? custom_calls) + public StackVMLinkedModule(IReadOnlyList functions, Stream text, Stream? rdata, Stream? custom_calls) { Functions = functions; Sections = new[] diff --git a/src/Native/include/nncase/runtime/model.h b/src/Native/include/nncase/runtime/model.h index 257488360f..45c67c6430 100644 --- a/src/Native/include/nncase/runtime/model.h +++ b/src/Native/include/nncase/runtime/model.h @@ -48,29 +48,29 @@ struct model_header { struct function_header { uint32_t parameters; - uint32_t entrypoint; - uint32_t text_size; - uint32_t size; uint32_t sections; - uint32_t reserved0; + uint64_t entrypoint; + uint64_t text_size; + uint64_t size; }; struct module_header { module_kind_t kind; uint32_t version; - uint32_t size; uint32_t sections; uint32_t functions; + uint32_t reserved0; + uint64_t size; }; struct section_header { char name[MAX_SECTION_NAME_LENGTH]; uint32_t flags; - uint32_t size; - uint32_t body_start; - uint32_t body_size; - uint32_t memory_size; uint32_t reserved0; + uint64_t size; + uint64_t body_start; + uint64_t body_size; + uint64_t memory_size; }; NNCASE_INLINE_VAR constexpr uint32_t SECTION_MERGED_INTO_RDATA = 1; @@ -96,6 +96,6 @@ struct shape_header { }; NNCASE_INLINE_VAR constexpr uint32_t MODEL_IDENTIFIER = 'KMDL'; -NNCASE_INLINE_VAR constexpr uint32_t MODEL_VERSION = 6; +NNCASE_INLINE_VAR constexpr uint32_t MODEL_VERSION = 7; END_NS_NNCASE_RUNTIME diff --git a/src/Nncase.CodeGen/CodeGen/FunctionBuilder.cs b/src/Nncase.CodeGen/CodeGen/FunctionBuilder.cs index 9a374d3f11..27091514dd 100644 --- a/src/Nncase.CodeGen/CodeGen/FunctionBuilder.cs +++ b/src/Nncase.CodeGen/CodeGen/FunctionBuilder.cs @@ -47,7 +47,7 @@ public ILinkableFunction Build(BaseFunction callable) // 3. Fix addrs FixAddrs(); TextWriter.Flush(); - return CreateLinkableFunction(Id, callable, FunctionRefs, _textContent.ToArray()); + return CreateLinkableFunction(Id, callable, FunctionRefs, _textContent); } public void Dispose() @@ -59,7 +59,7 @@ public void Dispose() protected abstract void WriteText(); - protected abstract ILinkableFunction CreateLinkableFunction(uint id, BaseFunction callable, IReadOnlyList functionRefs, byte[] text); + protected abstract ILinkableFunction CreateLinkableFunction(uint id, BaseFunction callable, IReadOnlyList functionRefs, Stream text); private void FixAddrs() { diff --git a/src/Nncase.CodeGen/CodeGen/ILinkableFunction.cs b/src/Nncase.CodeGen/CodeGen/ILinkableFunction.cs index 39faa69578..21ce7e8a3b 100644 --- a/src/Nncase.CodeGen/CodeGen/ILinkableFunction.cs +++ b/src/Nncase.CodeGen/CodeGen/ILinkableFunction.cs @@ -18,7 +18,7 @@ public interface ILinkableFunction public IEnumerable FunctionRefs { get; } - public byte[] Text { get; } + public Stream Text { get; } public IReadOnlyList Sections { get; } } diff --git a/src/Nncase.CodeGen/CodeGen/KModelTypes.cs b/src/Nncase.CodeGen/CodeGen/KModelTypes.cs index 1a21449ceb..c384df87bc 100644 --- a/src/Nncase.CodeGen/CodeGen/KModelTypes.cs +++ b/src/Nncase.CodeGen/CodeGen/KModelTypes.cs @@ -30,11 +30,10 @@ public struct ModelHeader public struct FunctionHeader { public uint Parameters; - public uint Entrypoint; - public uint TextSize; - public uint Size; public uint Sections; - public uint Reserved0; + public ulong Entrypoint; + public ulong TextSize; + public ulong Size; } [StructLayout(LayoutKind.Sequential)] @@ -42,9 +41,10 @@ public unsafe struct ModuleHeader { public fixed byte Kind[ModelInfo.MaxModuleKindLength]; public uint Version; - public uint Size; public uint Sections; public uint Functions; + public uint Reserved0; + public ulong Size; } /// @@ -55,11 +55,11 @@ public unsafe struct SectionHeader { public fixed byte Name[ModelInfo.MaxSectionNameLength]; public uint Flags; - public uint Size; - public uint BodyStart; - public uint BodySize; - public uint MemorySize; public uint Reserved0; + public ulong Size; + public ulong BodyStart; + public ulong BodySize; + public ulong MemorySize; } [StructLayout(LayoutKind.Sequential)] diff --git a/src/Nncase.CodeGen/CodeGen/LinkableModule.cs b/src/Nncase.CodeGen/CodeGen/LinkableModule.cs index 7bdc85d600..0fdd3a54e1 100644 --- a/src/Nncase.CodeGen/CodeGen/LinkableModule.cs +++ b/src/Nncase.CodeGen/CodeGen/LinkableModule.cs @@ -32,21 +32,23 @@ public ILinkedModule Link(ILinkContext linkContext) foreach (var func in _functions) { FixFunctionRefs(func, linkContext); + bw.Flush(); bw.AlignPosition(_textAlignment); var textBegin = bw.Position(); - bw.Write(func.Text); - linkedFunctions.Add(new LinkedFunction(func.Id, func.SourceFunction, (uint)textBegin, (uint)func.Text.Length, func.Sections)); + func.Text.Position = 0; + func.Text.CopyTo(bw.BaseStream); + linkedFunctions.Add(new LinkedFunction(func.Id, func.SourceFunction, (ulong)textBegin, (ulong)func.Text.Length, func.Sections)); } } - return CreateLinkedModule(linkedFunctions, text.ToArray()); + return CreateLinkedModule(linkedFunctions, text); } - protected abstract ILinkedModule CreateLinkedModule(IReadOnlyList linkedFunctions, byte[] text); + protected abstract ILinkedModule CreateLinkedModule(IReadOnlyList linkedFunctions, Stream text); private void FixFunctionRefs(ILinkableFunction func, ILinkContext linkContext) { - using var writer = new BinaryWriter(new MemoryStream(func.Text)); + using var writer = new BinaryWriter(func.Text, Encoding.UTF8, leaveOpen: true); foreach (var funcRef in func.FunctionRefs) { var id = linkContext.GetFunctionId(funcRef.Callable); diff --git a/src/Nncase.CodeGen/CodeGen/LinkedFunction.cs b/src/Nncase.CodeGen/CodeGen/LinkedFunction.cs index df9ff51a28..b3dbe692e0 100644 --- a/src/Nncase.CodeGen/CodeGen/LinkedFunction.cs +++ b/src/Nncase.CodeGen/CodeGen/LinkedFunction.cs @@ -12,7 +12,7 @@ namespace Nncase.CodeGen; public class LinkedFunction : ILinkedFunction { - public LinkedFunction(uint id, Callable sourceFunction, uint textBegin, uint textLength, IReadOnlyList sections) + public LinkedFunction(uint id, Callable sourceFunction, ulong textBegin, ulong textLength, IReadOnlyList sections) { Id = id; CompilerServices.InferenceType(sourceFunction); @@ -29,9 +29,9 @@ public LinkedFunction(uint id, Callable sourceFunction, uint textBegin, uint tex public IRType ReturnType { get; } - public uint TextBegin { get; } + public ulong TextBegin { get; } - public uint TextLength { get; } + public ulong TextLength { get; } public IReadOnlyList Sections { get; } } diff --git a/src/Nncase.CodeGen/CodeGen/LinkedModel.cs b/src/Nncase.CodeGen/CodeGen/LinkedModel.cs index a7a25a65e2..72461aaf69 100644 --- a/src/Nncase.CodeGen/CodeGen/LinkedModel.cs +++ b/src/Nncase.CodeGen/CodeGen/LinkedModel.cs @@ -103,7 +103,7 @@ private unsafe void Serialize(BinaryWriter writer, ILinkedModule module) var endPos = writer.Position(); // Write header - header.Size = (uint)(endPos - headerPos); + header.Size = (ulong)(endPos - headerPos); writer.Position(headerPos); writer.Write(ref header); writer.Position(endPos); @@ -138,7 +138,7 @@ private unsafe void Serialize(BinaryWriter writer, ILinkedFunction func) var endPos = writer.Position(); // Write header - funcHeader.Size = (uint)(endPos - headerPos); + funcHeader.Size = (ulong)(endPos - headerPos); writer.Position(headerPos); writer.Write(ref funcHeader); writer.Position(endPos); @@ -157,7 +157,7 @@ private unsafe void Serialize(BinaryWriter writer, ILinkedSection section) var headerPos = writer.Position(); writer.Skip((ulong)sizeof(SectionHeader)); - header.BodyStart = (uint)writer.AlignPosition(section.Alignment); + header.BodyStart = (ulong)writer.AlignPosition(section.Alignment); writer.Flush(); section.Serialize(writer.BaseStream); @@ -165,7 +165,7 @@ private unsafe void Serialize(BinaryWriter writer, ILinkedSection section) var endPos = writer.Position(); // Write header - header.Size = (uint)(endPos - headerPos); + header.Size = (ulong)(endPos - headerPos); writer.Position(headerPos); writer.Write(ref header); writer.Position(endPos); diff --git a/src/Nncase.CodeGen/CodeGen/LinkedSection.cs b/src/Nncase.CodeGen/CodeGen/LinkedSection.cs index 6e1c670bcc..2bbddefd90 100644 --- a/src/Nncase.CodeGen/CodeGen/LinkedSection.cs +++ b/src/Nncase.CodeGen/CodeGen/LinkedSection.cs @@ -11,16 +11,16 @@ namespace Nncase.CodeGen; public class LinkedSection : ILinkedSection { - private readonly byte[]? _content; + private readonly Stream? _content; - public LinkedSection(byte[]? content, string name, uint flags, uint alignment, uint sizeInMemory) + public LinkedSection(Stream? content, string name, uint flags, uint alignment, ulong sizeInMemory) { if (alignment == 0) { throw new ArgumentOutOfRangeException(nameof(alignment)); } - SizeInFile = (uint?)content?.Length ?? 0; + SizeInFile = (ulong?)content?.Length ?? 0; if (sizeInMemory < SizeInFile) { throw new ArgumentOutOfRangeException(nameof(sizeInMemory)); @@ -39,15 +39,16 @@ public LinkedSection(byte[]? content, string name, uint flags, uint alignment, u public uint Alignment { get; } - public uint SizeInFile { get; } + public ulong SizeInFile { get; } - public uint SizeInMemory { get; } + public ulong SizeInMemory { get; } public void Serialize(Stream output) { if (_content != null) { - output.Write(_content); + _content.Seek(0, SeekOrigin.Begin); + _content.CopyTo(output); } } } diff --git a/src/Nncase.CodeGen/CodeGen/SectionManager.cs b/src/Nncase.CodeGen/CodeGen/SectionManager.cs index c37e368fde..cc18c0e36b 100644 --- a/src/Nncase.CodeGen/CodeGen/SectionManager.cs +++ b/src/Nncase.CodeGen/CodeGen/SectionManager.cs @@ -45,26 +45,31 @@ public record FunctionRef(long Position, int Length, BaseFunction Callable, Func public class SectionManager { - private readonly Dictionary _sections = new(); + private readonly Dictionary _sections = new(); public BinaryWriter GetWriter(string name) { if (!_sections.TryGetValue(name, out var section)) { - var stream = new MemoryStream(); - section = (stream, new BinaryWriter(stream, Encoding.UTF8, true)); + var tmpFile = File.Open(Path.GetTempFileName(), new FileStreamOptions + { + Access = FileAccess.ReadWrite, + Mode = FileMode.Create, + Options = FileOptions.Asynchronous | FileOptions.DeleteOnClose, + }); + section = (tmpFile, new BinaryWriter(tmpFile, Encoding.UTF8, true)); _sections.Add(name, section); } return section.Writer; } - public byte[]? GetContent(string name) + public Stream? GetContent(string name) { if (_sections.TryGetValue(name, out var section)) { section.Writer.Flush(); - return section.Stream.ToArray(); + return section.Stream; } return null; diff --git a/src/Nncase.CodeGen/CodeGenExtensions.cs b/src/Nncase.CodeGen/CodeGenExtensions.cs index 7eee489db6..b73a9d2573 100644 --- a/src/Nncase.CodeGen/CodeGenExtensions.cs +++ b/src/Nncase.CodeGen/CodeGenExtensions.cs @@ -54,7 +54,14 @@ public static long Position(this BinaryWriter writer) /// The current position. public static long Position(this BinaryWriter writer, long pos) { - return writer.Seek((int)pos, SeekOrigin.Begin); + writer.Seek(0, SeekOrigin.Begin); + var segs = Math.DivRem(pos, int.MaxValue, out var rem); + for (long l = 0; l < segs; l++) + { + writer.Seek(int.MaxValue, SeekOrigin.Current); + } + + return writer.Seek(checked((int)rem), SeekOrigin.Current); } /// @@ -64,7 +71,7 @@ public static long Position(this BinaryWriter writer, long pos) /// Bytes to skip. public static void Skip(this BinaryWriter writer, ulong len) { - writer.Seek((int)len, SeekOrigin.Current); + writer.Seek(checked((int)len), SeekOrigin.Current); } public static unsafe void Write(this BinaryWriter writer, ref T value) diff --git a/src/Nncase.Core/CodeGen/CodeGenTypes.cs b/src/Nncase.Core/CodeGen/CodeGenTypes.cs index f39fdb456f..f44bcebacd 100644 --- a/src/Nncase.Core/CodeGen/CodeGenTypes.cs +++ b/src/Nncase.Core/CodeGen/CodeGenTypes.cs @@ -47,7 +47,7 @@ public static class ModelInfo /// /// kmodel version. /// - public const int Version = 6; + public const int Version = 7; /// /// merged rdata flag. diff --git a/src/Nncase.Core/CodeGen/IModuleBuilder.cs b/src/Nncase.Core/CodeGen/IModuleBuilder.cs index fc31f69235..bb9a520553 100644 --- a/src/Nncase.Core/CodeGen/IModuleBuilder.cs +++ b/src/Nncase.Core/CodeGen/IModuleBuilder.cs @@ -46,12 +46,12 @@ public interface ILinkedSection /// /// Gets size in file. /// - uint SizeInFile { get; } + ulong SizeInFile { get; } /// /// Gets size in memory. /// - uint SizeInMemory { get; } + ulong SizeInMemory { get; } /// /// Serialize payload. @@ -83,12 +83,12 @@ public interface ILinkedFunction /// /// Gets text begin. /// - uint TextBegin { get; } + ulong TextBegin { get; } /// /// Gets text length. /// - uint TextLength { get; } + ulong TextLength { get; } /// /// Gets sections. diff --git a/src/Nncase.Tests.TestFixture/packages.lock.json b/src/Nncase.Tests.TestFixture/packages.lock.json index a42ac54c45..13a2baae60 100644 --- a/src/Nncase.Tests.TestFixture/packages.lock.json +++ b/src/Nncase.Tests.TestFixture/packages.lock.json @@ -58,9 +58,9 @@ }, "xunit.runner.visualstudio": { "type": "Direct", - "requested": "[2.4.3, )", - "resolved": "2.4.3", - "contentHash": "kZZSmOmKA8OBlAJaquPXnJJLM9RwQ27H7BMVqfMLUcTi9xHinWGJiWksa3D4NEtz0wZ/nxd2mogObvBgJKCRhQ==" + "requested": "[2.5.0, )", + "resolved": "2.5.0", + "contentHash": "+Gp9vuC2431yPyKB15YrOTxCuEAErBQUTIs6CquumX1F073UaPHGW0VE/XVJLMh9W4sXdz3TBkcHdFWZrRn2Hw==" }, "xunit.v3.assert": { "type": "Direct", diff --git a/src/Nncase.Tests/Core/UnitTestTIR.cs b/src/Nncase.Tests/Core/UnitTestTIR.cs index ba7131f64e..54d504f58c 100644 --- a/src/Nncase.Tests/Core/UnitTestTIR.cs +++ b/src/Nncase.Tests/Core/UnitTestTIR.cs @@ -82,7 +82,7 @@ public void TestSizeVar() var name = "test"; var actual = T.SizeVar(name); var expected = Var.SizeVar(name); - Assert.True(actual.ToString().Equals(expected.ToString(), StringComparison.Ordinal)); + Assert.Equal(expected.ToString(), actual.ToString()); } [Fact] diff --git a/src/Nncase.Tests/packages.lock.json b/src/Nncase.Tests/packages.lock.json index b08aa2c881..dce3ce0116 100644 --- a/src/Nncase.Tests/packages.lock.json +++ b/src/Nncase.Tests/packages.lock.json @@ -108,9 +108,9 @@ }, "xunit.analyzers": { "type": "Direct", - "requested": "[1.1.0, )", - "resolved": "1.1.0", - "contentHash": "pFgSns6v+apWOqKaMpbi7LG7iHy9Dmhz54ySJKnn2f8jsArRsnOXf0Naqxy2+g0Q8YI7xhkfxT6YVoY+4GcQFg==" + "requested": "[1.2.0, )", + "resolved": "1.2.0", + "contentHash": "d3dehV/DASLRlR8stWQmbPPjfYC2tct50Evav+OlsJMkfFqkhYvzO1k0s81lk0px8O0knZU/FqC8SqbXOtn+hw==" }, "Xunit.Combinatorial": { "type": "Direct", @@ -123,12 +123,12 @@ }, "xunit.core": { "type": "Direct", - "requested": "[2.4.2, )", - "resolved": "2.4.2", - "contentHash": "KB4yGCxNqIVyekhJLXtKSEq6BaXVp/JO3mbGVE1hxypZTLEe7h+sTbAhpA+yZW2dPtXTuiW+C1B2oxxHEkrmOw==", + "requested": "[2.5.0, )", + "resolved": "2.5.0", + "contentHash": "dnV0Mn2s1C0y2m33AylQyMkEyhBQsL4R0302kwSGiEGuY3JwzEmhTa9pnghyMRPliYSs4fXfkEAP+5bKXryGFg==", "dependencies": { - "xunit.extensibility.core": "[2.4.2]", - "xunit.extensibility.execution": "[2.4.2]" + "xunit.extensibility.core": "[2.5.0]", + "xunit.extensibility.execution": "[2.5.0]" } }, "Xunit.DependencyInjection": { @@ -145,9 +145,9 @@ }, "xunit.runner.visualstudio": { "type": "Direct", - "requested": "[2.4.3, )", - "resolved": "2.4.3", - "contentHash": "kZZSmOmKA8OBlAJaquPXnJJLM9RwQ27H7BMVqfMLUcTi9xHinWGJiWksa3D4NEtz0wZ/nxd2mogObvBgJKCRhQ==" + "requested": "[2.5.0, )", + "resolved": "2.5.0", + "contentHash": "+Gp9vuC2431yPyKB15YrOTxCuEAErBQUTIs6CquumX1F073UaPHGW0VE/XVJLMh9W4sXdz3TBkcHdFWZrRn2Hw==" }, "xunit.v3.assert": { "type": "Direct", @@ -1439,8 +1439,8 @@ }, "xunit.extensibility.core": { "type": "Transitive", - "resolved": "2.4.2", - "contentHash": "W1BoXTIN1C6kpVSMw25huSet25ky6IAQUNovu3zGOGN/jWnbgSoTyCrlIhmXSg0tH5nEf8q7h3OjNHOjyu5PfA==", + "resolved": "2.5.0", + "contentHash": "xRm6NIV3i7I+LkjsAJ91Xz2fxJm/oMEi2CYq1G5HlGTgcK1Zo2wNbLO6nKX1VG5FZzXibSdoLwr/MofVvh3mFA==", "dependencies": { "NETStandard.Library": "1.6.1", "xunit.abstractions": "2.0.3" @@ -1448,11 +1448,11 @@ }, "xunit.extensibility.execution": { "type": "Transitive", - "resolved": "2.4.2", - "contentHash": "CZmgcKkwpyo8FlupZdWpJCryrAOWLh1FBPG6gmVZuPQkGQsim/oL4PcP4nfrC2hHgXUFtluvaJ0Sp9PQKUMNpg==", + "resolved": "2.5.0", + "contentHash": "7+v2Bvp+1ew1iMGQVb1glICi8jcNdHbRUX6Ru0dmJBViGdjiS7kyqcX2VxleQhFbKNi+WF0an7/TeTXD283RlQ==", "dependencies": { "NETStandard.Library": "1.6.1", - "xunit.extensibility.core": "[2.4.2]" + "xunit.extensibility.core": "[2.5.0]" } }, "nncase.codegen": { From 2bfceb956f6698d113ad9b027453450a6049b99f Mon Sep 17 00:00:00 2001 From: zhangyang2057 Date: Wed, 13 Sep 2023 20:05:10 +0800 Subject: [PATCH 16/25] Add more benchmark test data to show. (#1089) --- tests/config.toml | 9 ++- tests/inference.py | 112 +++++++++++++++++++++++++++++-------- tests/json2md.py | 57 ++++++++++++++++--- tests/nuc_proxy.py | 53 ++++++++++++------ tests/test_runner.py | 30 ++++++---- tests/test_utils.py | 15 ++++- tests/update_trace_info.py | 97 ++++++++++++++++++++++++++++++++ 7 files changed, 310 insertions(+), 63 deletions(-) create mode 100644 tests/update_trace_info.py diff --git a/tests/config.toml b/tests/config.toml index 604a745df6..11fe4ef48b 100644 --- a/tests/config.toml +++ b/tests/config.toml @@ -2,9 +2,7 @@ name = 'default_config' root = 'tests_output' kmodel_name = 'test.kmodel' desc_name = 'kmodel.desc' -infer_name = 'infer_report.json' dump_hist = false -dump_infer = false [compile_opt] preprocess = false @@ -43,6 +41,13 @@ input_mean = 0.5 input_std = 0.5 quant_scheme = "" +[infer_report_opt] +enabled = false +priority = 100 +kind = 'N/A' +model_name = 'N/A' +report_name = 'infer_report.json' + [generator] [generator.inputs] # ['random', 'bin', 'image', 'constant_of_shape'] diff --git a/tests/inference.py b/tests/inference.py index 52e9deecd2..f0a4912ecb 100644 --- a/tests/inference.py +++ b/tests/inference.py @@ -8,6 +8,8 @@ import json from test_utils import * import time +import subprocess +from update_trace_info import * def data_shape_list_string(data): @@ -24,16 +26,19 @@ def run_inference(self, compiler, target, ptq_enabled, infer_dir): running_on_evb = target in kpu_targets and nuc_ip is not None and nuc_port is not None and test_executable is not None and len( self.inputs) > 0 and len(self.outputs) > 0 - if self.cfg['dump_infer']: - self.infer_dict['case'] = os.path.basename(self.case_dir) - self.infer_dict['target'] = target + if self.cfg['infer_report_opt']['enabled']: + self.infer_report_dict['priority'] = self.cfg['infer_report_opt']['priority'] + self.infer_report_dict['kind'] = self.cfg['infer_report_opt']['kind'] + self.infer_report_dict['model'] = self.cfg['infer_report_opt']['model_name'] + self.infer_report_dict['shape'] = ',
'.join( + map(lambda d: '[' + ','.join(map(lambda x: str(x), d['model_shape'])) + ']', self.inputs)) if ptq_enabled: self.set_quant_opt(compiler) - if self.cfg['dump_infer']: + if self.cfg['infer_report_opt']['enabled']: case = os.path.basename(self.case_dir) - self.infer_dict['if_quant_type'] = self.cfg['ptq_opt']['quant_type'] - self.infer_dict['w_quant_type'] = self.cfg['ptq_opt']['w_quant_type'] + self.infer_report_dict['if_quant_type'] = self.cfg['ptq_opt']['quant_type'] + self.infer_report_dict['w_quant_type'] = self.cfg['ptq_opt']['w_quant_type'] compiler.compile() kmodel = compiler.gencode_tobytes() @@ -52,15 +57,14 @@ def run_inference(self, compiler, target, ptq_enabled, infer_dir): sim.load_model(kmodel) self.set_infer_input(sim, compile_opt) - if self.cfg['dump_infer']: + if self.cfg['infer_report_opt']['enabled']: t1 = time.perf_counter() sim.run() - if self.cfg['dump_infer']: + if self.cfg['infer_report_opt']['enabled']: t = (time.perf_counter() - t1) * 1000 - self.infer_dict['time(ms)'] = str(t) - self.infer_dict['fps'] = str(round(1000 / t, 2)) + self.infer_report_dict['actual_fps'] = str(round(1000 / t, 3)) outputs = self.dump_infer_output(sim, compile_opt, infer_dir) return outputs @@ -171,14 +175,74 @@ def run_evb(self, target, kmodel, compile_opt, infer_dir): # get infer result outputs = [] - result_dict = {} + header_dict = {} ret = client_socket.recv(1024) - result_dict = json.loads(ret.decode()) - if result_dict['type'].find('finish') != -1: - if self.cfg['dump_infer']: - t = result_dict['time'] - self.infer_dict['time(ms)'] = str(t) - self.infer_dict['fps'] = str(round(1000 / t, 2)) + header_dict = json.loads(ret.decode()) + length = header_dict['len'] + + # recv result + count = length // 1024 + left = length % 1024 + + client_socket.sendall(f"pls send detail".encode()) + recv_data = b'' + for i in range(count): + data = client_socket.recv(1024, socket.MSG_WAITALL) + recv_data += data + + if left: + recv_data += client_socket.recv(left, socket.MSG_WAITALL) + + detail = recv_data.decode() + + if header_dict['type'].find('finish') != -1: + if self.cfg['infer_report_opt']['enabled']: + + # update trace info + model_name = self.cfg['infer_report_opt']['model_name'] + infer_result = f'0:{model_name} :\n' + detail + trace_file = search_file(infer_dir, 'trace_info.py') + assert(trace_file != '') + update_trace_info(infer_result, trace_file) + + # roofline fps/mac usage + estimate_file = search_file(infer_dir, 'estimate_fps.py') + assert(estimate_file != '') + + mac_file = search_file(infer_dir, 'mac.csv') + assert(mac_file != '') + + cmd_status, cmd_result = subprocess.getstatusoutput( + f'python3 {estimate_file} {mac_file}') + assert(cmd_status == 0) + data = cmd_result.split(',') + assert(len(data) >= 3) + self.infer_report_dict['roofline_fps'] = data[1].split(':')[-1].strip() + self.infer_report_dict['roofline_mac_usage'] = data[2].split(':')[-1].strip() + + # actual fps + fps_pattern = re.compile( + r"^\|total\s+\|(\d+|\d+.\d+)\s+\|(\d+|\d+.\d+)\s+\|(\d+|\d+.\d+)\s+\|") + buf = io.StringIO(detail) + while True: + line = buf.readline() + if not line: + break + match = fps_pattern.match(line) + if match is not None: + self.infer_report_dict['actual_fps'] = str( + round(1000 / float(match.group(2)), 3)) + break + + # actual mac usage + draw_trace_file = search_file(infer_dir, 'draw_trace.py') + assert(draw_trace_file != '') + cmd_status, cmd_result = subprocess.getstatusoutput( + f'python3 {draw_trace_file} {mac_file}') + assert(cmd_status == 0) + data = cmd_result.split(',') + assert(len(data) >= 1) + self.infer_report_dict['actual_mac_usage'] = data[0].split(':')[-1].strip() client_socket.sendall(f"pls send outputs".encode()) @@ -206,10 +270,14 @@ def run_evb(self, target, kmodel, compile_opt, infer_dir): else: client_socket.close() - if self.cfg['dump_infer']: - self.infer_dict['result'] = 'Fail' - self.infer_dict['remark'] = result_dict['error'] - dump_dict_to_json(self.infer_dict, self.infer_file) - raise Exception(result_dict['error']) + if self.cfg['infer_report_opt']['enabled']: + self.infer_report_dict['result'] = 'Fail' + self.infer_report_dict['remark'] = detail.replace('\n', '
') + # self.infer_report_dict['remark'] = detail + prefix, suffix = os.path.splitext(self.infer_report_file) + json_file = f'{prefix}_{os.path.basename(self.case_dir)}{suffix}' + dump_dict_to_json(self.infer_report_dict, json_file) + + raise Exception(detail) return outputs diff --git a/tests/json2md.py b/tests/json2md.py index 983d859166..a1c2ac01b9 100644 --- a/tests/json2md.py +++ b/tests/json2md.py @@ -1,24 +1,65 @@ import argparse import json -import pandas as pd +import os +from pathlib import Path def json2md(json_file): + file_list = [] + for path in Path(os.path.dirname(json_file)).glob(f'{json_file}*.json'): + file_list.append(path) + json_list = [] - with open(json_file, 'r') as f: - json_list = json.load(f) + for f in file_list: + with open(f, 'r') as f: + json_list.extend(json.load(f)) + assert(len(json_list) > 0) + + # generate dict after sorting + json_list = sorted(json_list, key=lambda d: (d['priority'], d['kind'], d['model'])) + dict = {} + for e in json_list: + kind = e['kind'] + if kind not in dict: + dict[kind] = [] + dict[kind].append(e) + + # generate html table + md = '\n' + + # table head + md += '\t\n' + for key in json_list[0]: + if key != 'priority': + md += f'\t\t\n' + md += '\t\n' + + # table row + for value in dict.values(): + length = len(value) + for i in range(length): + md += '\t\n' + if i == 0: + for k, v in value[i].items(): + if k == 'kind': + md += f'\t\t\n' + elif k != 'priority': + md += f'\t\t\n' + else: + for k, v in value[i].items(): + if k != 'kind' and k != 'priority': + md += f'\t\t\n' + md += '\t\n' - json_list = sorted(json_list, key=lambda d: d['case']) - df = pd.DataFrame.from_records(json_list) - md = df.to_markdown() - md_file = json_file.split('/')[-1].split('.')[0] + '.md' + md += '
{key}
{v}{v}{v}
\n' + md_file = os.path.splitext(json_file)[0] + '.md' with open(md_file, 'w') as f: f.write(md) if __name__ == '__main__': parser = argparse.ArgumentParser(prog="json2md") - parser.add_argument("--json", help='json file', type=str) + parser.add_argument("--json", help='json file or json file prefix', type=str) args = parser.parse_args() json2md(args.json) diff --git a/tests/nuc_proxy.py b/tests/nuc_proxy.py index 408bdc6141..66253657dc 100644 --- a/tests/nuc_proxy.py +++ b/tests/nuc_proxy.py @@ -44,7 +44,7 @@ def write(self, cmd): def read_until(self, expected): self.logger.debug('read begin') data = self.s.read_until(expected.encode()).decode() - self.logger.debug('read end: data = {0}'.format(data)) + self.logger.debug('read end: data = {0}, size = {1}'.format(data, len(data))) return data def run_cmd(self, cmd, expected=''): @@ -63,6 +63,8 @@ def __init__(self, name, cfg, nfs, clear_queue): self.name = name self.infer_queue = queue.Queue(maxsize=clear_queue.maxsize) self.clear_queue = clear_queue + self.username = cfg['username'] + self.password = cfg['password'] self.working_dir = cfg['working_dir'] self.separator = cfg['separator'] @@ -73,10 +75,10 @@ def __init__(self, name, cfg, nfs, clear_queue): # logging mylogger = logging.getLogger() - mylogger.setLevel(logging.INFO) + mylogger.setLevel(logging.DEBUG) rf_handler = logging.handlers.RotatingFileHandler( f'nuc_proxy_{name}.log', mode='a', maxBytes=32 * 1024 * 1024, backupCount=10) - rf_handler.setLevel(logging.INFO) + rf_handler.setLevel(logging.DEBUG) rf_handler.setFormatter(logging.Formatter('%(asctime)s [%(levelname)s] %(message)s')) mylogger.addHandler(rf_handler) self.logger = mylogger @@ -85,6 +87,13 @@ def __init__(self, name, cfg, nfs, clear_queue): self.s0 = MySerial(cfg['uart0'], cfg['baudrate0'], self.logger) self.s1 = MySerial(cfg['uart1'], cfg['baudrate1'], self.logger) + def reboot(self): + # reboot after login + self.s0.run_cmd(self.username) + self.s0.run_cmd(self.password) + self.s0.run_cmd('reboot') + time.sleep(20) + def recv_file(conn, case_dir, logger): conn.sendall(f"pls send file info".encode()) @@ -147,29 +156,39 @@ def infer_worker(target): ret = target.s1.run_cmd(cmd, separator) # infer result - dict = {'type': 'finish', 'time': 0.0, 'error': ''} + dict = {'type': 'finish', 'len': 0} if ret.find('terminate') != -1 or ret.find('Exception') != -1: - target.logger.error('infer exception') - err = f'infer exception: {ret}' + err = 'infer exception' + target.logger.error(err) + msg = f'{err}: {ret}'.encode() dict['type'] = 'exception' - dict['error'] = err[0:1024] + dict['len'] = len(msg) conn.sendall(json.dumps(dict).encode()) + dummy = conn.recv(1024) + conn.sendall(msg) + + # reboot target when exception(it is likely that next test case will fail) + target.reboot() elif ret.find(separator) == -1: - # reboot target when timeout - target.logger.error('reboot for timeout') + err = 'infer timeout' + target.logger.error(err) + msg = f'{err}'.encode() dict['type'] = 'timeout' - dict['error'] = 'infer timeout' + dict['len'] = len(msg) conn.sendall(json.dumps(dict).encode()) + dummy = conn.recv(1024) + conn.sendall(msg) - # reboot after login - target.s0.run_cmd('root') - target.s0.run_cmd('') - target.s0.run_cmd('reboot') - time.sleep(20) + # reboot target when timeout + target.reboot() else: - dict['time'] = float(ret.split('\n')[-2].split()[1]) + msg = ret.encode() + dict['type'] = 'finish' + dict['len'] = len(msg) conn.sendall(json.dumps(dict).encode()) dummy = conn.recv(1024) + conn.sendall(msg) + dummy = conn.recv(1024) # send outputs for i in range(output_num): @@ -202,6 +221,8 @@ def main(): port = 10000 nfs = '/data/nfs' [k230] + username = 'root' + password = '' working_dir = '/sharefs' separator = '>' uart0 = '/dev/ttyUSB0' diff --git a/tests/test_runner.py b/tests/test_runner.py index 7ac0613ffa..2207ffefda 100644 --- a/tests/test_runner.py +++ b/tests/test_runner.py @@ -55,15 +55,20 @@ def __init__(self, case_name, override_cfg: str = None) -> None: # used for tag dynamic model for onnx simplify self.dynamic = False - if self.cfg['dump_infer']: - self.infer_file = test_utils.infer_file(self.cfg['infer_name']) - self.infer_dict = { - 'case': 'unknown', - 'target': 'cpu', + if self.cfg['infer_report_opt']['enabled']: + self.infer_report_file = test_utils.infer_report_file( + self.cfg['infer_report_opt']['report_name']) + self.infer_report_dict = { + 'priority': 100, + 'kind': 'N/A', + 'model': 'N/A', + 'shape': 'N/A', 'if_quant_type': 'uint8', 'w_quant_type': 'uint8', - 'time(ms)': 'N/A', - 'fps': 'N/A', + 'roofline_fps': 'N/A', + 'actual_fps': 'N/A', + 'roofline_mac_usage': 'N/A', + 'actual_mac_usage': 'N/A', 'result': 'Pass', 'remark': 'N/A' } @@ -183,7 +188,6 @@ def validte_config(self, config): if test_utils.in_ci(): config['dump_hist'] = False config['compile_opt']['dump_asm'] = False - config['compile_opt']['dump_ir'] = False config['compile_opt']['dump_quant_error'] = False # check target @@ -265,10 +269,12 @@ def run(self, model_file: Union[List[str], str]): judge, result = self.compare_results( expected, actual, stage, k_target, v_target['similarity_name'], k_mode, v_mode['threshold'], dump_hist, mode_dir) - if stage == 'infer' and self.cfg['dump_infer']: - self.infer_dict['result'] = 'Pass' if judge else 'Fail' - self.infer_dict['remark'] = result.replace('\n', '
') - dump_dict_to_json(self.infer_dict, self.infer_file) + if stage == 'infer' and self.cfg['infer_report_opt']['enabled']: + self.infer_report_dict['result'] = 'Pass' if judge else 'Fail' + self.infer_report_dict['remark'] = result.replace('\n', '
') + prefix, suffix = os.path.splitext(self.infer_report_file) + json_file = f'{prefix}_{os.path.basename(self.case_dir)}{suffix}' + dump_dict_to_json(self.infer_report_dict, json_file) if not judge: if test_utils.in_ci(): self.clear(self.case_dir) diff --git a/tests/test_utils.py b/tests/test_utils.py index c2d3894868..c136800c48 100644 --- a/tests/test_utils.py +++ b/tests/test_utils.py @@ -1,6 +1,7 @@ import os import json import numpy as np +from pathlib import Path def dump_bin_file(file: str, ndarray: np.array): @@ -61,9 +62,17 @@ def nuc_port(): return os.getenv('NUC_PROXY_PORT') -def test_executable(target): +def test_executable(target: str): return os.getenv('TEST_EXECUTABLE_{0}'.format(target.upper())) -def infer_file(file): - return os.getenv('INFER_FILE', file) +def infer_report_file(default: str): + return os.getenv('INFER_REPORT_FILE', default) + + +def search_file(dir: str, file: str): + p = '' + for path in Path(dir).rglob(file): + p = path + break + return p diff --git a/tests/update_trace_info.py b/tests/update_trace_info.py new file mode 100644 index 0000000000..71cb6f85a9 --- /dev/null +++ b/tests/update_trace_info.py @@ -0,0 +1,97 @@ +import re +from enum import IntFlag, auto +import os +from typing import Tuple, List +import io + +ITEM_PATTERN = re.compile( + r"^DataItem\(\d+, \"(\w+)\", (True|False), (0\.0), (0\.0), (0\.0)\),", re.RegexFlag.MULTILINE) + + +class Status(IntFlag): + find_titile = auto() + find_time = auto() + + +def find_titile(line: str) -> str: + title_pattern = re.compile(r"^\d+:([a-zA-Z0-9_.-]+)\s:\s") + match = title_pattern.match(line) + if match is None: + return None + return match.group(1) + + +def find_time(line: str) -> Tuple[str, str]: + time_pattern = re.compile(r"^\|(\w+)\s+\|(\d+|\d+.\d+)\s+\|(\d+|\d+.\d+)\s+\|") + match = time_pattern.match(line) + if match is None: + return None + return match.group(2), match.group(3) + + +def find_items(info_path: str) -> int: + if not os.path.exists(info_path): + return -1 + context = None + with open(info_path, 'r') as f: + context = f.read() + return len(ITEM_PATTERN.findall(context)) + + +def update_items(info_path: str, times: List[Tuple[str, str]]): + if not os.path.exists(info_path): + return -1 + context = None + with open(info_path, 'r') as f: + context = f.read() + + cnt = {'i': 0} + + def update(match: re.Match): + i = cnt['i'] + time = times[i] + new = f'DataItem({i}, \"{match.group(1)}\", {match.group(2)}, {time[0]}, {time[1]}, {float(time[1])-float(time[0]):.6f}),' + cnt['i'] += 1 + return new + + new_context = ITEM_PATTERN.sub(update, context) + with open(info_path, 'w') as f: + f.write(new_context) + + +def update_trace_info(infer_result: str, info_file: str): + status = Status.find_titile + title = None + item_num = -1 + times = [] + + buf = io.StringIO(infer_result) + while True: + line = buf.readline() + if not line: + break + print('line = {0}'.format(line)) + + if status == Status.find_titile: + title = find_titile(line) + print('title = {0}'.format(title)) + if title: + status = Status.find_time + item_num = find_items(info_file) + print('item_num = {0}'.format(item_num)) + if item_num == -1 or item_num == 0: + item_num = -1 + status = Status.find_titile + continue + + if status is Status.find_time: + time = find_time(line) + print('time = {0}'.format(time)) + if time: + times.append(time) + if (len(times) == item_num): + update_items(info_file, times) + print('time updated!') + times.clear() + status = Status.find_titile + continue From 85011d810954dc0694c882b28d9c43635013c55d Mon Sep 17 00:00:00 2001 From: FusionBolt <59008347+FusionBolt@users.noreply.github.com> Date: Fri, 15 Sep 2023 17:42:46 +0800 Subject: [PATCH 17/25] GNNE-1891 ShapeBucket Optimize (#1088) * Optimize ShapeBucket --------- Co-authored-by: FusionBolt --- .../CodeGen/StackVM/CodeGenVisitor.g.cs | 17 +- .../CodeGen/StackVM/StackVMEmitter.g.cs | 153 +++-- .../nncase/kernels/stackvm/tensor_ops.h | 24 +- .../nncase/runtime/stackvm/op_reader.h | 62 +- .../include/nncase/runtime/stackvm/opcode.h | 143 +++-- .../src/kernels/stackvm/reference/pad.cpp | 14 +- src/Native/src/kernels/stackvm/shape_ops.cpp | 108 +++- src/Native/src/runtime/stackvm/op_reader.cpp | 17 +- src/Native/src/runtime/stackvm/ops/tensor.cpp | 81 ++- .../runtime/stackvm/runtime_function_ops.h | 7 +- src/Nncase.Compiler/Compiler.cs | 51 +- src/Nncase.Core/IR/ShapeExpr/Functional.cs | 10 + src/Nncase.Core/IR/ShapeExpr/GetPaddings.cs | 40 ++ src/Nncase.Core/IR/ShapeExpr/ReshapeShape.cs | 24 + src/Nncase.Core/IR/ShapeExpr/SqueezeShape.cs | 24 + .../IR/ShapeExpr/TransposeShape.cs | 24 + .../IR/ShapeExpr/UnsqueezeShape.cs | 21 + src/Nncase.Core/Utilities/ShapeExprUtility.cs | 25 +- src/Nncase.Evaluator/Math/Binary.cs | 2 +- src/Nncase.Evaluator/Math/MatMul.cs | 2 +- src/Nncase.Evaluator/Math/Reduce.cs | 6 +- src/Nncase.Evaluator/NN/BatchToSpace.cs | 6 +- src/Nncase.Evaluator/NN/Conv2D.cs | 8 +- src/Nncase.Evaluator/NN/Pad.cs | 6 +- src/Nncase.Evaluator/NN/SpaceToBatch.cs | 6 +- src/Nncase.Evaluator/ShapeEvaluateContext.cs | 19 +- src/Nncase.Evaluator/ShapeEvaluateVisitor.cs | 2 +- .../ShapeEvaluatorProvider.cs | 3 +- .../ShapeExpr/BroadcastShape.cs | 5 +- src/Nncase.Evaluator/ShapeExpr/GetPaddings.cs | 89 +++ .../ShapeExpr/ReshapeShape.cs | 50 ++ .../ShapeExpr/ShapeExprModule.cs | 5 + .../ShapeExpr/SqueezeShape.cs | 57 ++ .../ShapeExpr/TransposeShape.cs | 51 ++ .../ShapeExpr/UnsqueezeShape.cs | 57 ++ src/Nncase.Evaluator/Tensors/Concat.cs | 4 +- src/Nncase.Evaluator/Tensors/Range.cs | 2 +- src/Nncase.Evaluator/Tensors/Reshape.cs | 71 +-- src/Nncase.Evaluator/Tensors/Slice.cs | 2 +- src/Nncase.Evaluator/Tensors/Squeeze.cs | 23 +- src/Nncase.Evaluator/Tensors/Stack.cs | 4 +- src/Nncase.Evaluator/Tensors/Tile.cs | 2 +- src/Nncase.Evaluator/Tensors/Transpose.cs | 12 +- src/Nncase.Evaluator/Tensors/UnSqueeze.cs | 24 +- src/Nncase.Importer/TFLite/Conv2D.cs | 14 +- src/Nncase.Importer/TFLite/Conv2DTranspose.cs | 8 +- src/Nncase.Importer/Util.cs | 8 +- .../Rules/Neutral/FoldReshape.cs | 5 + .../Rules/Neutral/FoldSqueeze.cs | 62 ++ .../Rules/Neutral/FoldTranspose.cs | 5 + .../Rules/Neutral/SplitSpaceToBatch.cs | 180 ++++++ .../Rules/ShapeBucket/FoldBucketReshape.cs | 44 -- .../Rules/ShapeBucket/FoldNopTuple.cs | 64 +++ .../Rules/ShapeBucket/MergeBucketFusion.cs | 48 +- .../Rules/ShapeBucket/MergeCallToFusion.cs | 44 +- .../Rules/ShapeBucket/RecordFusionShape.cs | 101 ++-- .../Rules/ShapeBucket/ShapeBucket.cs | 536 +++++++++++++----- .../Rules/ShapeBucket/ShapeBucketHelper.cs | 249 +++++++- .../Rules/ShapeExpr/FoldBroadcastShape.cs | 76 +++ .../Rules/ShapeExpr/FoldGetItemShapeOf.cs | 41 ++ .../Rules/ShapeExpr/FoldSplitShapeOf.cs | 57 ++ .../Rules/ShapeExpr/GatherToGetItem.cs | 24 + .../Rules/ShapeExpr/SliceToGetItem.cs | 44 ++ .../TransformTestBase.cs | 1 + src/Nncase.Tests/Importer/UnitTestUtil.cs | 17 - .../Rules/Neutral/UnitTestFoldSqueeze.cs | 33 ++ .../Neutral/UnitTestSplitSpaceToBatch.cs | 39 ++ .../Rules/ShapeBucket/ShapeBucketTest.cs | 168 +++++- .../ShapeExpr/UnitTestFoldBroadcastShape.cs | 31 + .../ShapeExpr/UnitTestFoldGetItemShapeOf.cs | 45 ++ .../ShapeExpr/UnitTestFoldSplitShapeOf.cs | 28 + .../ShapeExpr/UnitTestGatherToGetItem.cs | 35 ++ .../Rules/ShapeExpr/UnitTestSliceToGetItem.cs | 36 ++ test.md | 75 --- testEnvironments.json | 17 - 75 files changed, 2768 insertions(+), 730 deletions(-) create mode 100644 src/Nncase.Core/IR/ShapeExpr/GetPaddings.cs create mode 100644 src/Nncase.Core/IR/ShapeExpr/ReshapeShape.cs create mode 100644 src/Nncase.Core/IR/ShapeExpr/SqueezeShape.cs create mode 100644 src/Nncase.Core/IR/ShapeExpr/TransposeShape.cs create mode 100644 src/Nncase.Core/IR/ShapeExpr/UnsqueezeShape.cs create mode 100644 src/Nncase.Evaluator/ShapeExpr/GetPaddings.cs create mode 100644 src/Nncase.Evaluator/ShapeExpr/ReshapeShape.cs create mode 100644 src/Nncase.Evaluator/ShapeExpr/SqueezeShape.cs create mode 100644 src/Nncase.Evaluator/ShapeExpr/TransposeShape.cs create mode 100644 src/Nncase.Evaluator/ShapeExpr/UnsqueezeShape.cs create mode 100644 src/Nncase.Passes/Rules/Neutral/FoldSqueeze.cs create mode 100644 src/Nncase.Passes/Rules/Neutral/SplitSpaceToBatch.cs delete mode 100644 src/Nncase.Passes/Rules/ShapeBucket/FoldBucketReshape.cs create mode 100644 src/Nncase.Passes/Rules/ShapeBucket/FoldNopTuple.cs create mode 100644 src/Nncase.Passes/Rules/ShapeExpr/FoldBroadcastShape.cs create mode 100644 src/Nncase.Passes/Rules/ShapeExpr/FoldGetItemShapeOf.cs create mode 100644 src/Nncase.Passes/Rules/ShapeExpr/FoldSplitShapeOf.cs create mode 100644 src/Nncase.Passes/Rules/ShapeExpr/GatherToGetItem.cs create mode 100644 src/Nncase.Passes/Rules/ShapeExpr/SliceToGetItem.cs create mode 100644 src/Nncase.Tests/Rules/Neutral/UnitTestFoldSqueeze.cs create mode 100644 src/Nncase.Tests/Rules/Neutral/UnitTestSplitSpaceToBatch.cs create mode 100644 src/Nncase.Tests/Rules/ShapeExpr/UnitTestFoldBroadcastShape.cs create mode 100644 src/Nncase.Tests/Rules/ShapeExpr/UnitTestFoldGetItemShapeOf.cs create mode 100644 src/Nncase.Tests/Rules/ShapeExpr/UnitTestFoldSplitShapeOf.cs create mode 100644 src/Nncase.Tests/Rules/ShapeExpr/UnitTestGatherToGetItem.cs create mode 100644 src/Nncase.Tests/Rules/ShapeExpr/UnitTestSliceToGetItem.cs delete mode 100644 test.md delete mode 100644 testEnvironments.json diff --git a/modules/Nncase.Modules.StackVM/CodeGen/StackVM/CodeGenVisitor.g.cs b/modules/Nncase.Modules.StackVM/CodeGen/StackVM/CodeGenVisitor.g.cs index b900856080..2cfd50e458 100644 --- a/modules/Nncase.Modules.StackVM/CodeGen/StackVM/CodeGenVisitor.g.cs +++ b/modules/Nncase.Modules.StackVM/CodeGen/StackVM/CodeGenVisitor.g.cs @@ -1,6 +1,6 @@ // Copyright (c) Canaan Inc. All rights reserved. // Licensed under the Apache license. See LICENSE file in the project root for full license information. -/* This file is generated by tools/stackvm_gen/IsaGen at 2023/7/12 17:07:39 +08:00. */ +/* This file is generated by tools/stackvm_gen/IsaGen at 2023/9/5 19:40:30 +08:00. */ using System; using System.Collections.Generic; @@ -271,9 +271,24 @@ private void EmitTensorCall(Op op) case IR.ShapeExpr.Conv2DTransposeShape top: Emitter.T.Conv2DTransposeShape(); break; + case IR.ShapeExpr.GetPaddings top: + Emitter.T.GetPaddings(); + break; case IR.ShapeExpr.MatMulShape top: Emitter.T.MatMulShape(); break; + case IR.ShapeExpr.ReshapeShape top: + Emitter.T.ReshapeShape(); + break; + case IR.ShapeExpr.SqueezeShape top: + Emitter.T.SqueezeShape(); + break; + case IR.ShapeExpr.TransposeShape top: + Emitter.T.TransposeShape(); + break; + case IR.ShapeExpr.UnsqueezeShape top: + Emitter.T.UnsqueezeShape(); + break; case IR.Random.Normal top: Emitter.T.Normal(top.Type); break; diff --git a/modules/Nncase.Modules.StackVM/CodeGen/StackVM/StackVMEmitter.g.cs b/modules/Nncase.Modules.StackVM/CodeGen/StackVM/StackVMEmitter.g.cs index d69739ded8..6e2184c5ea 100644 --- a/modules/Nncase.Modules.StackVM/CodeGen/StackVM/StackVMEmitter.g.cs +++ b/modules/Nncase.Modules.StackVM/CodeGen/StackVM/StackVMEmitter.g.cs @@ -1,6 +1,6 @@ // Copyright (c) Canaan Inc. All rights reserved. // Licensed under the Apache license. See LICENSE file in the project root for full license information. -/* This file is generated by tools/stackvm_gen/IsaGen at 2023/7/12 17:07:39 +08:00. */ +/* This file is generated by tools/stackvm_gen/IsaGen at 2023/9/5 19:40:30 +08:00. */ using System; using System.Collections.Generic; @@ -876,52 +876,59 @@ public void GetItem() } ///. - public void Hardmax() + public void GetPaddings() { _emitter.Write((byte)100); _emitter.Write((ushort)32); } ///. - public void HardSigmoid() + public void Hardmax() { _emitter.Write((byte)100); _emitter.Write((ushort)33); } ///. - public void HardSwish() + public void HardSigmoid() { _emitter.Write((byte)100); _emitter.Write((ushort)34); } ///. - public void IndexOf() + public void HardSwish() { _emitter.Write((byte)100); _emitter.Write((ushort)35); } ///. - public void InstanceNormalization() + public void IndexOf() { _emitter.Write((byte)100); _emitter.Write((ushort)36); } ///. - public void L2Normalization() + public void InstanceNormalization() { _emitter.Write((byte)100); _emitter.Write((ushort)37); } ///. - public void LayerNorm(int axis, float epsilon) + public void L2Normalization() { _emitter.Write((byte)100); _emitter.Write((ushort)38); + } + + ///. + public void LayerNorm(int axis, float epsilon) + { + _emitter.Write((byte)100); + _emitter.Write((ushort)39); _emitter.Write(axis); _emitter.Write(epsilon); } @@ -930,35 +937,35 @@ public void LayerNorm(int axis, float epsilon) public void LeakyRelu() { _emitter.Write((byte)100); - _emitter.Write((ushort)39); + _emitter.Write((ushort)40); } ///. public void LogSoftmax() { _emitter.Write((byte)100); - _emitter.Write((ushort)40); + _emitter.Write((ushort)41); } ///. public void LpNormalization() { _emitter.Write((byte)100); - _emitter.Write((ushort)41); + _emitter.Write((ushort)42); } ///. public void LRN() { _emitter.Write((byte)100); - _emitter.Write((ushort)42); + _emitter.Write((ushort)43); } ///. public void LSTM(LSTMDirection direction, LSTMLayout layout, string[] activations) { _emitter.Write((byte)100); - _emitter.Write((ushort)43); + _emitter.Write((ushort)44); _emitter.Write((int)direction); _emitter.Write((int)layout); _emitter.Write(activations); @@ -968,21 +975,21 @@ public void LSTM(LSTMDirection direction, LSTMLayout layout, string[] activation public void MatMul() { _emitter.Write((byte)100); - _emitter.Write((ushort)44); + _emitter.Write((ushort)45); } ///. public void MatMulShape() { _emitter.Write((byte)100); - _emitter.Write((ushort)45); + _emitter.Write((ushort)46); } ///. public void Normal(DataType type) { _emitter.Write((byte)100); - _emitter.Write((ushort)46); + _emitter.Write((ushort)47); _emitter.Write(type); } @@ -990,7 +997,7 @@ public void Normal(DataType type) public void NormalLike(DataType type) { _emitter.Write((byte)100); - _emitter.Write((ushort)47); + _emitter.Write((ushort)48); _emitter.Write(type); } @@ -998,7 +1005,7 @@ public void NormalLike(DataType type) public void OneHot(OneHotMode oneHotMode) { _emitter.Write((byte)100); - _emitter.Write((ushort)48); + _emitter.Write((ushort)49); _emitter.Write((byte)oneHotMode); } @@ -1006,7 +1013,7 @@ public void OneHot(OneHotMode oneHotMode) public void Pad(PadMode padMode) { _emitter.Write((byte)100); - _emitter.Write((ushort)49); + _emitter.Write((ushort)50); _emitter.Write((byte)padMode); } @@ -1014,21 +1021,21 @@ public void Pad(PadMode padMode) public void PRelu() { _emitter.Write((byte)100); - _emitter.Write((ushort)50); + _emitter.Write((ushort)51); } ///. public void Prod() { _emitter.Write((byte)100); - _emitter.Write((ushort)51); + _emitter.Write((ushort)52); } ///. public void Quantize(DataType targetType) { _emitter.Write((byte)100); - _emitter.Write((ushort)52); + _emitter.Write((ushort)53); _emitter.Write(targetType); } @@ -1036,7 +1043,7 @@ public void Quantize(DataType targetType) public void QuantParamOf(QuantMode quantMode) { _emitter.Write((byte)100); - _emitter.Write((ushort)53); + _emitter.Write((ushort)54); _emitter.Write((int)quantMode); } @@ -1044,14 +1051,14 @@ public void QuantParamOf(QuantMode quantMode) public void Range() { _emitter.Write((byte)100); - _emitter.Write((ushort)54); + _emitter.Write((ushort)55); } ///. public void RangeOf(bool isRangeOfWeight) { _emitter.Write((byte)100); - _emitter.Write((ushort)55); + _emitter.Write((ushort)56); _emitter.Write(isRangeOfWeight); } @@ -1059,14 +1066,14 @@ public void RangeOf(bool isRangeOfWeight) public void Rank() { _emitter.Write((byte)100); - _emitter.Write((ushort)56); + _emitter.Write((ushort)57); } ///. public void Reduce(ReduceOp reduceOp) { _emitter.Write((byte)100); - _emitter.Write((ushort)57); + _emitter.Write((ushort)58); _emitter.Write((byte)reduceOp); } @@ -1074,7 +1081,7 @@ public void Reduce(ReduceOp reduceOp) public void ReduceArg(ReduceArgOp reduceArgOp, DataType destType) { _emitter.Write((byte)100); - _emitter.Write((ushort)58); + _emitter.Write((ushort)59); _emitter.Write((byte)reduceArgOp); _emitter.Write(destType); } @@ -1083,7 +1090,7 @@ public void ReduceArg(ReduceArgOp reduceArgOp, DataType destType) public void ReduceWindow2D(ReduceOp reduceOp) { _emitter.Write((byte)100); - _emitter.Write((ushort)59); + _emitter.Write((ushort)60); _emitter.Write((byte)reduceOp); } @@ -1091,21 +1098,21 @@ public void ReduceWindow2D(ReduceOp reduceOp) public void Relu() { _emitter.Write((byte)100); - _emitter.Write((ushort)60); + _emitter.Write((ushort)61); } ///. public void Relu6() { _emitter.Write((byte)100); - _emitter.Write((ushort)61); + _emitter.Write((ushort)62); } ///. public void Require(string message, bool canFoldConstCall) { _emitter.Write((byte)100); - _emitter.Write((ushort)62); + _emitter.Write((ushort)63); _emitter.Write(message); _emitter.Write(canFoldConstCall); } @@ -1114,14 +1121,21 @@ public void Require(string message, bool canFoldConstCall) public void Reshape() { _emitter.Write((byte)100); - _emitter.Write((ushort)63); + _emitter.Write((ushort)64); + } + + ///. + public void ReshapeShape() + { + _emitter.Write((byte)100); + _emitter.Write((ushort)65); } ///. public void ResizeImage(ImageResizeMode resizeMode, ImageResizeTransformationMode transformationMode, ImageResizeNearestMode nearestMode, bool isTFResize) { _emitter.Write((byte)100); - _emitter.Write((ushort)64); + _emitter.Write((ushort)66); _emitter.Write((byte)resizeMode); _emitter.Write((int)transformationMode); _emitter.Write((int)nearestMode); @@ -1132,147 +1146,161 @@ public void ResizeImage(ImageResizeMode resizeMode, ImageResizeTransformationMod public void ReverseSequence() { _emitter.Write((byte)100); - _emitter.Write((ushort)65); + _emitter.Write((ushort)67); } ///. public void ScatterND() { _emitter.Write((byte)100); - _emitter.Write((ushort)66); + _emitter.Write((ushort)68); } ///. public void Select() { _emitter.Write((byte)100); - _emitter.Write((ushort)67); + _emitter.Write((ushort)69); } ///. public void Selu() { _emitter.Write((byte)100); - _emitter.Write((ushort)68); + _emitter.Write((ushort)70); } ///. public void ShapeOf() { _emitter.Write((byte)100); - _emitter.Write((ushort)69); + _emitter.Write((ushort)71); } ///. public void Sigmoid() { _emitter.Write((byte)100); - _emitter.Write((ushort)70); + _emitter.Write((ushort)72); } ///. public void SizeOf() { _emitter.Write((byte)100); - _emitter.Write((ushort)71); + _emitter.Write((ushort)73); } ///. public void Slice() { _emitter.Write((byte)100); - _emitter.Write((ushort)72); + _emitter.Write((ushort)74); } ///. public void Softmax() { _emitter.Write((byte)100); - _emitter.Write((ushort)73); + _emitter.Write((ushort)75); } ///. public void Softplus() { _emitter.Write((byte)100); - _emitter.Write((ushort)74); + _emitter.Write((ushort)76); } ///. public void Softsign() { _emitter.Write((byte)100); - _emitter.Write((ushort)75); + _emitter.Write((ushort)77); } ///. public void SpaceToBatch() { _emitter.Write((byte)100); - _emitter.Write((ushort)76); + _emitter.Write((ushort)78); } ///. public void Split() { _emitter.Write((byte)100); - _emitter.Write((ushort)77); + _emitter.Write((ushort)79); } ///. public void Squeeze() { _emitter.Write((byte)100); - _emitter.Write((ushort)78); + _emitter.Write((ushort)80); + } + + ///. + public void SqueezeShape() + { + _emitter.Write((byte)100); + _emitter.Write((ushort)81); } ///. public void Stack() { _emitter.Write((byte)100); - _emitter.Write((ushort)79); + _emitter.Write((ushort)82); } ///. public void Swish() { _emitter.Write((byte)100); - _emitter.Write((ushort)80); + _emitter.Write((ushort)83); } ///. public void Tile() { _emitter.Write((byte)100); - _emitter.Write((ushort)81); + _emitter.Write((ushort)84); } ///. public void TopK() { _emitter.Write((byte)100); - _emitter.Write((ushort)82); + _emitter.Write((ushort)85); } ///. public void Transpose() { _emitter.Write((byte)100); - _emitter.Write((ushort)83); + _emitter.Write((ushort)86); + } + + ///. + public void TransposeShape() + { + _emitter.Write((byte)100); + _emitter.Write((ushort)87); } ///. public void Trilu() { _emitter.Write((byte)100); - _emitter.Write((ushort)84); + _emitter.Write((ushort)88); } ///. public void Unary(UnaryOp unaryOp) { _emitter.Write((byte)100); - _emitter.Write((ushort)85); + _emitter.Write((ushort)89); _emitter.Write((byte)unaryOp); } @@ -1280,7 +1308,7 @@ public void Unary(UnaryOp unaryOp) public void Uniform(DataType type) { _emitter.Write((byte)100); - _emitter.Write((ushort)86); + _emitter.Write((ushort)90); _emitter.Write(type); } @@ -1288,7 +1316,7 @@ public void Uniform(DataType type) public void UniformLike(DataType type) { _emitter.Write((byte)100); - _emitter.Write((ushort)87); + _emitter.Write((ushort)91); _emitter.Write(type); } @@ -1296,14 +1324,21 @@ public void UniformLike(DataType type) public void Unsqueeze() { _emitter.Write((byte)100); - _emitter.Write((ushort)88); + _emitter.Write((ushort)92); + } + + ///. + public void UnsqueezeShape() + { + _emitter.Write((byte)100); + _emitter.Write((ushort)93); } ///. public void Where(bool isTfWhere) { _emitter.Write((byte)100); - _emitter.Write((ushort)89); + _emitter.Write((ushort)94); _emitter.Write(isTfWhere); } } diff --git a/src/Native/include/nncase/kernels/stackvm/tensor_ops.h b/src/Native/include/nncase/kernels/stackvm/tensor_ops.h index db59425a29..e918f22f25 100644 --- a/src/Native/include/nncase/kernels/stackvm/tensor_ops.h +++ b/src/Native/include/nncase/kernels/stackvm/tensor_ops.h @@ -1,4 +1,4 @@ -/* This file is generated by tools/stackvm_gen/IsaGen at 2023/7/12 17:07:39 +/* This file is generated by tools/stackvm_gen/IsaGen at 2023/9/5 19:40:29 * +08:00. * * Copyright 2019-2021 Canaan Inc. @@ -178,6 +178,12 @@ NNCASE_API result get_item(value_t input, value_t index, value_t output = nullptr, kernel_context &context = default_kernel_context()); +NNCASE_API result +get_paddings(value_t input_shape, value_t weights_shape, value_t strides, + value_t dilations, value_t same, value_t lower, + value_t output = nullptr, + kernel_context &context = default_kernel_context()); + NNCASE_API result hard_sigmoid(value_t input, value_t alpha, value_t beta, value_t output = nullptr, @@ -330,6 +336,10 @@ NNCASE_API result reshape(value_t input, value_t shape, value_t output = nullptr, kernel_context &context = default_kernel_context()); +NNCASE_API result +reshape_shape(value_t input_shape, value_t shape, value_t output = nullptr, + kernel_context &context = default_kernel_context()); + NNCASE_API result resize_image( runtime::stackvm::image_resize_mode_t resize_mode, runtime::stackvm::image_resize_transformation_mode_t transformation_mode, @@ -400,6 +410,10 @@ NNCASE_API result squeeze(value_t input, value_t dim, value_t output = nullptr, kernel_context &context = default_kernel_context()); +NNCASE_API result +squeeze_shape(value_t input_shape, value_t dim, value_t output = nullptr, + kernel_context &context = default_kernel_context()); + NNCASE_API result stack(value_t inputs, value_t axis, value_t output = nullptr, kernel_context &context = default_kernel_context()); @@ -421,6 +435,10 @@ NNCASE_API result transpose(value_t input, value_t perm, value_t output = nullptr, kernel_context &context = default_kernel_context()); +NNCASE_API result +transpose_shape(value_t input_shape, value_t perm, value_t output = nullptr, + kernel_context &context = default_kernel_context()); + NNCASE_API result trilu(value_t input, value_t k, value_t upper, value_t output = nullptr, kernel_context &context = default_kernel_context()); @@ -444,6 +462,10 @@ NNCASE_API result unsqueeze(value_t input, value_t dim, value_t output = nullptr, kernel_context &context = default_kernel_context()); +NNCASE_API result +unsqueeze_shape(value_t input_shape, value_t dim, value_t output = nullptr, + kernel_context &context = default_kernel_context()); + NNCASE_API result where(bool is_tf_where, value_t cond, value_t x, value_t y, value_t output = nullptr, diff --git a/src/Native/include/nncase/runtime/stackvm/op_reader.h b/src/Native/include/nncase/runtime/stackvm/op_reader.h index 5de273cab1..80372463e4 100644 --- a/src/Native/include/nncase/runtime/stackvm/op_reader.h +++ b/src/Native/include/nncase/runtime/stackvm/op_reader.h @@ -1,4 +1,4 @@ -/* This file is generated by tools/stackvm_gen/IsaGen at 2023/7/12 17:07:39 +/* This file is generated by tools/stackvm_gen/IsaGen at 2023/9/5 19:40:29 * +08:00. * * Copyright 2019-2021 Canaan Inc. @@ -997,6 +997,14 @@ template <> struct tensor_op_reader { } }; +template <> struct tensor_op_reader { + tensor_get_paddings_op_t + operator()(NNCASE_UNUSED span_reader &reader) const { + tensor_get_paddings_op_t op; + return op; + } +}; + template <> struct tensor_op_reader { tensor_hard_sigmoid_op_t operator()(NNCASE_UNUSED span_reader &reader) const { @@ -1257,6 +1265,14 @@ template <> struct tensor_op_reader { } }; +template <> struct tensor_op_reader { + tensor_reshape_shape_op_t + operator()(NNCASE_UNUSED span_reader &reader) const { + tensor_reshape_shape_op_t op; + return op; + } +}; + template <> struct tensor_op_reader { tensor_resize_image_op_t operator()(NNCASE_UNUSED span_reader &reader) const { @@ -1373,6 +1389,14 @@ template <> struct tensor_op_reader { } }; +template <> struct tensor_op_reader { + tensor_squeeze_shape_op_t + operator()(NNCASE_UNUSED span_reader &reader) const { + tensor_squeeze_shape_op_t op; + return op; + } +}; + template <> struct tensor_op_reader { tensor_stack_op_t operator()(NNCASE_UNUSED span_reader &reader) const { tensor_stack_op_t op; @@ -1408,6 +1432,14 @@ template <> struct tensor_op_reader { } }; +template <> struct tensor_op_reader { + tensor_transpose_shape_op_t + operator()(NNCASE_UNUSED span_reader &reader) const { + tensor_transpose_shape_op_t op; + return op; + } +}; + template <> struct tensor_op_reader { tensor_trilu_op_t operator()(NNCASE_UNUSED span_reader &reader) const { tensor_trilu_op_t op; @@ -1447,6 +1479,14 @@ template <> struct tensor_op_reader { } }; +template <> struct tensor_op_reader { + tensor_unsqueeze_shape_op_t + operator()(NNCASE_UNUSED span_reader &reader) const { + tensor_unsqueeze_shape_op_t op; + return op; + } +}; + template <> struct tensor_op_reader { tensor_where_op_t operator()(NNCASE_UNUSED span_reader &reader) const { tensor_where_op_t op; @@ -1589,6 +1629,10 @@ class NNCASE_API tensor_op_visitor { return default_visit(tensor_function_t::get_item, &op); } virtual result + visit(NNCASE_UNUSED const tensor_get_paddings_op_t &op) noexcept { + return default_visit(tensor_function_t::get_paddings, &op); + } + virtual result visit(NNCASE_UNUSED const tensor_hard_sigmoid_op_t &op) noexcept { return default_visit(tensor_function_t::hard_sigmoid, &op); } @@ -1717,6 +1761,10 @@ class NNCASE_API tensor_op_visitor { return default_visit(tensor_function_t::reshape, &op); } virtual result + visit(NNCASE_UNUSED const tensor_reshape_shape_op_t &op) noexcept { + return default_visit(tensor_function_t::reshape_shape, &op); + } + virtual result visit(NNCASE_UNUSED const tensor_resize_image_op_t &op) noexcept { return default_visit(tensor_function_t::resize_image, &op); } @@ -1777,6 +1825,10 @@ class NNCASE_API tensor_op_visitor { return default_visit(tensor_function_t::squeeze, &op); } virtual result + visit(NNCASE_UNUSED const tensor_squeeze_shape_op_t &op) noexcept { + return default_visit(tensor_function_t::squeeze_shape, &op); + } + virtual result visit(NNCASE_UNUSED const tensor_stack_op_t &op) noexcept { return default_visit(tensor_function_t::stack, &op); } @@ -1797,6 +1849,10 @@ class NNCASE_API tensor_op_visitor { return default_visit(tensor_function_t::transpose, &op); } virtual result + visit(NNCASE_UNUSED const tensor_transpose_shape_op_t &op) noexcept { + return default_visit(tensor_function_t::transpose_shape, &op); + } + virtual result visit(NNCASE_UNUSED const tensor_trilu_op_t &op) noexcept { return default_visit(tensor_function_t::trilu, &op); } @@ -1817,6 +1873,10 @@ class NNCASE_API tensor_op_visitor { return default_visit(tensor_function_t::unsqueeze, &op); } virtual result + visit(NNCASE_UNUSED const tensor_unsqueeze_shape_op_t &op) noexcept { + return default_visit(tensor_function_t::unsqueeze_shape, &op); + } + virtual result visit(NNCASE_UNUSED const tensor_where_op_t &op) noexcept { return default_visit(tensor_function_t::where, &op); } diff --git a/src/Native/include/nncase/runtime/stackvm/opcode.h b/src/Native/include/nncase/runtime/stackvm/opcode.h index 26e98927f1..5c17c82894 100644 --- a/src/Native/include/nncase/runtime/stackvm/opcode.h +++ b/src/Native/include/nncase/runtime/stackvm/opcode.h @@ -1,4 +1,4 @@ -/* This file is generated by tools/stackvm_gen/IsaGen at 2023/7/12 17:07:38 +/* This file is generated by tools/stackvm_gen/IsaGen at 2023/9/5 19:40:29 * +08:00. * * Copyright 2019-2021 Canaan Inc. @@ -136,29 +136,29 @@ enum class tensor_function_t : uint16_t { elu = 20, erf = 21, gelu = 30, - hardmax = 32, - hard_sigmoid = 33, - hard_swish = 34, - instance_normalization = 36, - l2_normalization = 37, - layer_norm = 38, - leaky_relu = 39, - log_softmax = 40, - lp_normalization = 41, - lrn = 42, - one_hot = 48, - pad = 49, - prelu = 50, - reduce_window2d = 59, - relu = 60, - relu6 = 61, - selu = 68, - sigmoid = 70, - softmax = 73, - softplus = 74, - softsign = 75, - space_to_batch = 76, - swish = 80, + hardmax = 33, + hard_sigmoid = 34, + hard_swish = 35, + instance_normalization = 37, + l2_normalization = 38, + layer_norm = 39, + leaky_relu = 40, + log_softmax = 41, + lp_normalization = 42, + lrn = 43, + one_hot = 49, + pad = 50, + prelu = 51, + reduce_window2d = 60, + relu = 61, + relu6 = 62, + selu = 70, + sigmoid = 72, + softmax = 75, + softplus = 76, + softsign = 77, + space_to_batch = 78, + swish = 83, binary = 2, clamp = 9, compare = 10, @@ -167,15 +167,15 @@ enum class tensor_function_t : uint16_t { dequantize = 19, fake_dequantize = 23, fake_quantize = 24, - mat_mul = 44, - quantize = 52, - quant_param_of = 53, - range_of = 55, - reduce = 57, - reduce_arg = 58, - require = 62, - select = 67, - unary = 85, + mat_mul = 45, + quantize = 53, + quant_param_of = 54, + range_of = 56, + reduce = 58, + reduce_arg = 59, + require = 63, + select = 69, + unary = 89, bitcast = 3, broadcast = 4, bucket_pad = 6, @@ -189,35 +189,40 @@ enum class tensor_function_t : uint16_t { gather_elements = 28, gather_nd = 29, get_item = 31, - index_of = 35, - lstm = 43, - prod = 51, - range = 54, - rank = 56, - reshape = 63, - reverse_sequence = 65, - scatter_nd = 66, - shape_of = 69, - size_of = 71, - slice = 72, - split = 77, - squeeze = 78, - stack = 79, - tile = 81, - top_k = 82, - transpose = 83, - trilu = 84, - unsqueeze = 88, - where = 89, + index_of = 36, + lstm = 44, + prod = 52, + range = 55, + rank = 57, + reshape = 64, + reverse_sequence = 67, + scatter_nd = 68, + shape_of = 71, + size_of = 73, + slice = 74, + split = 79, + squeeze = 80, + stack = 82, + tile = 84, + top_k = 85, + transpose = 86, + trilu = 88, + unsqueeze = 92, + where = 94, broadcast_shape = 5, conv2d_shape = 15, conv2d_transpose_shape = 17, - mat_mul_shape = 45, - normal = 46, - normal_like = 47, - uniform = 86, - uniform_like = 87, - resize_image = 64, + get_paddings = 32, + mat_mul_shape = 46, + reshape_shape = 65, + squeeze_shape = 81, + transpose_shape = 87, + unsqueeze_shape = 93, + normal = 47, + normal_like = 48, + uniform = 90, + uniform_like = 91, + resize_image = 66, }; enum class binary_op_t : uint8_t { @@ -663,6 +668,8 @@ struct tensor_gelu_op_t {}; struct tensor_get_item_op_t {}; +struct tensor_get_paddings_op_t {}; + struct tensor_hard_sigmoid_op_t {}; struct tensor_hard_swish_op_t {}; @@ -758,6 +765,8 @@ struct tensor_require_op_t { struct tensor_reshape_op_t {}; +struct tensor_reshape_shape_op_t {}; + struct tensor_resize_image_op_t { image_resize_mode_t resize_mode; image_resize_transformation_mode_t transformation_mode; @@ -793,6 +802,8 @@ struct tensor_split_op_t {}; struct tensor_squeeze_op_t {}; +struct tensor_squeeze_shape_op_t {}; + struct tensor_stack_op_t {}; struct tensor_swish_op_t {}; @@ -803,6 +814,8 @@ struct tensor_top_k_op_t {}; struct tensor_transpose_op_t {}; +struct tensor_transpose_shape_op_t {}; + struct tensor_trilu_op_t {}; struct tensor_unary_op_t { @@ -819,6 +832,8 @@ struct tensor_uniform_like_op_t { struct tensor_unsqueeze_op_t {}; +struct tensor_unsqueeze_shape_op_t {}; + struct tensor_where_op_t { bool is_tf_where; }; @@ -993,8 +1008,18 @@ inline std::string to_string(tensor_function_t tensor_funct) { return "conv2d_shape"; case tensor_function_t::conv2d_transpose_shape: return "conv2d_transpose_shape"; + case tensor_function_t::get_paddings: + return "get_paddings"; case tensor_function_t::mat_mul_shape: return "mat_mul_shape"; + case tensor_function_t::reshape_shape: + return "reshape_shape"; + case tensor_function_t::squeeze_shape: + return "squeeze_shape"; + case tensor_function_t::transpose_shape: + return "transpose_shape"; + case tensor_function_t::unsqueeze_shape: + return "unsqueeze_shape"; case tensor_function_t::normal: return "normal"; case tensor_function_t::normal_like: diff --git a/src/Native/src/kernels/stackvm/reference/pad.cpp b/src/Native/src/kernels/stackvm/reference/pad.cpp index 6186101e8a..2b27400fab 100644 --- a/src/Native/src/kernels/stackvm/reference/pad.cpp +++ b/src/Native/src/kernels/stackvm/reference/pad.cpp @@ -162,7 +162,7 @@ void padding_impl_opt(T *in, T *out, gsl::span in_shape, dh = out_shape[0]; hh = out_shape[1]; wh = out_shape[2]; - } else { + } else if (in_shape.size() == 4) { cl = in_shape[0]; dl = in_shape[1]; hl = in_shape[2]; @@ -171,6 +171,16 @@ void padding_impl_opt(T *in, T *out, gsl::span in_shape, dh = out_shape[1]; hh = out_shape[2]; wh = out_shape[3]; + } else // size ==2 + { + cl = 1; + dl = 1; + hl = in_shape[0]; + wl = in_shape[1]; + ch = 1; + dh = 1; + hh = out_shape[0]; + wh = out_shape[1]; } pad_data2(in, out, cl, dl, hl, wl, ch, dh, hh, wh, value); @@ -216,7 +226,7 @@ result nncase::kernels::stackvm::reference::pad( std::all_of( paddings.begin(), paddings.end(), [](const padding &p) { return p.before == 0 && p.after >= 0; }) && - mode == pad_mode_t::constant && in_shape.size() >= 3; + mode == pad_mode_t::constant && in_shape.size() >= 2; if (std::all_of(paddings.begin(), paddings.end(), [](const padding &p) { return p.interior == 0; })) { diff --git a/src/Native/src/kernels/stackvm/shape_ops.cpp b/src/Native/src/kernels/stackvm/shape_ops.cpp index 7677b10c2b..991b16950c 100644 --- a/src/Native/src/kernels/stackvm/shape_ops.cpp +++ b/src/Native/src/kernels/stackvm/shape_ops.cpp @@ -106,6 +106,12 @@ result nncase::kernels::stackvm::broadcast_shape(value_t inputs, KERNEL_FINISH; } +#define WRITE_OUT_SHAPE \ + try_output(out_mem, output, dt_int64, dims_t{out_shape.size()}); \ + for (int i = 0; i < out_shape.size(); ++i) { \ + OUT_CAST(int64_t, out_mem)[i] = out_shape[i]; \ + } + result nncase::kernels::stackvm::mat_mul_shape(value_t lhs, value_t rhs, value_t output, @@ -113,9 +119,105 @@ result nncase::kernels::stackvm::mat_mul_shape(value_t lhs, try_dims(lhs_shape, lhs); try_dims(rhs_shape, rhs); try_var(out_shape, matmul_infer_shape(lhs_shape, rhs_shape)); - try_output(out_mem, output, dt_int64, dims_t{out_shape.size()}); - for (int i = 0; i < out_shape.size(); ++i) { - OUT_CAST(int64_t, out_mem)[i] = out_shape[i]; + WRITE_OUT_SHAPE; + KERNEL_FINISH; +} + +inline int get_windowed_output_size(int size, int filter, int stride, + int dilation, bool same, bool ceilMode) { + auto effectiveFilterSize = ((filter - 1) * dilation) + 1; + auto falseBranch = !ceilMode + ? ((size - effectiveFilterSize + stride) / stride) + : ceil(size - effectiveFilterSize + stride / stride); + auto trueBranch = (size + stride - 1) / stride; + return same ? trueBranch : falseBranch; +} + +inline padding get_windowed_padding(int32_t input_size, int32_t output_size, + int32_t filter, int32_t stride, + int32_t dilation, bool lower) { + auto effective_filter_size = (filter - 1) * dilation + 1; + int padding = std::max(0, (output_size - 1) * stride + + effective_filter_size - input_size); + auto before = padding / 2; + auto after = padding - padding / 2; + if (lower) { + return {std::max(before, after), std::min(before, after)}; } + return {before, after}; +} + +result nncase::kernels::stackvm::get_paddings( + value_t input_shape, value_t weights_shape, value_t strides, + value_t dilations, value_t same, value_t lower, value_t output, + [[maybe_unused]] kernel_context &) { + try_dims(in_shape, input_shape); + try_dims(w_shape, weights_shape); + try_strides(strides_value, strides); + try_strides(dilations_value, dilations); + try_to_scalar_v(same, bool); + try_to_scalar_v(lower, bool); + auto out_h = + get_windowed_output_size(in_shape[2], w_shape[2], strides_value[0], + dilations_value[0], same_value, false); + auto out_w = + get_windowed_output_size(in_shape[3], w_shape[3], strides_value[1], + dilations_value[1], same_value, false); + auto pad_h = + get_windowed_padding(in_shape[2], out_h, w_shape[2], strides_value[0], + dilations_value[0], lower_value); + auto pad_w = + get_windowed_padding(in_shape[3], out_w, w_shape[3], strides_value[1], + dilations_value[1], lower_value); + auto out_shape = dims_t{2, 2}; + try_out_mem(output, dt_int64, out_shape); + OUT_CAST(int64_t, output_mem)[0] = pad_h.before; + OUT_CAST(int64_t, output_mem)[1] = pad_h.after; + OUT_CAST(int64_t, output_mem)[2] = pad_w.before; + OUT_CAST(int64_t, output_mem)[3] = pad_w.after; + KERNEL_FINISH; +} + +result nncase::kernels::stackvm::reshape_shape(value_t input_shape, + value_t shape, + value_t output, + kernel_context &) { + try_dims(in_shape, input_shape); + try_axes(shape_value, shape); + auto out_shape = reshape_shape_infer(in_shape, shape_value); + WRITE_OUT_SHAPE; + KERNEL_FINISH; +} + +result +nncase::kernels::stackvm::transpose_shape(value_t input_shape, value_t perm, + value_t output, + [[maybe_unused]] kernel_context &) { + try_dims(in_shape, input_shape); + try_dims(perm_value, perm); + auto out_shape = transpose_infer_shape(in_shape, perm_value); + WRITE_OUT_SHAPE; + KERNEL_FINISH; +} + +result +nncase::kernels::stackvm::squeeze_shape(value_t input_shape, value_t dim, + value_t output, + [[maybe_unused]] kernel_context &) { + try_dims(in_shape, input_shape); + try_positive_axes(dim_value, dim, in_shape.size()); + auto out_shape = squeeze_infer_shape(in_shape, dim_value); + WRITE_OUT_SHAPE; + KERNEL_FINISH; +} + +result +nncase::kernels::stackvm::unsqueeze_shape(value_t input_shape, value_t dim, + value_t output, + [[maybe_unused]] kernel_context &) { + try_dims(in_shape, input_shape); + try_axes(dim_value, dim); + auto out_shape = unsqueeze_infer_shape(in_shape, dim_value); + WRITE_OUT_SHAPE; KERNEL_FINISH; } \ No newline at end of file diff --git a/src/Native/src/runtime/stackvm/op_reader.cpp b/src/Native/src/runtime/stackvm/op_reader.cpp index 04776e0f7d..901f0f6125 100644 --- a/src/Native/src/runtime/stackvm/op_reader.cpp +++ b/src/Native/src/runtime/stackvm/op_reader.cpp @@ -1,4 +1,4 @@ -/* This file is generated by tools/stackvm_gen/IsaGen at 2023/7/12 17:07:39 +/* This file is generated by tools/stackvm_gen/IsaGen at 2023/9/5 19:40:29 * +08:00. * * Copyright 2019-2021 Canaan Inc. @@ -99,6 +99,9 @@ result tensor_op_visitor::visit(tensor_function_t tensor_funct, return visit(tensor_op_reader()(reader)); case tensor_function_t::get_item: return visit(tensor_op_reader()(reader)); + case tensor_function_t::get_paddings: + return visit( + tensor_op_reader()(reader)); case tensor_function_t::hard_sigmoid: return visit( tensor_op_reader()(reader)); @@ -173,6 +176,9 @@ result tensor_op_visitor::visit(tensor_function_t tensor_funct, return visit(tensor_op_reader()(reader)); case tensor_function_t::reshape: return visit(tensor_op_reader()(reader)); + case tensor_function_t::reshape_shape: + return visit( + tensor_op_reader()(reader)); case tensor_function_t::resize_image: return visit( tensor_op_reader()(reader)); @@ -206,6 +212,9 @@ result tensor_op_visitor::visit(tensor_function_t tensor_funct, return visit(tensor_op_reader()(reader)); case tensor_function_t::squeeze: return visit(tensor_op_reader()(reader)); + case tensor_function_t::squeeze_shape: + return visit( + tensor_op_reader()(reader)); case tensor_function_t::stack: return visit(tensor_op_reader()(reader)); case tensor_function_t::swish: @@ -216,6 +225,9 @@ result tensor_op_visitor::visit(tensor_function_t tensor_funct, return visit(tensor_op_reader()(reader)); case tensor_function_t::transpose: return visit(tensor_op_reader()(reader)); + case tensor_function_t::transpose_shape: + return visit( + tensor_op_reader()(reader)); case tensor_function_t::trilu: return visit(tensor_op_reader()(reader)); case tensor_function_t::unary: @@ -227,6 +239,9 @@ result tensor_op_visitor::visit(tensor_function_t tensor_funct, tensor_op_reader()(reader)); case tensor_function_t::unsqueeze: return visit(tensor_op_reader()(reader)); + case tensor_function_t::unsqueeze_shape: + return visit( + tensor_op_reader()(reader)); case tensor_function_t::where: return visit(tensor_op_reader()(reader)); default: diff --git a/src/Native/src/runtime/stackvm/ops/tensor.cpp b/src/Native/src/runtime/stackvm/ops/tensor.cpp index 0439e7887c..6f09a7084c 100644 --- a/src/Native/src/runtime/stackvm/ops/tensor.cpp +++ b/src/Native/src/runtime/stackvm/ops/tensor.cpp @@ -1,4 +1,4 @@ -/* This file is generated by tools/stackvm_gen/IsaGen at 2023/7/12 17:07:39 +/* This file is generated by tools/stackvm_gen/IsaGen at 2023/9/5 19:40:29 * +08:00. * * Copyright 2019-2021 Canaan Inc. @@ -564,6 +564,29 @@ result stackvm_runtime_function::visit( return ok(); } +result stackvm_runtime_function::visit( + [[maybe_unused]] const tensor_get_paddings_op_t &op) noexcept { + dump_op("get_paddings"); + try_var(input_shape, pop_value()); + dump_input(input_shape); + try_var(weights_shape, pop_value()); + dump_input(weights_shape); + try_var(strides, pop_value()); + dump_input(strides); + try_var(dilations, pop_value()); + dump_input(dilations); + try_var(same, pop_value()); + dump_input(same); + try_var(lower, pop_value()); + dump_input(lower); + try_var(output, kernels::stackvm::get_paddings( + input_shape, weights_shape, strides, dilations, same, + lower, nullptr, module().kernel_context())); + dump_output(output); + stack_.push(std::move(output)); + return ok(); +} + result stackvm_runtime_function::visit( [[maybe_unused]] const tensor_hard_sigmoid_op_t &op) noexcept { dump_op("hard_sigmoid"); @@ -1091,6 +1114,20 @@ result stackvm_runtime_function::visit( return ok(); } +result stackvm_runtime_function::visit( + [[maybe_unused]] const tensor_reshape_shape_op_t &op) noexcept { + dump_op("reshape_shape"); + try_var(input_shape, pop_value()); + dump_input(input_shape); + try_var(shape, pop_value()); + dump_input(shape); + try_var(output, kernels::stackvm::reshape_shape(input_shape, shape, nullptr, + module().kernel_context())); + dump_output(output); + stack_.push(std::move(output)); + return ok(); +} + result stackvm_runtime_function::visit( [[maybe_unused]] const tensor_resize_image_op_t &op) noexcept { dump_op("resize_image"); @@ -1327,6 +1364,20 @@ result stackvm_runtime_function::visit( return ok(); } +result stackvm_runtime_function::visit( + [[maybe_unused]] const tensor_squeeze_shape_op_t &op) noexcept { + dump_op("squeeze_shape"); + try_var(input_shape, pop_value()); + dump_input(input_shape); + try_var(dim, pop_value()); + dump_input(dim); + try_var(output, kernels::stackvm::squeeze_shape(input_shape, dim, nullptr, + module().kernel_context())); + dump_output(output); + stack_.push(std::move(output)); + return ok(); +} + result stackvm_runtime_function::visit( [[maybe_unused]] const tensor_stack_op_t &op) noexcept { dump_op("stack"); @@ -1402,6 +1453,20 @@ result stackvm_runtime_function::visit( return ok(); } +result stackvm_runtime_function::visit( + [[maybe_unused]] const tensor_transpose_shape_op_t &op) noexcept { + dump_op("transpose_shape"); + try_var(input_shape, pop_value()); + dump_input(input_shape); + try_var(perm, pop_value()); + dump_input(perm); + try_var(output, kernels::stackvm::transpose_shape( + input_shape, perm, nullptr, module().kernel_context())); + dump_output(output); + stack_.push(std::move(output)); + return ok(); +} + result stackvm_runtime_function::visit( [[maybe_unused]] const tensor_trilu_op_t &op) noexcept { dump_op("trilu"); @@ -1482,6 +1547,20 @@ result stackvm_runtime_function::visit( return ok(); } +result stackvm_runtime_function::visit( + [[maybe_unused]] const tensor_unsqueeze_shape_op_t &op) noexcept { + dump_op("unsqueeze_shape"); + try_var(input_shape, pop_value()); + dump_input(input_shape); + try_var(dim, pop_value()); + dump_input(dim); + try_var(output, kernels::stackvm::unsqueeze_shape( + input_shape, dim, nullptr, module().kernel_context())); + dump_output(output); + stack_.push(std::move(output)); + return ok(); +} + result stackvm_runtime_function::visit( [[maybe_unused]] const tensor_where_op_t &op) noexcept { dump_op("where"); diff --git a/src/Native/src/runtime/stackvm/runtime_function_ops.h b/src/Native/src/runtime/stackvm/runtime_function_ops.h index 02841ebe35..ae6944ef59 100644 --- a/src/Native/src/runtime/stackvm/runtime_function_ops.h +++ b/src/Native/src/runtime/stackvm/runtime_function_ops.h @@ -1,4 +1,4 @@ -/* This file is generated by tools/stackvm_gen/IsaGen at 2023/7/12 17:07:39 +/* This file is generated by tools/stackvm_gen/IsaGen at 2023/9/5 19:40:29 * +08:00. * * Copyright 2019-2021 Canaan Inc. @@ -49,6 +49,7 @@ result visit(const tensor_gather_elements_op_t &op) noexcept override; result visit(const tensor_gather_nd_op_t &op) noexcept override; result visit(const tensor_gelu_op_t &op) noexcept override; result visit(const tensor_get_item_op_t &op) noexcept override; +result visit(const tensor_get_paddings_op_t &op) noexcept override; result visit(const tensor_hard_sigmoid_op_t &op) noexcept override; result visit(const tensor_hard_swish_op_t &op) noexcept override; result visit(const tensor_hardmax_op_t &op) noexcept override; @@ -82,6 +83,7 @@ result visit(const tensor_relu_op_t &op) noexcept override; result visit(const tensor_relu6_op_t &op) noexcept override; result visit(const tensor_require_op_t &op) noexcept override; result visit(const tensor_reshape_op_t &op) noexcept override; +result visit(const tensor_reshape_shape_op_t &op) noexcept override; result visit(const tensor_resize_image_op_t &op) noexcept override; result visit(const tensor_reverse_sequence_op_t &op) noexcept override; result visit(const tensor_scatter_nd_op_t &op) noexcept override; @@ -97,14 +99,17 @@ result visit(const tensor_softsign_op_t &op) noexcept override; result visit(const tensor_space_to_batch_op_t &op) noexcept override; result visit(const tensor_split_op_t &op) noexcept override; result visit(const tensor_squeeze_op_t &op) noexcept override; +result visit(const tensor_squeeze_shape_op_t &op) noexcept override; result visit(const tensor_stack_op_t &op) noexcept override; result visit(const tensor_swish_op_t &op) noexcept override; result visit(const tensor_tile_op_t &op) noexcept override; result visit(const tensor_top_k_op_t &op) noexcept override; result visit(const tensor_transpose_op_t &op) noexcept override; +result visit(const tensor_transpose_shape_op_t &op) noexcept override; result visit(const tensor_trilu_op_t &op) noexcept override; result visit(const tensor_unary_op_t &op) noexcept override; result visit(const tensor_uniform_op_t &op) noexcept override; result visit(const tensor_uniform_like_op_t &op) noexcept override; result visit(const tensor_unsqueeze_op_t &op) noexcept override; +result visit(const tensor_unsqueeze_shape_op_t &op) noexcept override; result visit(const tensor_where_op_t &op) noexcept override; diff --git a/src/Nncase.Compiler/Compiler.cs b/src/Nncase.Compiler/Compiler.cs index 74eccd2190..f4014fa047 100644 --- a/src/Nncase.Compiler/Compiler.cs +++ b/src/Nncase.Compiler/Compiler.cs @@ -12,6 +12,7 @@ using Nncase.Evaluator; using Nncase.Hosting; using Nncase.IR; +using Nncase.IR.NN; using Nncase.IR.Tensors; using Nncase.Passes; using Nncase.Passes.Mutators; @@ -118,7 +119,29 @@ public void TargetIndependentPass(IPassManager passManager) p.Add(); p.Add(); p.Add(); + p.Add(); + p.Add(); + p.Add(); + p.Add(); + p.Add(); + p.Add(); + p.Add(); + p.Add(); + p.Add(); + p.Add(); + p.Add(); + p.Add(); + p.Add(); + p.Add(); + p.Add(); + p.Add(); + p.Add(); + p.Add(); + p.Add(); + p.Add(); + p.Add(); }); + passManager.AddWithName("NeutralOptimizeTranspose").Configure(p => { p.Add(); @@ -180,24 +203,30 @@ public void TargetIndependentPass(IPassManager passManager) public void RegisterShapeBucket(IPassManager p) { var options = _compileSession.CompileOptions.ShapeBucketOptions; - var singleVar = options.VarMap.Values.SelectMany(x => x).OfType().ToHashSet().Count <= 1; if (!options.Enable) { return; } + var singleVar = options.VarMap.Values.SelectMany(x => x).OfType().ToHashSet().Count <= 1; CheckShapeBucketOptions(options); - ToFusion(p); - MergeOp(p); - LostToFusion(p, singleVar); - MergeOp(p); - ClearMarker(p); - - // MergeFusion(p, singleVar); - Bucket(p); - // Rebuild(p); - Simplify(p); + if (HasNotBucketOp(_module!.Entry!) || !singleVar) + { + ToFusion(p); + MergeOp(p, true); + LostToFusion(p, singleVar); + MergeOp(p, true); + ClearMarker(p); + MergeFusion(p, singleVar, true); + Bucket(p); + Rebuild(p, singleVar); + Simplify(p); + } + else + { + p.AddWithName("FullBucket"); + } } public void ClearFixShape(IPassManager p) diff --git a/src/Nncase.Core/IR/ShapeExpr/Functional.cs b/src/Nncase.Core/IR/ShapeExpr/Functional.cs index 8631e5e26f..555e9fa367 100644 --- a/src/Nncase.Core/IR/ShapeExpr/Functional.cs +++ b/src/Nncase.Core/IR/ShapeExpr/Functional.cs @@ -14,4 +14,14 @@ public static class ShapeExpr public static Call Conv2DTransposeShape(Expr input, Expr weights, Expr stride, Expr dilation, Expr padding, Expr outputPadding, Expr groups) => new(new Conv2DTransposeShape(), input, weights, stride, dilation, padding, outputPadding, groups); public static Call MatMulShape(Expr lhs, Expr rhs) => new(new MatMulShape(), lhs, rhs); + + public static Call GetPaddings(Expr input, Expr weights, Expr strides, Expr dilation, Expr same, Expr lower) => new(new GetPaddings(), input, weights, strides, dilation, same, lower); + + public static Call ReshapeShape(Expr input, Expr shape) => new(new ReshapeShape(), input, shape); + + public static Call SqueezeShape(Expr input, Expr dims) => new(new SqueezeShape(), input, dims); + + public static Call TransposeShape(Expr input, Expr perm) => new(new TransposeShape(), input, perm); + + public static Call UnsqueezeShape(Expr lhs, Expr rhs) => new(new UnsqueezeShape(), lhs, rhs); } diff --git a/src/Nncase.Core/IR/ShapeExpr/GetPaddings.cs b/src/Nncase.Core/IR/ShapeExpr/GetPaddings.cs new file mode 100644 index 0000000000..5bed9f4660 --- /dev/null +++ b/src/Nncase.Core/IR/ShapeExpr/GetPaddings.cs @@ -0,0 +1,40 @@ +// Copyright (c) Canaan Inc. All rights reserved. +// Licensed under the Apache license. See LICENSE file in the project root for full license information. + +using Nncase.PatternMatch; + +namespace Nncase.IR.ShapeExpr; + +[PatternFunctionalGenerator] +public class GetPaddings : Op +{ + /// + /// Gets Input. + /// + public static readonly ParameterInfo InputShape = new(typeof(GetPaddings), 0, "input_shape"); + + /// + /// Gets Weights. + /// + public static readonly ParameterInfo WeightsShape = new(typeof(GetPaddings), 1, "weights_shape"); + + /// + /// Gets Strides. + /// + public static readonly ParameterInfo Strides = new(typeof(GetPaddings), 2, "strides"); + + /// + /// Gets Dilations. + /// + public static readonly ParameterInfo Dilations = new(typeof(GetPaddings), 3, "dilations"); + + /// + /// Gets Same. + /// + public static readonly ParameterInfo Same = new(typeof(GetPaddings), 4, "same"); + + /// + /// Gets Lower. + /// + public static readonly ParameterInfo Lower = new(typeof(GetPaddings), 5, "lower"); +} diff --git a/src/Nncase.Core/IR/ShapeExpr/ReshapeShape.cs b/src/Nncase.Core/IR/ShapeExpr/ReshapeShape.cs new file mode 100644 index 0000000000..f6db6836a0 --- /dev/null +++ b/src/Nncase.Core/IR/ShapeExpr/ReshapeShape.cs @@ -0,0 +1,24 @@ +// Copyright (c) Canaan Inc. All rights reserved. +// Licensed under the Apache license. See LICENSE file in the project root for full license information. + +using Nncase.PatternMatch; +using static Nncase.IR.TypePatternUtility; + +namespace Nncase.IR.ShapeExpr; + +/// +/// Reshape expression. +/// +[PatternFunctionalGenerator] +public sealed partial class ReshapeShape : Op +{ + /// + /// Gets input shape. + /// + public static readonly ParameterInfo InputShape = new(typeof(ReshapeShape), 0, "input_shape"); + + /// + /// Gets shape. + /// + public static readonly ParameterInfo Shape = new(typeof(ReshapeShape), 1, "shape", HasRank(1)); +} diff --git a/src/Nncase.Core/IR/ShapeExpr/SqueezeShape.cs b/src/Nncase.Core/IR/ShapeExpr/SqueezeShape.cs new file mode 100644 index 0000000000..55338691b6 --- /dev/null +++ b/src/Nncase.Core/IR/ShapeExpr/SqueezeShape.cs @@ -0,0 +1,24 @@ +// Copyright (c) Canaan Inc. All rights reserved. +// Licensed under the Apache license. See LICENSE file in the project root for full license information. + +using Nncase.PatternMatch; +using static Nncase.IR.TypePatternUtility; + +namespace Nncase.IR.ShapeExpr; + +/// +/// Squeeze expression. +/// +[PatternFunctionalGenerator] +public sealed partial class SqueezeShape : Op +{ + /// + /// Gets input shape. + /// + public static readonly ParameterInfo InputShape = new(typeof(SqueezeShape), 0, "input_shape"); + + /// + /// Gets dimension. + /// + public static readonly ParameterInfo Dim = new(typeof(SqueezeShape), 1, "dim", HasRank(1) & IsIntegral()); +} diff --git a/src/Nncase.Core/IR/ShapeExpr/TransposeShape.cs b/src/Nncase.Core/IR/ShapeExpr/TransposeShape.cs new file mode 100644 index 0000000000..c658e15dc6 --- /dev/null +++ b/src/Nncase.Core/IR/ShapeExpr/TransposeShape.cs @@ -0,0 +1,24 @@ +// Copyright (c) Canaan Inc. All rights reserved. +// Licensed under the Apache license. See LICENSE file in the project root for full license information. + +using Nncase.PatternMatch; +using static Nncase.IR.TypePatternUtility; + +namespace Nncase.IR.ShapeExpr; + +/// +/// Gets input. +/// +[PatternFunctionalGenerator] +public sealed partial class TransposeShape : Op +{ + /// + /// Gets input. + /// + public static readonly ParameterInfo InputShape = new(typeof(TransposeShape), 0, "input"); + + /// + /// Gets perm. + /// + public static readonly ParameterInfo Perm = new(typeof(TransposeShape), 1, "perm", HasRank(1) & IsIntegral()); +} diff --git a/src/Nncase.Core/IR/ShapeExpr/UnsqueezeShape.cs b/src/Nncase.Core/IR/ShapeExpr/UnsqueezeShape.cs new file mode 100644 index 0000000000..ed1f396fef --- /dev/null +++ b/src/Nncase.Core/IR/ShapeExpr/UnsqueezeShape.cs @@ -0,0 +1,21 @@ +// Copyright (c) Canaan Inc. All rights reserved. +// Licensed under the Apache license. See LICENSE file in the project root for full license information. + +using Nncase.PatternMatch; +using static Nncase.IR.TypePatternUtility; + +namespace Nncase.IR.ShapeExpr; + +[PatternFunctionalGenerator] +public sealed partial class UnsqueezeShape : Op +{ + /// + /// Gets input_shape. + /// + public static readonly ParameterInfo InputShape = new(typeof(UnsqueezeShape), 0, "input_shape"); + + /// + /// Gets dimension. + /// + public static readonly ParameterInfo Dim = new(typeof(UnsqueezeShape), 1, "dim", HasRank(1) & IsIntegral()); +} diff --git a/src/Nncase.Core/Utilities/ShapeExprUtility.cs b/src/Nncase.Core/Utilities/ShapeExprUtility.cs index 28d953a8ad..c1da04dca4 100644 --- a/src/Nncase.Core/Utilities/ShapeExprUtility.cs +++ b/src/Nncase.Core/Utilities/ShapeExprUtility.cs @@ -19,8 +19,8 @@ public static Expr BroadcastShape(Expr lhsShape, params Expr[] rhsShape) public static Expr Positive(Expr axis, Expr inShape) { var rank = new Call(new Rank(), inShape); - var i32Axis = Cast(axis, DataTypes.Int32); - return new If(i32Axis < 0, i32Axis + rank, i32Axis); + var i64Axis = Cast(axis, DataTypes.Int64); + return new If(i64Axis < 0L, i64Axis + rank, i64Axis); } public static Expr Slice(Expr shape, int begin, int end) @@ -35,28 +35,28 @@ public static Expr Slice(Expr shape, Expr begin, Expr end) public static Expr Replace(Expr shapeExpr, Expr index, Expr value) { - return SliceAndMerge(shapeExpr, index, value, 1); + return SliceAndMerge(shapeExpr, index, value, 1L); } public static Expr Insert(Expr shapeExpr, Expr index, Expr value) { if (shapeExpr.CheckedShape.IsScalar) { - return SliceAndMerge(StackScalar(shapeExpr), index, value, 0); + return SliceAndMerge(StackScalar(shapeExpr), index, value, 0L); } - return SliceAndMerge(shapeExpr, index, value, 0); + return SliceAndMerge(shapeExpr, index, value, 0L); } public static Expr ReplaceList(Expr shapeExpr, Expr list, Expr value) { - return SliceAndMerge(shapeExpr, list, value, 1, false); + return SliceAndMerge(shapeExpr, list, value, 1L, false); } public static Expr Remove(Expr shapeExpr, Expr index) { var front = Slice(shapeExpr, 0, index); - var last = Slice(shapeExpr, index + 1, int.MaxValue); + var last = Slice(shapeExpr, index + 1L, int.MaxValue); return Concat(new IR.Tuple(front, last), 0); } @@ -65,10 +65,17 @@ public static Expr StackOne(Expr expr) return Stack(new IR.Tuple(expr), 0); } - private static Expr SliceAndMerge(Expr shapeExpr, Expr index, Expr value, Expr indexOffset, bool valueIsList = true) + public static IValue GetShapeValue(Call call) { + call.InferenceType(); + return Value.FromTensor(call.CheckedShape.ToValueArray().Select(x => (long)x).ToArray()); + } + + private static Expr SliceAndMerge(Expr originShapeExpr, Expr index, Expr value, Expr indexOffset, bool valueIsList = true) + { + var shapeExpr = Cast(originShapeExpr, DataTypes.Int64); var front = Slice(shapeExpr, 0, index); - var last = Slice(shapeExpr, Cast(index, DataTypes.Int32) + indexOffset, int.MaxValue); + var last = Slice(shapeExpr, Cast(index, DataTypes.Int64) + indexOffset, int.MaxValue); var c = valueIsList ? StackOne(value) : value; if (c.CheckedShape.IsScalar) { diff --git a/src/Nncase.Evaluator/Math/Binary.cs b/src/Nncase.Evaluator/Math/Binary.cs index 0b5515ca28..f5f9d3c65b 100755 --- a/src/Nncase.Evaluator/Math/Binary.cs +++ b/src/Nncase.Evaluator/Math/Binary.cs @@ -118,7 +118,7 @@ public Expr Visit(IShapeEvaluateContext context, Binary target) { var lhs = context.GetArgumentShape(target, Binary.Lhs); var rhs = context.GetArgumentShape(target, Binary.Rhs); - return IR.F.Tensors.Cast(ShapeExprUtility.BroadcastShape(lhs, rhs), DataTypes.Int32); + return ShapeExprUtility.BroadcastShape(lhs, rhs); } private int Compute(BinaryOp op, int a, int b) => op switch diff --git a/src/Nncase.Evaluator/Math/MatMul.cs b/src/Nncase.Evaluator/Math/MatMul.cs index 444d221c28..4785e1e1c1 100644 --- a/src/Nncase.Evaluator/Math/MatMul.cs +++ b/src/Nncase.Evaluator/Math/MatMul.cs @@ -71,7 +71,7 @@ public Expr Visit(IShapeEvaluateContext context, MatMul target) { var lhs = context.GetArgumentShape(target, MatMul.Lhs); var rhs = context.GetArgumentShape(target, MatMul.Rhs); - return Cast(IR.F.ShapeExpr.MatMulShape(lhs, rhs), DataTypes.Int32); + return IR.F.ShapeExpr.MatMulShape(lhs, rhs); } private IRType Visit(TensorType lhs, TensorType rhs) diff --git a/src/Nncase.Evaluator/Math/Reduce.cs b/src/Nncase.Evaluator/Math/Reduce.cs index 69e512b717..ead03f4701 100644 --- a/src/Nncase.Evaluator/Math/Reduce.cs +++ b/src/Nncase.Evaluator/Math/Reduce.cs @@ -110,7 +110,7 @@ public Expr Visit(IShapeEvaluateContext context, Reduce target) { if (axes.Length == input.CheckedShape.Count && keepDimsValue == 0) { - return Array.Empty(); + return Array.Empty(); } } @@ -119,7 +119,7 @@ public Expr Visit(IShapeEvaluateContext context, Reduce target) var ax = ShapeExprUtility.Positive(axValue, inShape); if (keepDimsValue == 1) { - outShape = ShapeExprUtility.Replace(outShape, ax, 1); + outShape = ShapeExprUtility.Replace(outShape, ax, 1L); } else { @@ -127,7 +127,7 @@ public Expr Visit(IShapeEvaluateContext context, Reduce target) } } - return outShape; + return Cast(outShape, DataTypes.Int64); } throw new NotImplementedException(); diff --git a/src/Nncase.Evaluator/NN/BatchToSpace.cs b/src/Nncase.Evaluator/NN/BatchToSpace.cs index d60473b41a..e53297c7ab 100644 --- a/src/Nncase.Evaluator/NN/BatchToSpace.cs +++ b/src/Nncase.Evaluator/NN/BatchToSpace.cs @@ -115,13 +115,13 @@ public Expr Visit(IShapeEvaluateContext context, BatchToSpace target) inShape = Stack(new IR.Tuple(inShape[0], inShape[2], inShape[1]), 0); } - var blockShape = context.GetArgument(target, BatchToSpace.BlockShape); + var blockShape = Cast(context.GetArgument(target, BatchToSpace.BlockShape), DataTypes.Int64); if (!blockShape.CheckedShape.IsFixed) { throw new NotImplementedException(); } - var crops = context.GetArgument(target, BatchToSpace.Crops); + var crops = Cast(context.GetArgument(target, BatchToSpace.Crops), DataTypes.Int64); var blockSize = Prod(blockShape); var batch = inShape[0]; var d0 = batch / blockSize; @@ -131,7 +131,7 @@ public Expr Visit(IShapeEvaluateContext context, BatchToSpace target) var inRank = Cast(ShapeOf(inShape)[0], DataTypes.Int32); var remainSize = inRank - 1 - m; - var remainShape = new If(remainSize > 0, ShapeExprUtility.Slice(inShape, 1 + m, int.MaxValue), Array.Empty()); + var remainShape = new If(remainSize > 0, ShapeExprUtility.Slice(inShape, 1 + m, int.MaxValue), Array.Empty()); var outShapeList = Concat(new IR.Tuple(Stack(new IR.Tuple(new[] { d0 }), 0), Stack(new IR.Tuple(cropSection), 0), remainShape), 0); diff --git a/src/Nncase.Evaluator/NN/Conv2D.cs b/src/Nncase.Evaluator/NN/Conv2D.cs index 67f361adc8..c26e219821 100644 --- a/src/Nncase.Evaluator/NN/Conv2D.cs +++ b/src/Nncase.Evaluator/NN/Conv2D.cs @@ -92,10 +92,10 @@ public Expr Visit(IShapeEvaluateContext context, Conv2D target) { var input = context.GetArgumentShape(target, Conv2D.Input); var weights = context.GetArgumentShape(target, Conv2D.Weights); - var pad = Cast(context.GetArgument(target, Conv2D.Padding), DataTypes.Int32); - var stride = Cast(context.GetArgument(target, Conv2D.Stride), DataTypes.Int32); - var dilation = Cast(context.GetArgument(target, Conv2D.Dilation), DataTypes.Int32); - var groups = Cast(context.GetArgument(target, Conv2D.Groups), DataTypes.Int32); + var pad = context.GetArgument(target, Conv2D.Padding); + var stride = context.GetArgument(target, Conv2D.Stride); + var dilation = context.GetArgument(target, Conv2D.Dilation); + var groups = context.GetArgument(target, Conv2D.Groups); return IR.F.ShapeExpr.Conv2DShape(input, weights, pad, stride, dilation, groups); } diff --git a/src/Nncase.Evaluator/NN/Pad.cs b/src/Nncase.Evaluator/NN/Pad.cs index 13a4111456..5d33750659 100644 --- a/src/Nncase.Evaluator/NN/Pad.cs +++ b/src/Nncase.Evaluator/NN/Pad.cs @@ -118,11 +118,11 @@ public Expr Visit(IShapeEvaluateContext context, Pad target) var end = Slice(pads, new[] { 1 }, new[] { 2 }, new[] { 1 }, new[] { 1 }); // paddings = [4, 2] -> [4, 1] + [4, 1] - var paddings = front + end; + var paddings = Cast(front + end, DataTypes.Int64); // outShape = inShape + paddings - var padsSumShape = StackScalar(Cast(ShapeOf(paddings)[0], DataTypes.Int32)); - var outShape = inShape + Cast(Reshape(paddings, padsSumShape), DataTypes.Int32); + var padsSumShape = StackScalar(ShapeOf(paddings)[0]); + var outShape = inShape + Reshape(paddings, padsSumShape); return outShape; } diff --git a/src/Nncase.Evaluator/NN/SpaceToBatch.cs b/src/Nncase.Evaluator/NN/SpaceToBatch.cs index 756f8c1472..98ec949151 100644 --- a/src/Nncase.Evaluator/NN/SpaceToBatch.cs +++ b/src/Nncase.Evaluator/NN/SpaceToBatch.cs @@ -98,11 +98,11 @@ public Expr Visit(IShapeEvaluateContext context, SpaceToBatch target) { var inShape = context.GetArgumentShape(target, SpaceToBatch.Input); var blockShape = context.GetArgument(target, SpaceToBatch.BlockShape); - var padding = context.GetArgument(target, SpaceToBatch.Paddings); + var padding = Cast(context.GetArgument(target, SpaceToBatch.Paddings), DataTypes.Int64); var input = context.GetArgument(target, SpaceToBatch.Input); if (blockShape is TensorConst blockConst) { - var blockShapeValue = blockConst.Value.ToArray(); + var blockShapeValue = blockConst.Value.ToArray(); var m = blockShapeValue.Length; var inRank = input.CheckedShape.Rank; @@ -122,7 +122,7 @@ public Expr Visit(IShapeEvaluateContext context, SpaceToBatch target) }).ToArray(); var remainSize = inRank - 1 - m; - var remainShape = new If(remainSize > 0, ShapeExprUtility.Slice(inShape, 1 + m, int.MaxValue), Array.Empty()); + var remainShape = new If(remainSize > 0, ShapeExprUtility.Slice(inShape, 1 + m, int.MaxValue), Array.Empty()); var outLast = remainShape; var outShape = Concat(new IR.Tuple(Stack(new IR.Tuple(outFirst.Concat(outMid).ToArray()), 0), outLast), 0); return outShape; diff --git a/src/Nncase.Evaluator/ShapeEvaluateContext.cs b/src/Nncase.Evaluator/ShapeEvaluateContext.cs index e9919fb3d6..6f3e5ff94c 100644 --- a/src/Nncase.Evaluator/ShapeEvaluateContext.cs +++ b/src/Nncase.Evaluator/ShapeEvaluateContext.cs @@ -22,8 +22,13 @@ internal sealed class ShapeEvaluateContext : IShapeEvaluateContext public ShapeEvaluateContext(Dictionary memo, ShapeExprCache cache) { _memo = memo; - Cache = cache.Cache; + foreach (var (key, value) in cache.Cache) + { + _memo[key] = value; + } + VarMap = cache.VarMap; + Cache = new(); } public IReadOnlyDictionary VarMap { get; } @@ -55,7 +60,7 @@ public Expr GetArgumentShape(Op op, ParameterInfo parameter) var expr = GetArgument(op, parameter); if (expr is Tuple tuple) { - return new Tuple(tuple.Fields.ToArray().Select(v => Cast(GetResultFromMemo(v), DataTypes.Int32)).ToArray()); + return new Tuple(tuple.Fields.ToArray().Select(v => Cast(GetResultFromMemo(v), DataTypes.Int64)).ToArray()); } // call @@ -64,7 +69,7 @@ public Expr GetArgumentShape(Op op, ParameterInfo parameter) var shape = expr.EvaluateShapeExpr(new ShapeExprCache(VarMap)); if (shape is Call c && c.Target is IR.Math.Require && c.Arguments[IR.Math.Require.Value.Index] is Tuple tupleShapeExpr) { - return new Tuple(tupleShapeExpr.Fields.ToArray().Select(expr => Cast(expr, DataTypes.Int32)).ToArray()); + return new Tuple(tupleShapeExpr.Fields.ToArray().Select(expr => Cast(expr, DataTypes.Int64)).ToArray()); } // for split @@ -76,23 +81,23 @@ public Expr GetArgumentShape(Op op, ParameterInfo parameter) return new Tuple( Enumerable .Range(0, tupleType.Fields.Count) - .Select(i => Cast(shape[i], DataTypes.Int32)) + .Select(i => Cast(shape[i], DataTypes.Int64)) .ToArray()); } else { - return new Tuple(((Tuple)shape).Fields.ToArray().Select(expr => Cast(expr, DataTypes.Int32)).ToArray()); + return new Tuple(((Tuple)shape).Fields.ToArray().Select(expr => Cast(expr, DataTypes.Int64)).ToArray()); } } } var shapeExpr = GetResultFromMemo(expr); - return Cast(shapeExpr, DataTypes.Int32); + return Cast(shapeExpr, DataTypes.Int64); } public Expr GetArgumentRank(Op op, ParameterInfo parameter) { - return StackScalar(Cast(GetArgumentShape(op, parameter)[0], DataTypes.Int32)); + return StackScalar(Cast(GetArgumentShape(op, parameter)[0], DataTypes.Int64)); } private Call GetCurrentCall() => CurrentCall ?? throw new InvalidOperationException("Current call is not set."); diff --git a/src/Nncase.Evaluator/ShapeEvaluateVisitor.cs b/src/Nncase.Evaluator/ShapeEvaluateVisitor.cs index f5e8c3ee4d..04b24b5109 100644 --- a/src/Nncase.Evaluator/ShapeEvaluateVisitor.cs +++ b/src/Nncase.Evaluator/ShapeEvaluateVisitor.cs @@ -102,7 +102,7 @@ protected override Expr VisitLeafVar(Var expr) throw new InvalidOperationException(); } - var shapeExpr = shape.Select((x, i) => x.IsFixed ? x.FixedValue : _context.VarMap[expr][i]).Select(x => IR.F.Tensors.Cast(x, DataTypes.Int32)).ToArray(); + var shapeExpr = shape.Select((x, i) => x.IsFixed ? x.FixedValue : _context.VarMap[expr][i]).Select(x => IR.F.Tensors.Cast(x, DataTypes.Int64)).ToArray(); return IR.F.Tensors.Stack(new IR.Tuple(shapeExpr), 0); } diff --git a/src/Nncase.Evaluator/ShapeEvaluatorProvider.cs b/src/Nncase.Evaluator/ShapeEvaluatorProvider.cs index 6c9a785a5a..adb4d296d8 100644 --- a/src/Nncase.Evaluator/ShapeEvaluatorProvider.cs +++ b/src/Nncase.Evaluator/ShapeEvaluatorProvider.cs @@ -64,6 +64,7 @@ public Expr EvaluateOpShapeExpr(Op op, IShapeEvaluateContext context) var evaluatorType = typeof(IShapeEvaluator<>).MakeGenericType(op.GetType()); var evaluator = (IShapeEvaluator)_serviceProvider.GetRequiredService(evaluatorType); var result = evaluator.Visit(context, op); + var s = op.GetType().Name + "_" + op.DisplayProperty(); if (!result.InferenceType()) { if (DumpScope.Current.IsEnabled(DumpFlags.Compile)) @@ -71,7 +72,7 @@ public Expr EvaluateOpShapeExpr(Op op, IShapeEvaluateContext context) DumpScope.Current.DumpIR(result, "EvaluateOpShapeExprInvalidResult"); } - throw new InvalidOperationException(); + throw new InvalidOperationException(s); } return result; diff --git a/src/Nncase.Evaluator/ShapeExpr/BroadcastShape.cs b/src/Nncase.Evaluator/ShapeExpr/BroadcastShape.cs index 61cb3e9438..c7cb702bca 100644 --- a/src/Nncase.Evaluator/ShapeExpr/BroadcastShape.cs +++ b/src/Nncase.Evaluator/ShapeExpr/BroadcastShape.cs @@ -41,9 +41,8 @@ public Cost Visit(ICostEvaluateContext context, BroadcastShape target) public Expr Visit(IShapeEvaluateContext context, BroadcastShape target) { var inShape = context.GetArgumentShape(target, BroadcastShape.Inputs); - var len = ((IR.Tuple)inShape).Fields.ToArray().Aggregate((Expr)1, (i, call) => IR.F.Math.Max(i, call)); - var bn = IR.F.Tensors.Cast(len, DataTypes.Int32); - return bn; + var len = ((IR.Tuple)inShape).Fields.ToArray().Aggregate((Expr)1L, (i, call) => IR.F.Math.Max(i, call)); + return len; } public Metric Visit(IMetricEvaluateContext context, BroadcastShape target) diff --git a/src/Nncase.Evaluator/ShapeExpr/GetPaddings.cs b/src/Nncase.Evaluator/ShapeExpr/GetPaddings.cs new file mode 100644 index 0000000000..5d5d775ea8 --- /dev/null +++ b/src/Nncase.Evaluator/ShapeExpr/GetPaddings.cs @@ -0,0 +1,89 @@ +// Copyright (c) Canaan Inc. All rights reserved. +// Licensed under the Apache license. See LICENSE file in the project root for full license information. + +using System; +using System.Linq; +using Nncase.CostModel; +using Nncase.Diagnostics; +using Nncase.IR; +using Nncase.IR.ShapeExpr; +using Nncase.IR.Tensors; +using Nncase.Utilities; +using static Nncase.IR.F.Tensors; + +namespace Nncase.Evaluator.ShapeExpr; + +public partial class GetPaddingsEvaluator : IEvaluator, ITypeInferencer, ICostEvaluator, IShapeEvaluator, IMetricEvaluator +{ + public static Expr ConcatPadding(Expr[] padH, Expr[] padW) + { + // return [[padh_before, padh_after], + // [padw_before, padw_after]] + return Stack( + new IR.Tuple( + Stack(new IR.Tuple(padH), 0), + Stack(new IR.Tuple(padW), 0)), + 0); + } + + public IValue Visit(IEvaluateContext context, GetPaddings target) + { + var inShape = context.GetArgumentValueAsArray(target, GetPaddings.InputShape); + var wShape = context.GetArgumentValueAsArray(target, GetPaddings.WeightsShape); + var strides = context.GetArgumentValueAsArray(target, GetPaddings.Strides); + var dilations = context.GetArgumentValueAsArray(target, GetPaddings.Dilations); + var same = context.GetArgumentValueAsScalar(target, GetPaddings.Same); + var lower = context.GetArgumentValueAsScalar(target, GetPaddings.Lower); + var padH = GetWindowedPadding(inShape[2], wShape[2], strides[0], dilations[0], same, lower); + var padW = GetWindowedPadding(inShape[3], wShape[3], strides[1], dilations[1], same, lower); + return ConcatPadding(padH, padW).Evaluate(); + } + + public IRType Visit(ITypeInferenceContext context, GetPaddings target) + { + return new TensorType(DataTypes.Int64, new[] { 2, 2 }); + } + + public Cost Visit(ICostEvaluateContext context, GetPaddings target) + { + return CostUtility.GetShapeExprCost(); + } + + public Expr Visit(IShapeEvaluateContext context, GetPaddings target) + { + return new[] { 2, 2 }; + } + + public Metric Visit(IMetricEvaluateContext context, GetPaddings target) + { + var returnType = context.GetReturnType(); + return new() + { + [MetricFactorNames.OffChipMemoryTraffic] = CostUtility.GetMemoryAccess(returnType), + }; + } + + private static Expr[] GetWindowedPadding(Expr inputSize, Expr filter, Expr stride, Expr dilation, bool same, bool lower = false) + { + var i32InputSize = Cast(inputSize, DataTypes.Int32); + var i32Filter = Cast(filter, DataTypes.Int32); + var i32Stride = Cast(stride, DataTypes.Int32); + var i32Dilation = Cast(dilation, DataTypes.Int32); + var outputSize = IR.Util.GetWindowedOutputSize(i32InputSize, i32Filter, i32Stride, i32Dilation, same, false); + return GetWindowedPaddingValue(i32InputSize, outputSize, i32Filter, i32Stride, i32Dilation, lower); + } + + private static Expr[] GetWindowedPaddingValue(Expr inputSize, Expr outputSize, Expr filter, Expr stride, Expr dilation, bool lower) + { + var effectiveFilterSize = ((filter - 1) * dilation) + 1; + var padding = IR.F.Math.Max(0, ((outputSize - 1) * stride) + effectiveFilterSize - inputSize); + var before = Cast(padding / 2, DataTypes.Int32); + var after = Cast(padding - (padding / 2), DataTypes.Int32); + if (lower) + { + return new[] { IR.F.Math.Max(before, after), IR.F.Math.Min(before, after) }; + } + + return new[] { before, after }; + } +} diff --git a/src/Nncase.Evaluator/ShapeExpr/ReshapeShape.cs b/src/Nncase.Evaluator/ShapeExpr/ReshapeShape.cs new file mode 100644 index 0000000000..c8b7d1a536 --- /dev/null +++ b/src/Nncase.Evaluator/ShapeExpr/ReshapeShape.cs @@ -0,0 +1,50 @@ +// Copyright (c) Canaan Inc. All rights reserved. +// Licensed under the Apache license. See LICENSE file in the project root for full license information. + +using System; +using System.Linq; +using Nncase.CostModel; +using Nncase.Diagnostics; +using Nncase.IR; +using Nncase.IR.ShapeExpr; +using Nncase.IR.Tensors; +using Nncase.Utilities; + +namespace Nncase.Evaluator.ShapeExpr; + +public partial class ReshapeShapeEvaluator : IEvaluator, ITypeInferencer, ICostEvaluator, IShapeEvaluator, IMetricEvaluator +{ + public IValue Visit(IEvaluateContext context, ReshapeShape target) + { + var inShape = context.GetArgumentValueAsArray(target, ReshapeShape.InputShape); + var shape = context.GetArgumentValueAsTensor(target, ReshapeShape.Shape); + var t = IR.F.Tensors.Reshape(new Var(new TensorType(DataTypes.Float32, inShape)), shape); + return ShapeExprUtility.GetShapeValue(t); + } + + public IRType Visit(ITypeInferenceContext context, ReshapeShape target) + { + var shape = context.CheckArgumentType(target, ReshapeShape.Shape); + return new TensorType(DataTypes.Int64, shape.Shape.ToValueArray()); + } + + public Cost Visit(ICostEvaluateContext context, ReshapeShape target) + { + return CostUtility.GetShapeExprCost(); + } + + public Expr Visit(IShapeEvaluateContext context, ReshapeShape target) + { + var shape = context.GetArgument(target, ReshapeShape.Shape); + return shape.CheckedShape.ToValueArray(); + } + + public Metric Visit(IMetricEvaluateContext context, ReshapeShape target) + { + var returnType = context.GetReturnType(); + return new() + { + [MetricFactorNames.OffChipMemoryTraffic] = CostUtility.GetMemoryAccess(returnType), + }; + } +} diff --git a/src/Nncase.Evaluator/ShapeExpr/ShapeExprModule.cs b/src/Nncase.Evaluator/ShapeExpr/ShapeExprModule.cs index bbc3631372..e0a1ec3505 100644 --- a/src/Nncase.Evaluator/ShapeExpr/ShapeExprModule.cs +++ b/src/Nncase.Evaluator/ShapeExpr/ShapeExprModule.cs @@ -20,5 +20,10 @@ public void ConfigureServices(IRegistrator registrator) registrator.RegisterManyInterface(reuse: Reuse.Singleton); registrator.RegisterManyInterface(reuse: Reuse.Singleton); registrator.RegisterManyInterface(reuse: Reuse.Singleton); + registrator.RegisterManyInterface(reuse: Reuse.Singleton); + registrator.RegisterManyInterface(reuse: Reuse.Singleton); + registrator.RegisterManyInterface(reuse: Reuse.Singleton); + registrator.RegisterManyInterface(reuse: Reuse.Singleton); + registrator.RegisterManyInterface(reuse: Reuse.Singleton); } } diff --git a/src/Nncase.Evaluator/ShapeExpr/SqueezeShape.cs b/src/Nncase.Evaluator/ShapeExpr/SqueezeShape.cs new file mode 100644 index 0000000000..df1c668bdf --- /dev/null +++ b/src/Nncase.Evaluator/ShapeExpr/SqueezeShape.cs @@ -0,0 +1,57 @@ +// Copyright (c) Canaan Inc. All rights reserved. +// Licensed under the Apache license. See LICENSE file in the project root for full license information. + +using System; +using System.Linq; +using Nncase.CostModel; +using Nncase.Diagnostics; +using Nncase.IR; +using Nncase.IR.ShapeExpr; +using Nncase.IR.Tensors; +using Nncase.Utilities; + +namespace Nncase.Evaluator.ShapeExpr; + +public partial class SqueezeShapeEvaluator : IEvaluator, ITypeInferencer, ICostEvaluator, IShapeEvaluator, IMetricEvaluator +{ + public IValue Visit(IEvaluateContext context, SqueezeShape target) + { + var inShape = context.GetArgumentValueAsArray(target, SqueezeShape.InputShape); + var dims = context.GetArgumentValueAsTensor(target, SqueezeShape.Dim); + var t = IR.F.Tensors.Squeeze(new Var(new TensorType(DataTypes.Float32, inShape)), dims); + return ShapeExprUtility.GetShapeValue(t); + } + + public IRType Visit(ITypeInferenceContext context, SqueezeShape target) + { + var input = context.GetArgument(target, SqueezeShape.InputShape); + var dims = context.CheckArgumentType(target, SqueezeShape.Dim); + if (!input.CheckedShape.IsFixed) + { + return new TensorType(DataTypes.Int64, new[] { Dimension.Unknown }); + } + + return new TensorType(DataTypes.Int64, new[] { input.CheckedShape.Size - dims.Shape[0] }); + } + + public Cost Visit(ICostEvaluateContext context, SqueezeShape target) + { + return CostUtility.GetShapeExprCost(); + } + + public Expr Visit(IShapeEvaluateContext context, SqueezeShape target) + { + var input = context.GetArgument(target, SqueezeShape.InputShape); + var dims = context.GetArgument(target, SqueezeShape.Dim); + return new[] { input.CheckedShape.Size - dims.CheckedShape[0].FixedValue }; + } + + public Metric Visit(IMetricEvaluateContext context, SqueezeShape target) + { + var returnType = context.GetReturnType(); + return new() + { + [MetricFactorNames.OffChipMemoryTraffic] = CostUtility.GetMemoryAccess(returnType), + }; + } +} diff --git a/src/Nncase.Evaluator/ShapeExpr/TransposeShape.cs b/src/Nncase.Evaluator/ShapeExpr/TransposeShape.cs new file mode 100644 index 0000000000..49a1046627 --- /dev/null +++ b/src/Nncase.Evaluator/ShapeExpr/TransposeShape.cs @@ -0,0 +1,51 @@ +// Copyright (c) Canaan Inc. All rights reserved. +// Licensed under the Apache license. See LICENSE file in the project root for full license information. + +using System; +using System.Linq; +using NetFabric.Hyperlinq; +using Nncase.CostModel; +using Nncase.Diagnostics; +using Nncase.IR; +using Nncase.IR.ShapeExpr; +using Nncase.IR.Tensors; +using Nncase.Utilities; + +namespace Nncase.Evaluator.ShapeExpr; + +public partial class TransposeShapeEvaluator : IEvaluator, ITypeInferencer, ICostEvaluator, IShapeEvaluator, IMetricEvaluator +{ + public IValue Visit(IEvaluateContext context, TransposeShape target) + { + var inShape = context.GetArgumentValueAsArray(target, TransposeShape.InputShape); + var perm = context.GetArgumentValueAsTensor(target, TransposeShape.Perm); + var t = IR.F.Tensors.Transpose(new Var(new TensorType(DataTypes.Float32, inShape)), perm); + return ShapeExprUtility.GetShapeValue(t); + } + + public IRType Visit(ITypeInferenceContext context, TransposeShape target) + { + var tt = context.CheckArgumentType(target, TransposeShape.InputShape); + return new TensorType(DataTypes.Int64, new[] { tt.Shape[0] }); + } + + public Cost Visit(ICostEvaluateContext context, TransposeShape target) + { + return CostUtility.GetShapeExprCost(); + } + + public Expr Visit(IShapeEvaluateContext context, TransposeShape target) + { + var input = context.GetArgument(target, TransposeShape.Perm); + return input.CheckedShape[0].FixedValue; + } + + public Metric Visit(IMetricEvaluateContext context, TransposeShape target) + { + var returnType = context.GetReturnType(); + return new() + { + [MetricFactorNames.OffChipMemoryTraffic] = CostUtility.GetMemoryAccess(returnType), + }; + } +} diff --git a/src/Nncase.Evaluator/ShapeExpr/UnsqueezeShape.cs b/src/Nncase.Evaluator/ShapeExpr/UnsqueezeShape.cs new file mode 100644 index 0000000000..c195b6c2dc --- /dev/null +++ b/src/Nncase.Evaluator/ShapeExpr/UnsqueezeShape.cs @@ -0,0 +1,57 @@ +// Copyright (c) Canaan Inc. All rights reserved. +// Licensed under the Apache license. See LICENSE file in the project root for full license information. + +using System; +using System.Linq; +using Nncase.CostModel; +using Nncase.Diagnostics; +using Nncase.IR; +using Nncase.IR.ShapeExpr; +using Nncase.IR.Tensors; +using Nncase.Utilities; + +namespace Nncase.Evaluator.ShapeExpr; + +public partial class UnsqueezeShapeEvaluator : IEvaluator, ITypeInferencer, ICostEvaluator, IShapeEvaluator, IMetricEvaluator +{ + public IValue Visit(IEvaluateContext context, UnsqueezeShape target) + { + var inShape = context.GetArgumentValueAsArray(target, UnsqueezeShape.InputShape); + var dims = context.GetArgumentValueAsTensor(target, UnsqueezeShape.Dim); + var t = IR.F.Tensors.Unsqueeze(new Var(new TensorType(DataTypes.Float32, inShape)), dims); + return ShapeExprUtility.GetShapeValue(t); + } + + public IRType Visit(ITypeInferenceContext context, UnsqueezeShape target) + { + var input = context.CheckArgumentType(target, UnsqueezeShape.InputShape); + var dims = context.CheckArgumentType(target, UnsqueezeShape.Dim); + if (!input.Shape.IsFixed) + { + return new TensorType(DataTypes.Int64, new[] { Dimension.Unknown }); + } + + return new TensorType(DataTypes.Int64, new[] { input.Shape.Size + dims.Shape[0] }); + } + + public Cost Visit(ICostEvaluateContext context, UnsqueezeShape target) + { + return CostUtility.GetShapeExprCost(); + } + + public Expr Visit(IShapeEvaluateContext context, UnsqueezeShape target) + { + var input = context.GetArgument(target, UnsqueezeShape.InputShape); + var dims = context.GetArgument(target, UnsqueezeShape.Dim); + return IR.F.Tensors.Stack(new IR.Tuple(new[] { IR.F.Tensors.ShapeOf(input)[0] + (long)dims.CheckedShape[0].FixedValue }), 0); + } + + public Metric Visit(IMetricEvaluateContext context, UnsqueezeShape target) + { + var returnType = context.GetReturnType(); + return new() + { + [MetricFactorNames.OffChipMemoryTraffic] = CostUtility.GetMemoryAccess(returnType), + }; + } +} diff --git a/src/Nncase.Evaluator/Tensors/Concat.cs b/src/Nncase.Evaluator/Tensors/Concat.cs index 994e76de22..d1098ccf7b 100644 --- a/src/Nncase.Evaluator/Tensors/Concat.cs +++ b/src/Nncase.Evaluator/Tensors/Concat.cs @@ -54,8 +54,8 @@ public Expr Visit(IShapeEvaluateContext context, Concat target) var inShape = context.GetArgumentShape(target, Concat.Input); var axis = context.GetArgument(target, Concat.Axis); var axisV = ShapeExprUtility.Positive(axis, inShape[0]); - var inShapes = ((IR.Tuple)inShape).Fields.ToArray().Select(x => Cast(x, DataTypes.Int32)).ToArray(); - var dim = inShapes.ToArray().Aggregate((Expr)0, (sum, shape) => sum + shape[axisV]); + var inShapes = ((IR.Tuple)inShape).Fields.ToArray().Select(x => Cast(x, DataTypes.Int64)).ToArray(); + var dim = inShapes.ToArray().Aggregate((Expr)0L, (sum, shape) => sum + shape[axisV]); var outShape = ShapeExprUtility.Replace(inShapes[0], axisV, dim); return outShape; } diff --git a/src/Nncase.Evaluator/Tensors/Range.cs b/src/Nncase.Evaluator/Tensors/Range.cs index 5f185fe350..dac1afb1d1 100644 --- a/src/Nncase.Evaluator/Tensors/Range.cs +++ b/src/Nncase.Evaluator/Tensors/Range.cs @@ -95,6 +95,6 @@ public Expr Visit(IShapeEvaluateContext context, Range target) var begin = context.GetArgument(target, Range.Begin); var end = context.GetArgument(target, Range.End); var step = context.GetArgument(target, Range.Step); - return ShapeExprUtility.StackOne((end - begin) / step); + return IR.F.Tensors.Cast(StackOne((end - begin) / step), DataTypes.Int64); } } diff --git a/src/Nncase.Evaluator/Tensors/Reshape.cs b/src/Nncase.Evaluator/Tensors/Reshape.cs index 615728f7c7..38c4d150ee 100644 --- a/src/Nncase.Evaluator/Tensors/Reshape.cs +++ b/src/Nncase.Evaluator/Tensors/Reshape.cs @@ -53,32 +53,9 @@ Cost ICostEvaluator.Visit(ICostEvaluateContext context, Reshape target) public Expr Visit(IShapeEvaluateContext context, Reshape target) { + var inShape = context.GetArgumentShape(target, Reshape.Input); var shape = context.GetArgument(target, Reshape.Shape); - var inputShape = Cast(context.GetArgumentShape(target, Reshape.Input), DataTypes.Int32); - if (shape is TensorConst shapeConst) - { - var shapeArray = shapeConst.Value.ToArray(); - var negIndex = shapeArray.IndexOf(-1); - if (negIndex < 0) - { - return shapeArray; - } - - var dim = Prod(inputShape) / System.Math.Abs(shapeArray.Aggregate((s, x) => x * s)); - var rhs = shapeArray.Select((_, i) => i == negIndex ? dim + 1 : (Expr)0).ToArray(); - var newShape = Stack(new IR.Tuple(rhs), 0); - - // dim = Product(inShape) / Produce(Reshape.Shape) - // e.g. [1, 3, -1, 24] + [dim + 1, 0] = [1, 3, dim, 24] - return newShape + shapeArray; - } - - shape = Cast(shape, DataTypes.Int32); - var iSize = Prod(inputShape); - var sSize = Prod(shape); - var negDimInfactValue = iSize / Abs(sSize); - var index = IndexOf(shape, -1); - return new If(sSize < 0, ShapeExprUtility.Replace(shape, index, negDimInfactValue), shape); + return IR.F.ShapeExpr.ReshapeShape(inShape, shape); } public Metric Visit(IMetricEvaluateContext context, Reshape target) @@ -93,12 +70,10 @@ private IRType Visit(ITypeInferenceContext context, Reshape target, TensorType i return input; } - if (context.GetArgument(target, Reshape.Shape) is TensorConst shapeConst && - input.Shape.IsFixed) + if (context.GetArgument(target, Reshape.Shape) is TensorConst shapeConst) { var shapeValue = shapeConst.Value.ToArray(); var negCount = shapeValue.Count(IsMinus1); - var inputSize = input.Shape.Prod().FixedValue; var shapeSize = shapeValue.Aggregate(1, (x, y) => x * y); if (negCount > 1) { @@ -106,27 +81,39 @@ private IRType Visit(ITypeInferenceContext context, Reshape target, TensorType i $"Reshape at most one dimension of the new shape can be -1," + $" shape:{shapeValue}"); } - else if (negCount < 1) + + if (input.Shape.IsFixed) { - if (inputSize != shapeSize) + var inputSize = input.Shape.Prod().FixedValue; + if (negCount < 1) { - return new InvalidType("Reshape input shape size and param shape size must be same," + - $" shape:{shapeValue.ToArray().Aggregate(string.Empty, (s, i) => s + i + " ")}, input shape${string.Join(",", input.Shape)}"); - } + if (inputSize != shapeSize) + { + return new InvalidType("Reshape input shape size and param shape size must be same," + + $" shape:{shapeValue.ToArray().Aggregate(string.Empty, (s, i) => s + i + " ")}, input shape${string.Join(",", input.Shape)}"); + } - return input with { Shape = new Shape(shapeValue) }; + return input with { Shape = new Shape(shapeValue) }; + } + else + { + shapeSize = -shapeSize; + var negIndex = shapeValue.Select((dim, index) => (dim, index)).First(x => IsMinus1(x.dim)).index; + if (inputSize % shapeSize != 0) + { + return new InvalidType("Reshape input size must be divisible by shapeSize when has -1"); + } + + shapeValue[negIndex] = inputSize / shapeSize; + return input with { Shape = new Shape(shapeValue) }; + } } else { - shapeSize = -shapeSize; - var negIndex = shapeValue.Select((dim, index) => (dim, index)).First(x => IsMinus1(x.dim)).index; - if (inputSize % shapeSize != 0) + return input with { - return new InvalidType("Reshape input size must be divisible by shapeSize when has -1"); - } - - shapeValue[negIndex] = inputSize / shapeSize; - return input with { Shape = new Shape(shapeValue) }; + Shape = new Shape(shapeValue.Select(x => x == -1 ? Dimension.Unknown : x).ToArray()), + }; } } diff --git a/src/Nncase.Evaluator/Tensors/Slice.cs b/src/Nncase.Evaluator/Tensors/Slice.cs index 219894f0da..eada657d01 100644 --- a/src/Nncase.Evaluator/Tensors/Slice.cs +++ b/src/Nncase.Evaluator/Tensors/Slice.cs @@ -104,7 +104,7 @@ public Expr Visit(IShapeEvaluateContext context, Slice target) return Ceil(Abs(end - begin) / Abs(stride)); }).ToArray(); - return Stack(new IR.Tuple(outDims), 0); + return Cast(Stack(new IR.Tuple(outDims), 0), DataTypes.Int64); } /// Axis. diff --git a/src/Nncase.Evaluator/Tensors/Squeeze.cs b/src/Nncase.Evaluator/Tensors/Squeeze.cs index 05517c5b4d..19573e7208 100644 --- a/src/Nncase.Evaluator/Tensors/Squeeze.cs +++ b/src/Nncase.Evaluator/Tensors/Squeeze.cs @@ -38,28 +38,9 @@ public Cost Visit(ICostEvaluateContext context, Squeeze target) public Expr Visit(IShapeEvaluateContext context, Squeeze target) { - var inShape = context.GetArgumentShape(target, Squeeze.Input); - var input = context.GetArgument(target, Squeeze.Input); + var input = context.GetArgumentShape(target, Squeeze.Input); var dims = context.GetArgument(target, Squeeze.Dim); - if (dims is TensorConst dimConst) - { - var rank = input.CheckedShape.Count; - var dimValue = dimConst.Value.ToArray().Select(x => x < 0 ? x + rank : x).ToArray(); - var outDims = Enumerable.Range(0, rank).Where(i => !dimValue.Contains(i)).Select(i => inShape[i]).ToArray(); - if (outDims.Length == 0) - { - return 1; - } - - if (outDims.Length == input.CheckedShape.Rank) - { - throw new InvalidOperationException("Bad Squeeze Shape Expr"); - } - - return IR.F.Tensors.Stack(new IR.Tuple(outDims), 0); - } - - throw new NotImplementedException(); + return IR.F.ShapeExpr.SqueezeShape(input, dims); } public Metric Visit(IMetricEvaluateContext context, Squeeze target) diff --git a/src/Nncase.Evaluator/Tensors/Stack.cs b/src/Nncase.Evaluator/Tensors/Stack.cs index 00cb5c4472..4d07bda39e 100644 --- a/src/Nncase.Evaluator/Tensors/Stack.cs +++ b/src/Nncase.Evaluator/Tensors/Stack.cs @@ -58,10 +58,10 @@ public Cost Visit(ICostEvaluateContext context, Stack target) public Expr Visit(IShapeEvaluateContext context, Stack target) { var inShape = context.GetArgumentShape(target, Stack.Inputs); - Expr one = new[] { 1 }; + Expr one = new[] { 1L }; if (inShape[0].CheckedShape.IsScalar) { - one = 1; + one = 1L; } return IR.F.Tensors.Concat(new IR.Tuple(inShape[0], one), 0); diff --git a/src/Nncase.Evaluator/Tensors/Tile.cs b/src/Nncase.Evaluator/Tensors/Tile.cs index 122f122d5a..19bebffdfa 100644 --- a/src/Nncase.Evaluator/Tensors/Tile.cs +++ b/src/Nncase.Evaluator/Tensors/Tile.cs @@ -46,7 +46,7 @@ public Expr Visit(IShapeEvaluateContext context, Tile target) { var inShape = context.GetArgumentShape(target, Tile.Input); var repeats = context.GetArgument(target, Tile.Repeats); - return inShape * IR.F.Tensors.Cast(repeats, DataTypes.Int32); + return inShape * IR.F.Tensors.Cast(repeats, DataTypes.Int64); } public Metric Visit(IMetricEvaluateContext context, Tile target) diff --git a/src/Nncase.Evaluator/Tensors/Transpose.cs b/src/Nncase.Evaluator/Tensors/Transpose.cs index e4bd2ee45f..77e74d07f1 100644 --- a/src/Nncase.Evaluator/Tensors/Transpose.cs +++ b/src/Nncase.Evaluator/Tensors/Transpose.cs @@ -92,17 +92,9 @@ public Metric Visit(IMetricEvaluateContext context, Transpose target) public Expr Visit(IShapeEvaluateContext context, Transpose target) { - var perm = context.GetArgument(target, Transpose.Perm); - var rank = context.GetArgument(target, Transpose.Input).CheckedShape.Rank; - var permValue = IR.F.Tensors.Cast(perm, DataTypes.Int32); var inShape = context.GetArgumentShape(target, Transpose.Input); - var outShape = Enumerable.Range(0, rank).Select(i => inShape[i]).ToArray(); - for (int i = 0; i < rank; i++) - { - outShape[i] = inShape[permValue[i]]; - } - - return IR.F.Tensors.Stack(new IR.Tuple(outShape), 0); + var perm = context.GetArgument(target, Transpose.Perm); + return IR.F.ShapeExpr.TransposeShape(inShape, perm); } private IRType Visit(ITypeInferenceContext context, Transpose target, TensorType input) diff --git a/src/Nncase.Evaluator/Tensors/UnSqueeze.cs b/src/Nncase.Evaluator/Tensors/UnSqueeze.cs index b8c937c44a..bd86940fee 100644 --- a/src/Nncase.Evaluator/Tensors/UnSqueeze.cs +++ b/src/Nncase.Evaluator/Tensors/UnSqueeze.cs @@ -43,29 +43,9 @@ public Cost Visit(ICostEvaluateContext context, Unsqueeze target) public Expr Visit(IShapeEvaluateContext context, Unsqueeze target) { + var input = context.GetArgumentShape(target, Unsqueeze.Input); var dims = context.GetArgument(target, Unsqueeze.Dim); - if (dims is TensorConst dimsConst) - { - var dimsValue = dimsConst.Value.ToArray(); - var outShape = context.GetArgumentShape(target, Unsqueeze.Input); - - foreach (var dimVal in dimsValue) - { - if (dimVal >= 0) - { - outShape = ShapeExprUtility.Insert(outShape, dimVal, 1); - } - else - { - var index = IR.F.Math.Max(IR.F.Tensors.Cast(IR.F.Tensors.ShapeOf(outShape)[0], DataTypes.Int32) + dimVal + 1, 0); - outShape = ShapeExprUtility.Insert(outShape, index, 1); - } - } - - return outShape; - } - - throw new NotImplementedException(); + return IR.F.ShapeExpr.UnsqueezeShape(input, dims); } public Metric Visit(IMetricEvaluateContext context, Unsqueeze target) => Metric.Zero; diff --git a/src/Nncase.Importer/TFLite/Conv2D.cs b/src/Nncase.Importer/TFLite/Conv2D.cs index 0fc41dfb7f..260ee76d0e 100644 --- a/src/Nncase.Importer/TFLite/Conv2D.cs +++ b/src/Nncase.Importer/TFLite/Conv2D.cs @@ -29,19 +29,14 @@ private Expr VisitConv2D(in tflite.Operator op) weights = F.Tensors.NHWCToNCHW(weights); var bias = GetInputExprs(op, 2); var options = op.BuiltinOptionsAsConv2DOptions(); - var (inH, inW) = Util.GetHW(input); - var (fH, fW) = Util.GetHW(weights); var strideH = options.StrideH; var strideW = options.StrideW; var dilationH = options.DilationHFactor; var dilationW = options.DilationWFactor; - var padH = Util.GetWindowedPadding(inH, fH, strideH, dilationH, options.Padding == tflite.Padding.SAME); - var padW = Util.GetWindowedPadding(inW, fW, strideW, dilationW, options.Padding == tflite.Padding.SAME); var stride = Tensor.From(new[] { strideH, strideW }, new[] { 2 }); var dilation = Tensor.From(new[] { dilationH, dilationW }, new[] { 2 }); - var padding = Util.ConcatPadding(padH, padW); + var padding = Util.GetPaddings(input, weights, stride, dilation, options.Padding == tflite.Padding.SAME, false); var clamp = ToFloatClampRange(options.FusedActivationFunction); - var inputQuantParams = GetInputQuantParams(op, 0); var weightsQuantParams = GetInputQuantParams(op, 1); var biasQuantParams = GetInputQuantParams(op, 2); @@ -123,19 +118,14 @@ private Expr VisitDepthwiseConv2D(in tflite.Operator op) var bias = GetInputExprs(op, 2); input = F.Tensors.NHWCToNCHW(input); weights = F.Tensors.Transpose(weights, new[] { 3, 0, 1, 2 }); - _ = GetTensorShape(GetInputTensor(op, 1)); var options = op.BuiltinOptionsAsDepthwiseConv2DOptions(); - var (inH, inW) = Util.GetHW(input); - var (fH, fW) = Util.GetHW(weights); var strideH = options.StrideH; var strideW = options.StrideW; var dilationH = options.DilationHFactor; var dilationW = options.DilationWFactor; - var padH = Util.GetWindowedPadding(inH, fH, strideH, dilationH, options.Padding == tflite.Padding.SAME); - var padW = Util.GetWindowedPadding(inW, fW, strideW, dilationW, options.Padding == tflite.Padding.SAME); var stride = Tensor.From(new[] { strideH, strideW }, new[] { 2 }); var dilation = Tensor.From(new[] { dilationH, dilationW }, new[] { 2 }); - var padding = Util.ConcatPadding(padH, padW); + var padding = Util.GetPaddings(input, weights, stride, dilation, options.Padding == tflite.Padding.SAME, false); var depthMul = options.DepthMultiplier; if (depthMul != 1) { diff --git a/src/Nncase.Importer/TFLite/Conv2DTranspose.cs b/src/Nncase.Importer/TFLite/Conv2DTranspose.cs index d5687e7cdb..ec8e64f9af 100644 --- a/src/Nncase.Importer/TFLite/Conv2DTranspose.cs +++ b/src/Nncase.Importer/TFLite/Conv2DTranspose.cs @@ -32,17 +32,15 @@ private Expr VisitConv2DTranspose(in tflite.Operator op) } var options = op.BuiltinOptionsAsTransposeConvOptions(); - var (_, _) = Util.GetHW(input); - var (fH, fW) = Util.GetHW(weights, true); var strideH = options.StrideH; var strideW = options.StrideW; var dilationH = 1; var dilationW = 1; - var padH = Util.GetWindowedPadding(newOutShape[2], fH, strideH, dilationH, options.Padding == tflite.Padding.SAME); - var padW = Util.GetWindowedPadding(newOutShape[3], fW, strideW, dilationW, options.Padding == tflite.Padding.SAME); var stride = Tensor.From(new[] { strideH, strideW }, new[] { 2 }); var dilation = Tensor.From(new[] { dilationH, dilationW }, new[] { 2 }); - var padding = Util.ConcatPadding(padH, padW); + var oldWShape = F.Tensors.ShapeOf(weights); + var wShape = F.Tensors.Stack(new IR.Tuple(oldWShape[0], oldWShape[3], oldWShape[1], oldWShape[2]), 0); + var padding = F.ShapeExpr.GetPaddings(F.Tensors.Stack(new IR.Tuple(newOutShape), 0), wShape, stride, dilation, options.Padding == tflite.Padding.SAME, false); var clamp = ValueRange.Full; return F.Tensors.NCHWToNHWC(F.Math.Clamp( diff --git a/src/Nncase.Importer/Util.cs b/src/Nncase.Importer/Util.cs index a3ca52d74e..762d503235 100644 --- a/src/Nncase.Importer/Util.cs +++ b/src/Nncase.Importer/Util.cs @@ -90,13 +90,9 @@ public static Expr[] GetWindowedPadding(Expr inputSize, Expr filter, Expr stride } // lower used for onnx when auto_pad attr is SAME_LOWER - public static Expr GetPaddings(Expr input, Expr weights, long[] stride, long[] dilation, bool same, bool lower = false) + public static Expr GetPaddings(Expr input, Expr weights, Expr stride, Expr dilation, bool same, bool lower = false) { - var (inH, inW) = GetHW(input); - var (fH, fW) = GetHW(weights); - var padH = GetWindowedPadding(inH, fH, (int)stride[0], (int)dilation[0], same, lower); - var padW = GetWindowedPadding(inW, fW, (int)stride[1], (int)dilation[1], same, lower); - return ConcatPadding(padH, padW); + return IR.F.ShapeExpr.GetPaddings(ShapeOf(input), ShapeOf(weights), stride, dilation, same, lower); } public static Expr ComputeSplit(Expr input, long outputSize, long axis) diff --git a/src/Nncase.Passes/Rules/Neutral/FoldReshape.cs b/src/Nncase.Passes/Rules/Neutral/FoldReshape.cs index a5324fd11a..2d12883101 100644 --- a/src/Nncase.Passes/Rules/Neutral/FoldReshape.cs +++ b/src/Nncase.Passes/Rules/Neutral/FoldReshape.cs @@ -78,6 +78,11 @@ public sealed partial class ReshapeToTranspose : IRewriteRule private Expr? GetReplace(Expr input, Call call) { + if (input.CheckedShape.Rank <= 1) + { + return null; + } + var newShape = call.CheckedShape.ToValueArray(); var inShape = input.CheckedShape.ToValueArray(); var sigNewShape = newShape.Where(x => x != 1).ToArray(); diff --git a/src/Nncase.Passes/Rules/Neutral/FoldSqueeze.cs b/src/Nncase.Passes/Rules/Neutral/FoldSqueeze.cs new file mode 100644 index 0000000000..87437d0bdc --- /dev/null +++ b/src/Nncase.Passes/Rules/Neutral/FoldSqueeze.cs @@ -0,0 +1,62 @@ +// Copyright (c) Canaan Inc. All rights reserved. +// Licensed under the Apache license. See LICENSE file in the project root for full license information. + +using System; +using System.Collections.Generic; +using System.Collections.Immutable; +using System.Linq; +using Nncase.IR; +using Nncase.IR.Math; +using Nncase.IR.Tensors; +using Nncase.Passes; +using Nncase.PatternMatch; +using static Nncase.IR.F.Math; +using static Nncase.IR.F.Tensors; +using static Nncase.IR.TypePatternUtility; +using static Nncase.PatternMatch.F.Math; +using static Nncase.PatternMatch.F.Tensors; +using static Nncase.PatternMatch.Utility; + +namespace Nncase.Passes.Rules.Neutral; + +[RuleGenerator] +public partial class FoldUnsqueezeSqueeze : RewriteRule +{ + /// + public override Pattern Pattern => IsUnsqueeze( + "unsqu", + "output", + IsSqueeze(IsWildcard("input"), IsTensorConst("sqAxes")), + IsTensorConst("unsqAxes")); + + private Expr? GetReplace(Call output, Expr input) + { + if (output.CheckedShape.SequenceEqual(input.CheckedShape)) + { + return input; + } + + return null; + } +} + +[RuleGenerator] +public partial class FoldSqueezeUnsqueeze : RewriteRule +{ + /// + public override Pattern Pattern => IsSqueeze( + "sqOp", + "output", + IsUnsqueeze(IsWildcard("input"), IsTensorConst("unsqAxes")), + IsTensorConst("sqAxes")); + + private Expr? GetReplace(Call output, Expr input) + { + if (output.CheckedShape.SequenceEqual(input.CheckedShape)) + { + return input; + } + + return null; + } +} diff --git a/src/Nncase.Passes/Rules/Neutral/FoldTranspose.cs b/src/Nncase.Passes/Rules/Neutral/FoldTranspose.cs index c3611f11b7..d5e9d6256f 100644 --- a/src/Nncase.Passes/Rules/Neutral/FoldTranspose.cs +++ b/src/Nncase.Passes/Rules/Neutral/FoldTranspose.cs @@ -101,6 +101,11 @@ public sealed partial class TransposeToReshape : IRewriteRule private Expr? GetReplace(Expr input, Expr tp, Tensor perm, RunPassContext context) { + if (input.CheckedShape.Rank <= 1) + { + return null; + } + // If all significant dims remains ascending order, it can be converted to a reshape. var inShape = input.CheckedShape; var sigAxes = new HashSet(); diff --git a/src/Nncase.Passes/Rules/Neutral/SplitSpaceToBatch.cs b/src/Nncase.Passes/Rules/Neutral/SplitSpaceToBatch.cs new file mode 100644 index 0000000000..4361b2db15 --- /dev/null +++ b/src/Nncase.Passes/Rules/Neutral/SplitSpaceToBatch.cs @@ -0,0 +1,180 @@ +// Copyright (c) Canaan Inc. All rights reserved. +// Licensed under the Apache license. See LICENSE file in the project root for full license information. + +using System; +using System.Collections.Generic; +using System.Linq; +using Nncase.Diagnostics; +using Nncase.IR; +using Nncase.IR.Tensors; +using Nncase.Passes.Rules.ShapeExpr; +using Nncase.PatternMatch; +using Nncase.Utilities; +using OrtKISharp; +using static Nncase.IR.F.Math; +using static Nncase.IR.F.NN; +using static Nncase.IR.F.Tensors; +using static Nncase.IR.TypePatternUtility; +using static Nncase.PatternMatch.F.Math; +using static Nncase.PatternMatch.F.NN; +using static Nncase.PatternMatch.F.Tensors; +using static Nncase.PatternMatch.Utility; + +namespace Nncase.Passes.Rules.Neutral; + +[RuleGenerator] +public partial class SplitSpaceToBatch : RewriteRule +{ + /// + public override Pattern Pattern { get; } = IsSpaceToBatch( + IsWildcard("input") with { TypePattern = HasRank() }, + IsWildcard("blockShape") with { TypePattern = HasFixedShape() }, + IsWildcard("paddings")); + + public Expr? GetReplace(Expr input, Expr blockShape, Expr paddings) + { + var spatialSize = blockShape.CheckedShape.Size; + var remainShapeSize = input.CheckedShape.Rank - spatialSize - 1; + var newPaddings = Enumerable.Repeat((Expr)0, (1 + spatialSize + remainShapeSize) * 2).ToArray(); + for (int i = 0; i < spatialSize; i++) + { + newPaddings[1 + i] = paddings[i, 0]; + newPaddings[1 + (newPaddings.Length / 2) + i] = paddings[i, 1]; + } + + var tmpPaddings = Stack(new IR.Tuple(newPaddings), 0); + var newPaddingsTensor = Transpose(Reshape(tmpPaddings, new long[] { 2, 1 + spatialSize + remainShapeSize }), new long[] { 1, 0 }); + var p = Pad(input, newPaddingsTensor, PadMode.Constant, 0f); + + var padShape = Cast(ShapeOf(p), DataTypes.Int32); + var batchShape1 = StackScalar(padShape[0]); + var spatialShape1 = RangeExec( + spatialSize, + i => Stack(new IR.Tuple(padShape[i + 1] / blockShape[i], blockShape[i]), 0)) + .Aggregate((x, y) => Concat(new IR.Tuple(x, y), 0)); + var remainShape1 = Stack(new IR.Tuple(RangeExec(remainShapeSize, i => padShape[1 + spatialSize + i])), 0); + var reshappedShape1 = Concat( + new IR.Tuple( + batchShape1, + spatialShape1, + remainShape1), + 0); + + var perm = RangeExec(spatialSize, i => (i * 2) + 2) + .Concat(new[] { 0 }) + .Concat(RangeExec(spatialSize, i => (i * 2) + 1)) + .Concat(RangeExec(remainShapeSize, i => i + ((int)spatialSize * 2) + 1)) + .Select(x => (long)x) + .ToArray(); + + var reshappedShape2 = Concat( + input: new IR.Tuple( + StackScalar(padShape[0] * Prod(blockShape)), + Stack(new IR.Tuple(RangeExec(spatialSize, i => padShape[i + 1] / blockShape[i])), 0), + Stack(new IR.Tuple(RangeExec(remainShapeSize, i => padShape[1 + spatialSize + i])), 0)), + 0); + + var reshape1 = Reshape(p, reshappedShape1); + var rt = Transpose(reshape1, perm); + var reshape2 = Reshape(rt, reshappedShape2); + return reshape2; + } + + private T[] RangeExec(long end, Func f) + { + return EndRange(0, (int)end).Select(f).ToArray(); + } + + private IEnumerable EndRange(int begin, int end) + { + return Enumerable.Range(begin, end - begin); + } +} + +[RuleGenerator] +public partial class SplitBatchToSpace : RewriteRule +{ + /// + public override Pattern Pattern { get; } = IsBatchToSpace( + IsWildcard("input") with { TypePattern = HasRank() }, + IsWildcard("blockShape") with { TypePattern = HasFixedShape() }, + IsWildcard("crop")); + + public Expr? GetReplace(Expr input, Expr blockShape, Expr crop) + { + // to nhwc + var input0 = NCHWToNHWC(input); + var blockLen = blockShape.CheckedShape.Size; + var xLen = input0.CheckedShape.Rank; + var xShape = Cast(ShapeOf(input0), DataTypes.Int32); + var spatial = ShapeExprUtility.Slice(xShape, 1, blockLen + 1); + var depth = ShapeExprUtility.Slice(xShape, blockLen + 1, xLen); + var targetSpatial = spatial * blockShape; + + var ccat1 = Concat(new IR.Tuple(spatial, blockShape), 0); + var re1 = Reshape(ccat1, new[] { ccat1.CheckedShape[0].FixedValue / blockLen, blockLen }); + var interLeave = Reshape(Transpose(re1, new long[] { 1, 0 }), new long[] { -1 }); + var shape1 = Concat(new IR.Tuple(new int[] { -1 }, interLeave, depth), 0); + + var g1 = BoostRange(2, (2 * blockLen) + 1, 2); + var g2 = BoostRange(1, (2 * blockLen) + 1, 2); + var g3 = BoostRange(0, xLen + blockLen).ToArray()[1 + (2 * blockLen)]; + var indices = g1.Append(0).Concat(g2).Append(g3); + + var perm = GetPerm(xLen, blockLen); + + var newShape = indices.Select(i => shape1[i]).ToArray(); + var x2 = Reshape(input0, Stack(new IR.Tuple(newShape), 0)); + var tr2 = Transpose(x2, perm); + var shape2 = Concat(new IR.Tuple(new[] { -1 }, targetSpatial, depth), 0); + var x3 = Reshape(tr2, shape2); + + var cropTransposed = Transpose(crop, new long[] { 1, 0 }); + var cropArray = Reshape(cropTransposed, new long[] { -1 }); + var w = cropTransposed.CheckedShape[1].FixedValue; + var cropStart = ShapeExprUtility.Slice(cropArray, 0, w); + var cropEnd = ShapeExprUtility.Slice(cropArray, w, w + w); + var endRange = targetSpatial - cropEnd; + var axesConst = BoostRange(1, blockLen + 1).ToArray(); + var strideConst = Enumerable.Repeat(1, axesConst.Length).ToArray(); + var result = Slice(x3, cropStart, endRange, axesConst, strideConst); + + // to nchw + var transposeResult = NHWCToNCHW(result); + return transposeResult; + } + + private static IEnumerable BoostRange(int start, int end, int step = 1) + { + int x = start; + do + { + yield return x; + x += step; + if ((step < 0 && x <= end) || (step > 0 && end <= x)) + { + break; + } + } + while (true); + } + + private long[] GetPerm(int xLen, int blockLen) + { + var perm = Enumerable.Range(0, xLen + blockLen).ToArray(); + perm[0] = blockLen; + perm[1] = blockLen + 1; + perm[2] = 0; + foreach (var i in BoostRange(3, (blockLen * 2) + 1)) + { + perm[i] = perm[i - 2] + 1; + } + + return perm.Select(x => (long)x).ToArray(); + } + + private T[] ZipExec(T[] a, T[] b, Func f) + { + return a.Zip(b).Select(x => f(x.First, x.Second)).ToArray(); + } +} diff --git a/src/Nncase.Passes/Rules/ShapeBucket/FoldBucketReshape.cs b/src/Nncase.Passes/Rules/ShapeBucket/FoldBucketReshape.cs deleted file mode 100644 index 2c78c5ca35..0000000000 --- a/src/Nncase.Passes/Rules/ShapeBucket/FoldBucketReshape.cs +++ /dev/null @@ -1,44 +0,0 @@ -// Copyright (c) Canaan Inc. All rights reserved. -// Licensed under the Apache license. See LICENSE file in the project root for full license information. - -using System.Linq; -using Nncase.IR; -using Nncase.IR.Tensors; -using Nncase.PatternMatch; -using Nncase.Utilities; -using static Nncase.IR.TypePatternUtility; -using static Nncase.PatternMatch.F.Tensors; -using static Nncase.PatternMatch.Utility; - -namespace Nncase.Passes.Rules.ShapeBucket; - -[RuleGenerator] -public sealed partial class FoldBucketPadReshape : RewriteRule -{ - // Reshape(Gather(Shape, 0, 0), new[] { 0 }) -> GetItem(Shape, 0) - public override Pattern Pattern => IsReshape( - IsBucketPad(null, "bucketPad", IsWildcard(), IsTensorConst()), - IsTensorConst("newShape")); - - private Expr? GetReplace(Call bucketPad, Expr newShape) - { - return ReplaceUtility.ReplaceCallParams(bucketPad, (BucketPad.Shape.Index, newShape)); - } -} - -// todo: squeeze -[RuleGenerator] -public sealed partial class FoldBucketPadUnsqueeze : RewriteRule -{ - // Reshape(Gather(Shape, 0, 0), new[] { 0 }) -> GetItem(Shape, 0) - public override Pattern Pattern => IsUnsqueeze( - null, - "unsqueeze", - IsBucketPad(null, "bucketPad", IsWildcard(), IsTensorConst()), - IsTensorConst()); - - private Expr? GetReplace(Call bucketPad, Call unsqueeze) - { - return ReplaceUtility.ReplaceCallParams(bucketPad, (BucketPad.Shape.Index, unsqueeze.CheckedShape.ToValueArray())); - } -} diff --git a/src/Nncase.Passes/Rules/ShapeBucket/FoldNopTuple.cs b/src/Nncase.Passes/Rules/ShapeBucket/FoldNopTuple.cs new file mode 100644 index 0000000000..edbfd66074 --- /dev/null +++ b/src/Nncase.Passes/Rules/ShapeBucket/FoldNopTuple.cs @@ -0,0 +1,64 @@ +// Copyright (c) Canaan Inc. All rights reserved. +// Licensed under the Apache license. See LICENSE file in the project root for full license information. + +using System.Linq; +using System.Reactive; +using System.Threading.Tasks; +using Nncase.Diagnostics; +using Nncase.IR; +using Nncase.IR.Tensors; +using Nncase.PatternMatch; +using Nncase.Utilities; +using static Nncase.PatternMatch.Utility; +using static Nncase.Utilities.ReplaceUtility; + +namespace Nncase.Passes.Rules.ShapeBucket; + +public class FoldNopTuple : FunctionPass +{ + protected override Task RunCoreAsync(BaseFunction input, RunPassContext context) + { + int i = 0; + while (true) + { + var preHash = input.GetHashCode(); + DumpScope.Current.DumpIR(input, $"{i}_before"); + + new FoldNopTupleVisitior().Visit(input); + DumpScope.Current.DumpIR(input, $"{i++}_after_convert"); + var afterHash = input.GetHashCode(); + if (preHash == afterHash) + { + return Task.FromResult(input); + } + } + } + + internal class FoldNopTupleVisitior : ExprVisitor + { + private bool _changed; + + public FoldNopTupleVisitior() + : base(true) + { + } + + protected override Expr DefaultVisitLeaf(Expr expr) => expr; + + protected override Expr VisitLeafTuple(Tuple expr) + { + if (!_changed && expr.Users.All(user => user is Call { Target: GetItem })) + { + foreach (var user in expr.Users) + { + var index = ((TensorConst)((Call)user).Arguments[GetItem.Index.Index]).Value.ToScalar(); + ReplaceUtility.ReplaceAllUsesWith(user, expr.Fields[index]); + } + + _changed = true; + } + + return expr; + } + } +} diff --git a/src/Nncase.Passes/Rules/ShapeBucket/MergeBucketFusion.cs b/src/Nncase.Passes/Rules/ShapeBucket/MergeBucketFusion.cs index f22e2d4c70..be7dad641b 100644 --- a/src/Nncase.Passes/Rules/ShapeBucket/MergeBucketFusion.cs +++ b/src/Nncase.Passes/Rules/ShapeBucket/MergeBucketFusion.cs @@ -25,16 +25,38 @@ namespace Nncase.Passes.Rules.ShapeBucket; public class MergeBucketFusionPass : FunctionPass { + private readonly bool _greedy; + + public MergeBucketFusionPass(bool greedy) + { + _greedy = greedy; + } + protected override async Task RunCoreAsync(BaseFunction input, RunPassContext context) { + // bool greedy and dynamic var main = (Function)input; + int i = 0; while (true) { var preHash = main.GetHashCode(); - CompilerServices.Rewrite(main, new IRewriteRule[] { new MultiUserCallToFusion(), new MergeTupleFusion() }, new()); - await new MergeSeqBucketFusion().RunAsync(main, context); - IRHelpers.DCE(main); - await new MergeMultiUsersFusion().RunAsync(main, context); + if (_greedy) + { + CompilerServices.Rewrite(main, new IRewriteRule[] { new MultiUserCallToFusion(false, _greedy), new MergeTupleFusion() }, new()); + await new MergeSeqBucketFusion().RunAsync(main, context); + IRHelpers.DCE(main); + await new MergeMultiUsersFusion().RunAsync(main, context); + DumpIR(main, $"{i}_before", "FoldNopTuple"); + await new FoldNopTuple().RunAsync(main, context); + } + else + { + await new MergeSeqBucketFusion().RunAsync(main, context); + IRHelpers.DCE(main); + } + + CheckRepeat(main); + CheckErrorVar(main, main.Parameters.ToArray()); var postHash = main.GetHashCode(); if (preHash == postHash) { @@ -42,6 +64,7 @@ protected override async Task RunCoreAsync(BaseFunction input, Run } } + DumpIR(main, "MergeBucketFusionEnd"); return main; } } @@ -176,10 +199,6 @@ public class MergeMultiUsersFusion : FunctionPass public static bool DetectedRing(Call outerCall, Expr[] users) { - // var users = outerCall.Users.ToArray(); - // todo: fix this,TestComplexExpr - // var userArgs = users.SelectMany(user => ((Call)user).Arguments.ToArray()).Except(users).ToArray(); - // 用这个不过,但是好像会引起其他问题?? var userArgs = users.SelectMany(user => ((Call)user).Arguments.ToArray()).ToArray(); foreach (var arg in userArgs) { @@ -231,23 +250,15 @@ private static (Expr? NewCall, UserInfo[] AllUsers) MergeMultiUserFusion(Call ou // todo: not support if (users.Any(user => user is Tuple)) { - // Console.WriteLine("HasTuple"); return notSupport; } var userInfos = CollectUsers(outerCall, users); - // todo: support only one user, because merge fusion rule is not enough - // maybe a error - // if (userInfos.Length < 2) - // { - // return null; - // } - // has invalid if (userInfos.Length != users.Distinct().ToArray().Length) { - Console.WriteLine("not all fusion call and getItemMode"); + // Console.WriteLine("not all fusion call and getItemMode"); return notSupport; } @@ -601,8 +612,7 @@ protected override Expr VisitLeafCall(Call expr) } // Console.WriteLine($"Match {fusion.Name} counter:{Counter}"); - DumpIR(Root, "OriginRoot", RelPath); - + // DumpIR(Root, "OriginRoot", RelPath); var (newCall, users) = MergeMultiUserFusion(outerCall, fusion); if (newCall != null) { diff --git a/src/Nncase.Passes/Rules/ShapeBucket/MergeCallToFusion.cs b/src/Nncase.Passes/Rules/ShapeBucket/MergeCallToFusion.cs index 5118cb44e9..bac3b6f135 100644 --- a/src/Nncase.Passes/Rules/ShapeBucket/MergeCallToFusion.cs +++ b/src/Nncase.Passes/Rules/ShapeBucket/MergeCallToFusion.cs @@ -7,6 +7,7 @@ using System.Xml; using NetFabric.Hyperlinq; using Nncase.IR; +using Nncase.IR.Math; using Nncase.IR.Tensors; using Nncase.PatternMatch; using static Nncase.Passes.Rules.ShapeBucket.ShapeBucketHelper; @@ -35,11 +36,6 @@ public static bool AllConst(Call originCall) return false; } - - public bool ValidTarget(Expr target) - { - return CallValidator.ValidTarget(target); - } } [RuleGenerator] @@ -106,6 +102,17 @@ public partial class MergePrevMarkerToFusion : MergeFusionBase [RuleGenerator] public partial class MergeNextCallToFusion : MergeFusionBase { + private readonly bool _greedy = true; + + public MergeNextCallToFusion(bool greedy = true) + { + _greedy = greedy; + } + + public MergeNextCallToFusion() + { + } + public Pattern FusionCall => IsCall( "fusionOuterCall", IsFusion( @@ -127,13 +134,13 @@ public partial class MergeNextCallToFusion : MergeFusionBase // nextCall(marker(fusion(x))) -> fusion(nextCall(marker(x))) public Expr? GetReplace(Call nextCall, Expr maybeFusionCallMarker, Expr target, Call fusionOuterCall, BucketFusion fusion) { - var singleVar = CompileSession.CompileOptions.ShapeBucketOptions.VarMap.Values.SelectMany(x => x).OfType().ToHashSet().Count <= 1; + var singleVar = SingleDimVar(CompileSession.CompileOptions.ShapeBucketOptions); if (!singleVar && nextCall.Arguments.ToArray().OfType().Count() > 1) { return null; } - if (!ValidTarget(target)) + if (!CallValidator.ValidTarget(nextCall, _greedy)) { return null; } @@ -237,8 +244,25 @@ private bool SameEffectVar(Call originCall, Fusion fusion) [RuleGenerator] public partial class MergePrevCallToFusion : MergeFusionBase { + // 输入必须匹配marker,因为即便合并marker也是要在外面保留一份副本 + // fusion(marker(prevCall()) { var } -> fusion(var) { marker(prevCall()) } + // fusion((prevCall()) { var } -> fusion(var) { prevCall() } + private readonly bool _greedy = true; + + private readonly bool _mergeFusion; + private string _prevCallStr = string.Empty; + public MergePrevCallToFusion() + { + } + + public MergePrevCallToFusion(bool greedy = true, bool mergeFusion = false) + { + _greedy = greedy; + _mergeFusion = mergeFusion; + } + public override Pattern Pattern => IsCall( "fusionOuterCall", IsFusion( @@ -257,10 +281,6 @@ public Pattern MaybeMarker(string exprName, Pattern exprPatten) => IsAlt( IsRangeOfMarker(exprPatten, IsWildcard()), exprPatten); - // 输入必须匹配marker,因为即便合并marker也是要在外面保留一份副本 - // fusion(marker(prevCall()) { var } -> fusion(var) { marker(prevCall()) } - // fusion((prevCall()) { var } -> fusion(var) { prevCall() } - // dfs // xx | marker(xx)不行, 会先匹配到xx // xx(marker) | xx 可以 @@ -600,7 +620,7 @@ private bool IsInvalid(Call lhsPrevCall, Expr lhsTarget) return true; } - if (!ValidTarget(lhsTarget)) + if (!CallValidator.ValidTarget(lhsPrevCall, _greedy)) { return true; } diff --git a/src/Nncase.Passes/Rules/ShapeBucket/RecordFusionShape.cs b/src/Nncase.Passes/Rules/ShapeBucket/RecordFusionShape.cs index 110e37026a..94f7977f2f 100644 --- a/src/Nncase.Passes/Rules/ShapeBucket/RecordFusionShape.cs +++ b/src/Nncase.Passes/Rules/ShapeBucket/RecordFusionShape.cs @@ -12,10 +12,22 @@ using Nncase.Evaluator; using Nncase.IR; using static Nncase.IR.F.Tensors; +using static Nncase.Passes.Rules.ShapeBucket.ShapeBucketHelper; namespace Nncase.Passes.Rules.ShapeBucket; -public record FusionShapeData(IValue Outshape, IValue[] InputShapes); +public class FusionShapeData +{ + public FusionShapeData(IValue outshape, IValue[] inputShapes) + { + Outshape = outshape; + InputShapes = inputShapes; + } + + public IValue Outshape { get; } + + public IValue[] InputShapes { get; } +} public class FusionShapeUpdater : ExprVisitor { @@ -26,7 +38,7 @@ public FusionShapeUpdater(Dictionary memo) _memo = memo; } - public Dictionary FusionShape { get; set; } = new(); + public Dictionary FusionShape { get; } = new(); protected override Expr DefaultVisitLeaf(Expr expr) => expr; @@ -34,7 +46,11 @@ protected override Expr VisitLeafCall(Call expr) { if (expr.Target is BucketFusion f) { - var argShape = expr.Arguments.ToArray().Select(arg => GetShape(_memo[arg])).ToArray(); + var argShape = expr.Arguments.ToArray().Select(arg => + { + var exp = arg is Marker m ? m.Target : arg; + return GetShape(_memo[exp]); + }).ToArray(); var shape = GetShape(_memo[expr]); FusionShape[f] = new FusionShapeData(shape, argShape); } @@ -54,25 +70,6 @@ private IValue GetShape(IValue value) } } -public class SimpleTimer : IDisposable -{ - private readonly DateTime _startTime; - private readonly string _name; - - public SimpleTimer(string name) - { - _startTime = System.DateTime.Now; - _name = name; - } - - public void Dispose() - { - var endTime = System.DateTime.Now; - var time = endTime - _startTime; - Console.WriteLine($"{_name} tooks {time.Seconds}"); - } -} - public class RecordFusionShape : FunctionPass { private Dictionary _dimVarValues = new(); @@ -84,11 +81,32 @@ public RecordFusionShape(Dictionary shapeList) public Dictionary FusionShapeInfo { get; set; } + // make dummy value from InputInfo + // VarInfo:(DimVar -> Value) + public static Dictionary + MakeDummyInput(IReadOnlyDictionary info, Dictionary varInfo) + { + return info.ToDictionary( + pair => pair.Key, + pair => + { + // todo: dummy input可能会有问题... + var shapeExpr = pair.Key.CheckedShape.IsScalar + ? (Expr)Array.Empty() + : Stack(new IR.Tuple(pair.Value.Select(x => Cast(x, DataTypes.Int64)).ToArray()), 0); + + var shape = shapeExpr.Evaluate(varInfo).AsTensor(); + return ConstantOfShape( + shape, + Cast(1, pair.Key.CheckedDataType)).Evaluate(varInfo); + }); + } + protected override Task RunCoreAsync(BaseFunction main, RunPassContext context) { var options = CompileSession.CompileOptions.ShapeBucketOptions; var varMap = options.VarMap; - _dimVarValues = ShapeBucketHelper.MakeVarValuesForAllSegment(options); + _dimVarValues = MakeVarValuesForAllSegment(options); // 一共有多组key seg var list = Enumerable.Range(0, _dimVarValues.First().Value.Length).Select(i => @@ -96,13 +114,14 @@ protected override Task RunCoreAsync(BaseFunction main, RunPassCon // 一组里面多个key seg return _dimVarValues.Select(pair => (pair.Key, Value: pair.Value[i])).ToArray(); }).ToArray(); + + var body = ((Function)main).Body; var tmpFusionShapeList = list.Select((seg, i) => { var varValues = seg.ToDictionary(pair => pair.Key, pair => (IValue)Value.FromTensor(pair.Value)); var exprValues = seg.ToDictionary(pair => (Expr)pair.Key, pair => (IValue)Value.FromTensor(pair.Value)); var input = MakeDummyInput(varMap, varValues); - var body = ((Function)main).Body; - var memo = EvaluatorUtil.GetMemo(body, input); + var memo = EvaluatorUtil.GetMemo(body, ConcatDictionary(input, varValues)); var f = new FusionShapeUpdater(ConcatDictionary(memo, exprValues)); f.Visit(main); return f.FusionShape; @@ -110,6 +129,7 @@ protected override Task RunCoreAsync(BaseFunction main, RunPassCon .ToLookup(x => x.Key, x => x.Value) .ToDictionary(pair => pair.Key, pair => pair.ToArray()); + GC.Collect(); foreach (var (f, shapeInfo) in tmpFusionShapeList) { FusionShapeInfo[f] = shapeInfo; @@ -117,35 +137,4 @@ protected override Task RunCoreAsync(BaseFunction main, RunPassCon return Task.FromResult(main); } - - private static Dictionary ConcatDictionary(Dictionary memo, Dictionary exprValues) - { - foreach (var (key, value) in exprValues) - { - memo[key] = value; - } - - return memo; - } - - // make dummy value from InputInfo - // VarInfo:(DimVar -> Value) - private static Dictionary - MakeDummyInput(IReadOnlyDictionary info, Dictionary varInfo) - { - return info.ToDictionary( - pair => pair.Key, - pair => - { - // todo: dummy input可能会有问题... - var shapeExpr = pair.Key.CheckedShape.IsScalar - ? (Expr)Array.Empty() - : Stack(new IR.Tuple(pair.Value.Select(x => Cast(x, DataTypes.Int32)).ToArray()), 0); - - var shape = shapeExpr.Evaluate(varInfo).AsTensor(); - return ConstantOfShape( - shape, - Cast(1, pair.Key.CheckedDataType)).Evaluate(varInfo); - }); - } } diff --git a/src/Nncase.Passes/Rules/ShapeBucket/ShapeBucket.cs b/src/Nncase.Passes/Rules/ShapeBucket/ShapeBucket.cs index 197a5e0e8b..2eb9c0f39a 100644 --- a/src/Nncase.Passes/Rules/ShapeBucket/ShapeBucket.cs +++ b/src/Nncase.Passes/Rules/ShapeBucket/ShapeBucket.cs @@ -13,14 +13,17 @@ using System.Transactions; using DryIoc; using DryIoc.ImTools; +using GiGraph.Dot.Types.Geometry; using Microsoft.Extensions.DependencyInjection; using Microsoft.Toolkit.HighPerformance; using NetFabric.Hyperlinq; +using Nncase.CodeGen; using Nncase.Diagnostics; using Nncase.Evaluator; using Nncase.IR; using Nncase.IR.Math; using Nncase.IR.NN; +using Nncase.IR.ShapeExpr; using Nncase.IR.Tensors; using Nncase.Passes.Analysis; using Nncase.Passes.Rules.Lower; @@ -35,6 +38,7 @@ using static Nncase.PatternMatch.F.Tensors; using static Nncase.PatternMatch.Utility; using static Nncase.Utilities.ReplaceUtility; +using BaseFunction = Nncase.IR.BaseFunction; using Dimension = Nncase.IR.Dimension; using FoldConstCall = Nncase.Passes.Mutators.FoldConstCall; using Stack = Nncase.IR.Tensors.Stack; @@ -74,25 +78,6 @@ public BucketFusion(string moduleKind, Var[] effectVar, Expr body, params Var[] public Var[] EffectVar { get; set; } - public bool IsSimple - { - get - { - // todo: change list - var names = Name.Split("_"); - var list = new[] { "MatMul", "Conv2D", "Conv2DTranspose", "Transpose" }; - foreach (string name in names) - { - if (list.Contains(name)) - { - return false; - } - } - - return true; - } - } - public static BucketFusion FromNormalFusion(Fusion f, Var[] effectVars) { return new BucketFusion(f.Name, "stackvm", f.Body, f.Parameters.ToArray(), effectVars); @@ -139,8 +124,6 @@ public CallToFusion() public override Pattern Pattern => throw new InvalidOperationException(); - protected virtual bool MustHaveMarker => true; - private Call? CurrentCall { get; set; } private string Name => CurrentCall!.Target.GetType().Name; @@ -173,9 +156,6 @@ public virtual bool Check(Call call) Console.WriteLine(call.Target.GetType().Name); var argsMarkerData = CollectInputs(call); var args = argsMarkerData.Select(pair => pair.Item1).ToArray(); - - // var argsMarker = argsMarkerData.Select(pair => pair.Item1).ToArray(); - // var args = argsMarker.Select(arg => arg.Target).ToArray(); var varMap = CompileSession.CompileOptions.ShapeBucketOptions.VarMap; var set = MakeEffectVarArray(CompileSession, varMap, args); var fusionVars = MakeNewParam(args); @@ -351,9 +331,12 @@ protected override void Init(IMatchResult result) public class MultiUserCallToFusion : CallToFusion { - public MultiUserCallToFusion(bool onlyDynamic = false) + private readonly bool _greedy = true; + + public MultiUserCallToFusion(bool onlyDynamic = false, bool greedy = true) : base(onlyDynamic) { + _greedy = greedy; } public MultiUserCallToFusion() @@ -364,27 +347,7 @@ public MultiUserCallToFusion() { if (expr is Call c && c.Target is not BucketFusion) { - if (c.Target is Binary) - { - if (c.Arguments[0] is not Const && c.Arguments[1] is not Const) - { - return false; - } - - return true; - } - - if (c.Target is IR.Tensors.Reshape) - { - if (c.Arguments[IR.Tensors.Reshape.Shape.Index] is TensorConst) - { - return CallValidator.ValidTarget(c.Target); - } - } - else - { - return CallValidator.ValidTarget(c.Target); - } + return CallValidator.ValidTarget(c, _greedy); } return false; @@ -536,8 +499,29 @@ public TransposeToFusion(bool isDynamic = false) : base(isDynamic) { } +} - protected override bool MustHaveMarker => false; +public class ReshapeToFusion : CallToFusion +{ + public ReshapeToFusion(bool isDynamic = false) + : base(isDynamic) + { + } + + public override Pattern Pattern => IsCallWildcard("call", IsOp()); + + protected override (Expr, int)[] CollectInputs(Call call) + { + var input = call.Arguments[IR.Tensors.Reshape.Input.Index]; + var inputPair = (input, IR.Tensors.Reshape.Input.Index); + var padPair = (call.Arguments[IR.Tensors.Reshape.Shape.Index], IR.Tensors.Reshape.Shape.Index); + if (padPair.Item1 is TensorConst) + { + return new[] { inputPair }; + } + + return new[] { inputPair, padPair }; + } } public class UnaryToFusion : MarkerCallToFusion @@ -560,7 +544,7 @@ public BinaryToFusion(bool isDynamic = false) { } - // public override bool Check(Call call) => call.CheckedShape.Rank > 1; + public override bool Check(Call call) => call.CheckedShape.Rank > 1; } [RuleGenerator] @@ -621,20 +605,23 @@ public partial class ClearFusionOuterMarker : RewriteRule public class FusionBucketContext { - public FusionBucketContext(Call outerCall, BucketFusion fusion, Dictionary varMap, Dictionary dimVarValues, ShapeExprCache cache) + private readonly int _index; + + public FusionBucketContext(Call outerCall, BucketFusion fusion, ShapeBucketOptions options, ShapeExprCache cache, int index, FusionShapeData[] shapeInfos) { OuterCall = outerCall; Fusion = fusion; - VarMap = varMap; + VarMap = options.VarMap; Cache = cache; - Cache.VarMap = varMap; - FusionInputShapeExpr = MakeFusionInputShapeExpr(outerCall, fusion, cache); - CheckAlive(FusionInputShapeExpr); - DimVarValues = dimVarValues; + Cache.VarMap = options.VarMap; + FusionInputShapeExpr = new(); + DimVarValues = MakeVarValuesForAllSegment(options); + Arguments = OuterCall.Arguments.ToArray(); Parameters = Fusion.Parameters.ToArray(); FixedShapeCache = new(); - SliceShape = ComputeSliceShape(); + SliceShape = ComputeSliceShape(shapeInfos); + _index = index; } public Expr SliceShape { get; } @@ -680,7 +667,6 @@ private static Dictionary MakeFusionInputShapeExpr(Call call, Bucke { var data = fusion.Parameters.ToArray().Zip(call.Arguments.ToArray().Select((arg, i) => { - // DumpIR(arg, "MakeFusionInputShapeExprArg"); var result = arg.EvaluateShapeExpr(cache); if (!result.InferenceType()) { @@ -698,31 +684,138 @@ private static Dictionary MakeFusionInputShapeExpr(Call call, Bucke return fusionInputData; } - private static void CheckAlive(Dictionary fusionInputInfo) + private static Expr ReplaceShapeOf(Dictionary fusionInputsShapeExpr, Dictionary varMap, Expr originShape, Var[] parameters, Var[] dimVarKeys, FusionBucketContext context, Dictionary dict) { - foreach (var value in fusionInputInfo.Values) + // return originShape; + // 拷贝shape表达式,以免被原始的计算引用 + var cloneShape = originShape.Clone(); + CompilerServices.Rewrite(cloneShape, new[] { new RemoveMarker() }, new()); + var f = new FindVar(); + f.Visit(cloneShape); + var newVars = f.Vars; + + // 可能在VarMap里面有,但是newVar中没有,所以把newVar转换为oldVar + var newDict = fusionInputsShapeExpr + .Concat(varMap) + .Where(pair => newVars.FindFirst(newVar => newVar.Name == pair.Key.Name) != null) + .ToDictionary( + pair => + { + var k = newVars.FindFirst(newVar => newVar.Name == pair.Key.Name); + return k; + }, + pair => + { + var v = pair.Value; + return v; + }) + .ToDictionary(x => x.Key, x => x.Value); + + var originVars = parameters + .ToArray() + .Concat(varMap.Keys) + .Concat(dimVarKeys) + .ToDictionary(v => v.Name, v => v); + + Task.Run(() => new FoldNopTuple().RunAsync(new Function(cloneShape), new())).Wait(); + Expr sliceShape = cloneShape; + var p = new ReplaceOfCollector(); + p.Visit(cloneShape); + var processList = p.List; + processList.Reverse(); + + var argCache = context.Arguments.ToDictionary(arg => arg, arg => (Expr)ShapeOf(arg)); + var exprs = argCache.SelectMany(pair => new[] { pair.Key, pair.Value }).ToArray(); + var pinner = new ExprPinner(exprs); + var cache = new ShapeExprCache(newDict, argCache); + + foreach (var call in processList) + { + var newShapeOf = call.Arguments[0].EvaluateShapeExpr(cache); + ReplaceUtility.ReplaceAllUsesWith(call, newShapeOf); + } + + foreach (var (key, value) in dict) { - foreach (var expr in value) + var mutator = new Passes.Mutators.Substitutor(e => { - if (!expr.IsAlive) + if (e is Var v1 && v1.Name == value.Name) { - throw new NotImplementedException(); + return key; } - } + + return null; + }); + mutator.Visit(sliceShape, Unit.Default); } + + newVars.ToArray().ForEach(newVar => + { + if (originVars.TryGetValue(newVar.Name, out var originVar)) + { + ReplaceExpr(sliceShape, newVar, originVar); + } + }); + + var body = sliceShape; + var simplifySliceShape = SimplifyShape(body); + return simplifySliceShape; } - private Expr ComputeSliceShape() + private static Expr SimplifyShape(Expr body) => + CompilerServices.Rewrite( + body, + new IRewriteRule[] + { + new FoldStackGetItem(), new FoldShapeOf(), new FoldTwoReshapes(), new FoldTwoCasts(), + new FoldTwoSlices(), new FoldNopBinary(), new FoldNopCast(), new Neutral.FoldConstCall(), + new FoldNopReshape(), new FoldNopSlice(), new FoldIf(), new FoldBroadcastShape(), new FoldSplitShapeOf(), + }, + new()); + + private Expr ComputeSliceShape(FusionShapeData[] shapeInfos) { var originBody = FusionBody; var shapeOfFusionInput = MakeShapeOfFusionInput(Parameters, Arguments); var originShape = originBody.EvaluateShapeExpr(shapeOfFusionInput); originShape.InferenceType(); - return originShape; + // complex check + // 判断是否需要replace,里面是否存在满足条件的shapeof + var args = Arguments.ToDictionary(x => x, x => new Var(x.CheckedType)); + var input = MakeShapeOfFusionInput(Parameters, args.Values.ToArray()); + var varShape = originBody.EvaluateShapeExpr(input); + var p = new ReplaceOfCollector(); + p.Visit(originBody); + if (p.List.Count == 0) + { + return SimplifyShape(originShape); + } + + return ReplaceShapeOf(shapeOfFusionInput, VarMap, varShape, Parameters, DimVarValues.Keys.ToArray(), this, args); } } +public class ReplaceOfCollector : ExprVisitor +{ + public List List { get; } = new(); + + protected override Expr VisitLeafCall(Call expr) + { + var input = expr.Arguments[0]; + + // input is marker or call + if (expr.Target is ShapeOf && input.CheckedShape.Rank > 2 && input is not Var) + { + List.Add(expr); + } + + return expr; + } + + protected override Expr DefaultVisitLeaf(Expr expr) => expr; +} + [RuleGenerator] public partial class FusionBucket : RewriteRule { @@ -748,17 +841,18 @@ public FusionBucket(Dictionary list) GenerateParameters(null)), GenerateParameters(null)); - internal Dictionary VarMap => CompileSession.CompileOptions.ShapeBucketOptions.VarMap; - public static Expr PreProcess(FusionBucketContext context, Var param, Dictionary inputInfo, Dictionary varValues, Dictionary fusionInputData, int segIndex, int inputIndex) { // Console.WriteLine($"seg index{segIndex}"); if (context.FixedShapeCache.TryGetValue(segIndex, out var cachedFixedShape)) { - // var cachedShape = cachedFixedShape[inputIndex]; - // Console.WriteLine(string.Join(",", cachedShape)); - // Console.WriteLine("Cache ok"); - return new Call(new BucketPad(), param, cachedFixedShape[inputIndex]); + var shape = cachedFixedShape[inputIndex]; + if ((param.CheckedShape.IsFixed && shape.SequenceEqual(param.CheckedShape.ToValueArray())) || param.CheckedShape.IsScalar) + { + return param; + } + + return new Call(new BucketPad(), param, shape); } throw new InvalidDataException("Shape Cache not found"); @@ -780,7 +874,38 @@ public static (Dictionary MinDict, Dictionary MaxDict) return (minDict, maxDict); } - public static Expr MakeSplitEntry(FusionBucketContext context, Dictionary varInfo, int segIndex) + public static Expr Split(FusionBucketContext context) + { + var failure = MakeFailure(context.FusionBody); + + // todo: test this + var value = GetVarValue(context); + + int i = 0; + + // todo: only used for same range + var body = context.DimVarValues.First().Value.OrderByDescending(x => x).Aggregate( + failure, + (sum, seg) => + { + // 根据var,也就是target为这个fusion的call的参数来进行判断落在哪个段 + var cond = value <= (long)seg; + var sameCond = IR.F.Math.Equal(value, (long)seg); + + // select var value for current segment + var varInfo = context.DimVarValue(i); + var thenBody = MakeSplitEntry(context, varInfo, i, sameCond); + var elseBody = sum; + i++; + + var result = new If(cond, thenBody, elseBody); + return result; + }); + + return body; + } + + public static Expr MakeSplitEntry(FusionBucketContext context, Dictionary varInfo, int segIndex, Expr sameCond, bool sameOpt = false) { var originBody = context.FusionBody; var fusionVars = context.Parameters; @@ -791,7 +916,6 @@ public static Expr MakeSplitEntry(FusionBucketContext context, Dictionary fusion原始的var -> target为fusion的call的input // 本质上只是对这个body的所有输入做替换 // 避免这里的修改影响到原始的body,每个分支需要进行自己的修改,所以要clone处理 - // DumpIR(originBody, "originBody", _relPath); var call = ReplaceClone(originBody, fusionVars.Zip(fixInputs).ToArray()); if (!call.InferenceType()) { @@ -800,8 +924,26 @@ public static Expr MakeSplitEntry(FusionBucketContext context, Dictionary pair.Value.Any(x => x is Var)).Select(pair => + { + var (v, dims) = pair; + var i = dims.IndexOf(x => x is Var); + return ShapeOf(v)[i]; + }).ToArray(); + + if (varList.Length > 1) + { + return varList.Aggregate((sum, x) => IR.F.Math.Max(sum, x)); + } + + return varList.First(); } public Expr? GetReplace(Call outerCall, BucketFusion fusion, Expr fusionBody) @@ -811,24 +953,11 @@ public static Expr MakeSplitEntry(FusionBucketContext context, Dictionary(); if (!FusionShapeInfo.TryGetValue(fusion, out shapeInfos)) { @@ -842,6 +971,9 @@ public static Expr MakeSplitEntry(FusionBucketContext context, Dictionary x.InputShapes.Select(iShape => iShape.AsTensor().ToArray().ToArray()).ToArray()).ToArray(); @@ -853,6 +985,7 @@ public static Expr MakeSplitEntry(FusionBucketContext context, Dictionary 1"); } - var info = ComputeSegmentInfo(counts, options); - var body = Split(context, info); + // 1. 普通情况不应该rebuild + // 2. rebuild的正确性 + if (ShouldBeRebuild(context)) + { + _counter++; + Console.WriteLine("Rebuild"); + var rebuild = RestoreBodyWithArgs(context.Arguments, context.Parameters, context.FusionBody); + DumpIR(rebuild, "Rebuild", _relPath); + return rebuild; + } + + var body = Split(context); body.InferenceType(); - if (body.Users.Count > 1 || body.CheckedType is InvalidType) + if (body.CheckedType is InvalidType) { + DumpIR(body, "InvalidBody"); throw new InvalidOperationException(); } - if (body is not If) + if (body.Users.Count > 1) { - _counter++; - DumpIR(body, "Rebuild", _relPath); - return body; + throw new InvalidOperationException(); } - // DumpIR(body, "newBodyBeforeReplace", _relPath); // FixInput Replace Var var newBody = ReplaceFusionVarWithCallArgs(fusion, context.Arguments, body); @@ -938,19 +1079,19 @@ private static void PrintShapeInfos(FusionShapeData[] shapeInfos) private static Expr MakeSlice(FusionBucketContext context, Expr call, Expr originBody) { + var sliceShape = context.SliceShape; if (call.CheckedType is TupleType tuple) { var fields = Enumerable.Range(0, tuple.Count) - .Select(i => MakeSliceForTensor(originBody[i], call[i], context)).ToArray(); + .Select(i => MakeSliceForTensor(sliceShape[i], call[i], context)).ToArray(); return new IR.Tuple(fields); } - return MakeSliceForTensor(originBody, call, context); + return MakeSliceForTensor(sliceShape, call, context); } - private static Expr MakeSliceForTensor(Expr originBody, Expr call, FusionBucketContext context) + private static Expr MakeSliceForTensor(Expr sliceShape, Expr call, FusionBucketContext context) { - var sliceShape = context.SliceShape; var rank = call.CheckedShape.Rank; var simplifyCall = CompilerServices.Rewrite( call, @@ -967,10 +1108,13 @@ private static Expr MakeSliceForTensor(Expr originBody, Expr call, FusionBucketC new FoldNopReshape(), new FoldNopSlice(), new FoldIf(), + new FoldBroadcastShape(), }, new()); - var body = (Expr)Slice(simplifyCall, Enumerable.Repeat(0, rank).ToArray(), Cast(sliceShape, DataTypes.Int32), rank); + var axes = Tensor.From(Enumerable.Range(0, rank).Select(x => (long)x).ToArray()); + var strides = Tensor.FromScalar(1L, rank); + var body = (Expr)Slice(simplifyCall, Enumerable.Repeat(0L, rank).ToArray(), Cast(sliceShape, DataTypes.Int64), axes, strides); return body; } @@ -980,11 +1124,26 @@ private static bool IsFixed(int totalCount, int[][] minFixedShapeList, int[][] m private static bool ShouldRestore(Call outerCall, BucketFusion fusion) { - return fusion.IsSimple || - outerCall.CheckedType is TupleType || - outerCall.CheckedShape.Rank == 0 || - outerCall.Arguments.ToArray().Any(arg => - arg.CheckedType is TupleType); + if (CallValidator.IsSimple(fusion)) + { + return true; + } + + if (outerCall.CheckedType is TupleType tt) + { + if (tt.Fields.All(f => f is TensorType t && t.Shape.Rank < 2)) + { + return true; + } + } + + if (outerCall.Arguments.ToArray().Any(arg => + arg.CheckedType is TupleType)) + { + return true; + } + + return false; } private static Expr RestoreBodyWithArgs(Expr[] args, Var[] parameters, Expr body) => @@ -1055,72 +1214,141 @@ private static Expr ReplaceFusionVarWithCallArgs(BucketFusion fusion, Expr[] arg return result; }); - private static Expr Split(FusionBucketContext context, SegmentInfo info) + private static Expr MakeFailure(Expr fusionBody) { - var fusionInputs = context.Arguments; - var (inputIndex, dimIndex, segments) = info; - var dim = ShapeOf(fusionInputs[inputIndex])[dimIndex]; - var failure = MakeFailure(context.FusionBody); - - int i = 0; - - // 1. 普通情况不应该rebuild - // 2. rebuild的正确性 - // if (ShouldBeRebuild(context)) - // { - // Console.WriteLine("Rebuild"); - // return RestoreBodyWithArgs(context.Arguments, context.Parameters, context.FusionBody); - // } - var body = segments.OrderByDescending(x => x).Aggregate( - failure, - (sum, seg) => - { - // 根据var,也就是target为这个fusion的call的参数来进行判断落在哪个段 - var cond = dim <= (long)seg; - - // select var value for current segment - var varInfo = context.DimVarValue(i); - var thenBody = MakeSplitEntry(context, varInfo, i); - var elseBody = sum; - i++; - - var result = new If(cond, thenBody, elseBody); - return result; - }); - - return body; + var failure = fusionBody.CheckedType switch + { + TupleType tuple => new IR.Tuple(tuple.Fields.ToArray() + .Select(x => + { + return ConstantOfShape(new[] { 1 }, Cast(0, ((TensorType)x).DType)); + }).ToArray()), + TensorType tensorType => (Expr)ConstantOfShape(new[] { 1 }, Cast(0, tensorType.DType)), + _ => throw new ArgumentOutOfRangeException("fusionBody"), + }; + return IR.F.Math.Require(false, failure, "input dim large than limit"); } private static bool ShouldBeRebuild(FusionBucketContext context) { var varInfo = context.DimVarValue(0); - var entry = MakeSplitEntry(context, varInfo, 0); + var entry = MakeSplitEntry(context, varInfo, 0, false, false); return entry switch { IR.Tuple tuple => tuple.Fields.ToArray().Any(ShouldBeRebuild), Call => ShouldBeRebuild(entry), - _ => throw new ArgumentOutOfRangeException("context"), + _ => DumpError(entry), }; } - private static bool ShouldBeRebuild(Expr entry) => entry is Call { Target: IR.Tensors.Slice } c && - (!c.Arguments[IR.Tensors.Slice.Input.Index].CheckedShape - .IsFixed); + private static bool DumpError(Expr entry) + { + DumpIR(entry, "FailedEntry"); + throw new InvalidOperationException(); + } + + private static bool ShouldBeRebuild(Expr entry) + { + if (entry is Call { Target: IR.Tensors.Slice } c) + { + var body = c.Arguments[IR.Tensors.Slice.Input.Index]; + if (body.CheckedShape.IsFixed) + { + var visitor = new DynamicCheckVisitor(); + visitor.Visit(body); + return visitor.HasDynamic; + } + } - private static Expr MakeFailure(Expr fusionBody) + return true; + } + + public class DynamicCheckVisitor : ExprVisitor { - var failure = fusionBody.CheckedType switch + private bool _hasDynamic; + + public bool HasDynamic => _hasDynamic; + + protected override Expr DefaultVisitLeaf(Expr expr) => expr; + + protected override Expr VisitLeafCall(Call expr) { - TupleType tuple => new IR.Tuple(tuple.Fields.ToArray() - .Select(x => + if (CallValidator.ForceConvert.Contains(expr.Target.GetType().TypeHandle)) + { + if (!expr.CheckedShape.IsFixed) { - return ConstantOfShape(new[] { 1 }, Cast(0, ((TensorType)x).DType)); - }).ToArray()), - TensorType tensorType => (Expr)ConstantOfShape(new[] { 1 }, Cast(0, tensorType.DType)), - _ => throw new ArgumentOutOfRangeException("fusionBody"), - }; - return IR.F.Math.Require(false, failure, "input dim large than limit"); + _hasDynamic = true; + } + } + + return expr; + } } } internal record SegmentInfo(int InputIndex, int DimIndex, int[] Segments); + +public class FullBucket : FunctionPass +{ + protected override Task RunCoreAsync(BaseFunction input, RunPassContext ctx) + { + if (!SingleDimVar(CompileSession.CompileOptions.ShapeBucketOptions)) + { + throw new NotImplementedException("Not Implement multi DimVar for FullBucket"); + } + + var main = (Function)input; + var replaceItem = main.Parameters.ToArray().Select(param => (param, (Expr)new Var(param.CheckedType))).ToArray(); + var cloneMain = (Function)ReplaceClone(main, replaceItem); + var options = CompileSession.CompileOptions.ShapeBucketOptions; + var tmpFusion = new BucketFusion("stackvm", cloneMain.Body, cloneMain.Parameters, Array.Empty()); + var call = new Call(tmpFusion, main.Parameters.ToArray()); + var dimVarValues = MakeVarValuesForAllSegment(options); + var list = InputConfList(dimVarValues); + var shapeData = MakeShapeData(list, options); + + var context = new FusionBucketContext(call, tmpFusion, options, new ShapeExprCache(options.VarMap), 0, shapeData); + + var allFixedShapes = shapeData + .Select(x => + x.InputShapes.Select(iShape => iShape.AsTensor().ToArray().ToArray()).ToArray()).ToArray(); + for (int i = 0; i < shapeData.Length; i++) + { + for (int j = 0; j < allFixedShapes.Length; j++) + { + context.FixedShapeCache[j] = allFixedShapes[j]; + } + } + + var newBody = FusionBucket.Split(context); + foreach (var (oldVar, tmpVar) in replaceItem) + { + ReplaceExpr(newBody, tmpVar, oldVar); + } + + return Task.FromResult((BaseFunction)main.With(body: newBody)); + } + + private static FusionShapeData[] MakeShapeData((Var Key, int Value)[][] list, ShapeBucketOptions options) => + list.Select(seg => + { + var varValues = seg.ToDictionary(pair => pair.Key, pair => (IValue)Value.FromTensor(pair.Value)); + var inShape = options.VarMap.Select(pair => + { + var shapeExpr = pair.Key.CheckedShape.IsScalar + ? (Expr)Array.Empty() + : Stack(new IR.Tuple(pair.Value.Select(x => Cast(x, DataTypes.Int64)).ToArray()), 0); + + var shape = shapeExpr.Evaluate(varValues).AsTensor(); + return shape; + }).ToArray(); + return new FusionShapeData(Value.None, inShape.Select(Value.FromTensor).ToArray()); + }).ToArray(); + + private static (Var Key, int Value)[][] InputConfList(Dictionary dimVarValues) => + Enumerable.Range(0, dimVarValues.First().Value.Length).Select(i => + { + // 一组里面多个key seg + return dimVarValues.Select(pair => (pair.Key, Value: pair.Value[i])).ToArray(); + }).ToArray(); +} diff --git a/src/Nncase.Passes/Rules/ShapeBucket/ShapeBucketHelper.cs b/src/Nncase.Passes/Rules/ShapeBucket/ShapeBucketHelper.cs index 3d9cbd389e..0275771c3c 100644 --- a/src/Nncase.Passes/Rules/ShapeBucket/ShapeBucketHelper.cs +++ b/src/Nncase.Passes/Rules/ShapeBucket/ShapeBucketHelper.cs @@ -6,6 +6,7 @@ using System.Linq; using System.Reactive; using DryIoc.ImTools; +using Nncase.CodeGen; using Nncase.Diagnostics; using Nncase.IR; using Nncase.IR.Math; @@ -22,23 +23,18 @@ namespace Nncase.Passes.Rules.ShapeBucket; public static class CallValidator { - private static readonly HashSet ForceConvert = new() + public static readonly HashSet ForceConvert = new() { typeof(Conv2D).TypeHandle, + typeof(Conv2DTranspose).TypeHandle, typeof(MatMul).TypeHandle, - typeof(Unsqueeze).TypeHandle, - typeof(Squeeze).TypeHandle, - typeof(Cast).TypeHandle, - typeof(Unary).TypeHandle, typeof(Transpose).TypeHandle, typeof(Pad).TypeHandle, + typeof(Tile).TypeHandle, }; - // todo: add debug mode private static readonly HashSet MaybeDynamic = new() { - // typeof(SpaceToBatch).TypeHandle, - // typeof(BatchToSpace).TypeHandle, typeof(Concat).TypeHandle, typeof(Stack).TypeHandle, typeof(Binary).TypeHandle, @@ -46,7 +42,12 @@ public static class CallValidator typeof(Gather).TypeHandle, typeof(ShapeOf).TypeHandle, - // typeof(Reshape).TypeHandle, + typeof(Unsqueeze).TypeHandle, + typeof(Squeeze).TypeHandle, + typeof(Cast).TypeHandle, + typeof(Unary).TypeHandle, + + typeof(Reshape).TypeHandle, typeof(Expand).TypeHandle, typeof(ConstantOfShape).TypeHandle, typeof(Where).TypeHandle, @@ -60,22 +61,64 @@ public static class CallValidator public static bool IsMaybeDynamic(Expr target) => MaybeDynamic.Contains(target.GetType().TypeHandle); - public static bool IsForceConvert(Expr target) => ForceConvert.Contains(target.GetType().TypeHandle); + public static bool IsForceConvert(Expr target) => ForceConvert.Contains(target.GetType().TypeHandle) || target is ActivationOp; - public static bool ValidTarget(Expr target) + public static bool ValidTarget(Call call, bool greedy) { - if (target is ActivationOp) + var target = call.Target; + + var singleVar = + ShapeBucketHelper.SingleDimVar( + CompileSessionScope.GetCurrentThrowIfNull().CompileOptions.ShapeBucketOptions); + + if (target is Binary && call.Arguments.ToArray().OfType().Any()) { return true; } - if (IsMaybeDynamic(target) || IsForceConvert(target)) + if (IsForceConvert(target)) + { + return true; + } + + // dynamic reshape cause dynamic shape call + if (!greedy && IsDynamicReshape(call)) + { + return false; + } + + if (singleVar && greedy && IsMaybeDynamic(target)) { return true; } return false; } + + public static bool IsSimple(BucketFusion fusion) + { + var v = new OpCollector(); + v.Visit(fusion.Body); + foreach (var type in v.Counter.Keys) + { + if (CallValidator.ForceConvert.Contains(type)) + { + return false; + } + } + + foreach (var op in v.OpSet) + { + if (op is ActivationOp) + { + return false; + } + } + + return true; + } + + private static bool IsDynamicReshape(Call call) => call.Target is Reshape && call.Arguments[Reshape.Shape.Index] is not Const; } public static class ShapeBucketRegister @@ -91,16 +134,25 @@ public static void CheckShapeBucketOptions(ShapeBucketOptions options) } } - public static void MergeOp(IPassManager iPassManager) + public static bool HasNotBucketOp(Expr entry) + { + var counter = new OpCollector(); + counter.Visit(entry); + var invalid = new[] { typeof(Softmax), typeof(LayerNorm) }; + var canFullBucket = invalid.Any(x => counter.Counter.Keys.Contains(x.TypeHandle)); + return canFullBucket; + } + + public static void MergeOp(IPassManager iPassManager, bool greedy) { iPassManager.AddWithName("MergeNextCall").Configure(c => { - c.Add(); + c.Add(greedy); c.Add(); }); iPassManager.AddWithName("MergePrevCall").Configure(c => { - c.Add(); + c.Add(greedy); c.Add(); }); } @@ -108,6 +160,7 @@ public static void MergeOp(IPassManager iPassManager) public static void ToFusion(IPassManager p, bool onlyDynamic = false) => p.AddWithName("ToFusion").Configure(c => { + c.Add(); c.Add(onlyDynamic); c.Add(onlyDynamic); c.Add(onlyDynamic); @@ -124,21 +177,31 @@ public static void Bucket(IPassManager p) }); } - public static void Rebuild(IPassManager p) + public static void Rebuild(IPassManager p, bool singleVar) { // rebuild ToFusion(p, true); + MergeOp(p, false); + + // todo: lost to fusion + p.AddWithName("LostToFusion").Configure(p => + { + p.Add(true); + p.Add(true); + }); + + MergeFusion(p, singleVar, false); Bucket(p); } - public static void MergeFusion(IPassManager p, bool singleVar) + public static void MergeFusion(IPassManager p, bool singleVar, bool greedy) { if (!singleVar) { return; } - p.AddWithName("MergeBucketFusionPass"); + p.AddWithName("MergeBucketFusionPass", greedy); } public static void LostToFusion(IPassManager p, bool singleVar) => @@ -163,6 +226,7 @@ public static void ClearMarker(IPassManager p) => public static void Simplify(IPassManager p) => p.AddWithName("Simplify").Configure(c => { + c.Add(); c.Add(); c.Add(); c.Add(); @@ -174,19 +238,39 @@ public static void Simplify(IPassManager p) => c.Add(); c.Add(); c.Add(); + c.Add(); + c.Add(); + c.Add(); }); } public static class ShapeBucketHelper { + public static Dictionary ConcatDictionary(Dictionary memo, Dictionary exprValues) + where T : Expr + { + foreach (var (key, value) in exprValues) + { + memo[key] = value; + } + + return memo; + } + public static Dictionary MakeVarValuesForAllSegment(ShapeBucketOptions options) { int segmentCount = options.SegmentsCount; var varRange = options.RangeInfo; var varMap = options.VarMap; + var staticShape = false; var varAndInputAllSegment = varRange.ToDictionary(pair => pair.Key, pair => { var (min, max) = pair.Value; + if (staticShape) + { + return Enumerable.Range(min, max - min).ToArray(); + } + var segments = ComputeSegmentList(segmentCount, min, max); return segments; }); @@ -328,6 +412,31 @@ public static void DumpIR(Expr expr, string prefix, string? reletivePath = null, DumpScope.Current.DumpIR(expr, s, reletivePath); } } + + public static void CheckRepeat(Expr call) + { + // todo: 检查所有fusion里面的param有没有重复名字的 + // todo: 检查有没有fusion名字重复的 + var c = new CheckFusionCallVisitor(); + c.Visit(call); + c.Check(); + } + + public static void CheckErrorVar(Expr body, Var[] vars) + { + var f = new FindVar(); + f.Visit(body); + if (!f.Vars.All(vars.Contains)) + { + Console.WriteLine(string.Join(", ", f.Vars.Select(x => x.Name).ToArray())); + throw new InvalidOperationException("Has Invalid Var In Body"); + } + } + + public static bool SingleDimVar(ShapeBucketOptions options) + { + return options.VarMap.Values.SelectMany(x => x).OfType().ToHashSet().Count <= 1; + } } public class FindExpr : ExprVisitor @@ -380,7 +489,7 @@ protected override Expr DispatchVisit(Expr expr) public class FindVar : ExprVisitor { - public HashSet Vars { get; set; } = new(); + public HashSet Vars { get; } = new(); // todo: if visit call(VarFusion), then return EffectVar protected override Expr VisitLeafVar(Var expr) @@ -412,6 +521,34 @@ public sealed partial class ForceConvertOpChecker : RewriteRule } } +public class OpCollector : ExprVisitor +{ + public Dictionary Counter { get; } = new(); + + public HashSet OpSet { get; } = new(); + + protected override Expr VisitCall(Call expr) + { + if (expr.Target is Op op) + { + var handle = expr.Target.GetType().TypeHandle; + if (Counter.ContainsKey(handle)) + { + Counter[handle] += 1; + } + else + { + Counter[handle] = 1; + OpSet.Add(op); + } + } + + return base.VisitCall(expr); + } + + protected override Expr DefaultVisitLeaf(Expr expr) => expr; +} + internal static class ExprArrayExtension { public static IEnumerable OfNoConst(this IEnumerable args) @@ -433,25 +570,79 @@ public int GetHashCode(KeyValuePair obj) } } -internal class OpCounter : ExprVisitor +internal sealed class CheckFusionCallVisitor : ExprWalker { - private readonly Dictionary _counter = new(); + private readonly HashSet _callName = new(); + private readonly Dictionary _errorFusion = new(); - protected override Expr VisitCall(Call expr) + private readonly HashSet _fusionName = new(); + private readonly HashSet _repeatFusion = new(); + + private readonly HashSet _fusionParamsName = new(); + private readonly HashSet _repeatParamFusion = new(); + + public void Check() { - if (expr.Target is Op) + var error = false; + if (_errorFusion.Count != 0) { - var handle = expr.Target.GetType().TypeHandle; - if (_counter.ContainsKey(handle)) + error = true; + Console.WriteLine("errorFusion"); + } + + if (_repeatFusion.Count != 0) + { + error = true; + Print("repeatFusion not zero", _repeatFusion); + } + + if (_repeatParamFusion.Count != 0) + { + error = true; + Print("repeatParamFusion not zero", _repeatParamFusion); + } + + if (error) + { + throw new InvalidOperationException(); + } + } + + protected override Unit VisitLeafFusion(Fusion fusion) + { + // 可能有多个user啊,每次进来访问 + if (fusion is BucketFusion bf) + { + if (_fusionName.Contains(bf.Name)) { - _counter[handle] += 1; + _repeatFusion.Add(bf.Name); } else { - _counter[handle] = 1; + _fusionName.Add(bf.Name); } + + var parameters = bf.Parameters.ToArray(); + foreach (var parameter in parameters) + { + if (_fusionParamsName.Contains(parameter.Name)) + { + _repeatParamFusion.Add(parameter.Name); + } + } + + _fusionParamsName.UnionWith(parameters.Select(p => p.Name).ToArray()); } - return base.VisitCall(expr); + return default; + } + + private void Print(string name, HashSet list) + { + Console.WriteLine(name); + foreach (string s in list) + { + Console.WriteLine(s); + } } } diff --git a/src/Nncase.Passes/Rules/ShapeExpr/FoldBroadcastShape.cs b/src/Nncase.Passes/Rules/ShapeExpr/FoldBroadcastShape.cs new file mode 100644 index 0000000000..c45cf17931 --- /dev/null +++ b/src/Nncase.Passes/Rules/ShapeExpr/FoldBroadcastShape.cs @@ -0,0 +1,76 @@ +// Copyright (c) Canaan Inc. All rights reserved. +// Licensed under the Apache license. See LICENSE file in the project root for full license information. + +using System.Linq; +using Google.OrTools.Sat; +using Nncase.Evaluator; +using Nncase.IR; +using Nncase.IR.ShapeExpr; +using Nncase.PatternMatch; +using static Nncase.IR.TypePatternUtility; +using static Nncase.PatternMatch.F.ShapeExpr; +using static Nncase.PatternMatch.F.Tensors; +using static Nncase.PatternMatch.Utility; + +namespace Nncase.Passes.Rules.ShapeExpr; + +[RuleGenerator] +public partial class FoldBroadcastShapeConst : RewriteRule +{ + public override Pattern Pattern => IsCall(IsOp(), IsTuple("input")); + + private Expr? GetReplace(IR.Tuple input) + { + var constFields = input.Fields.ToArray().OfType().ToArray(); + if (constFields.Length == 0) + { + return null; + } + + if (constFields.Length == 1) + { + return null; + } + + var shape = IR.F.ShapeExpr.BroadcastShape(constFields.Select(x => (Expr)x.Value).ToArray()).Evaluate().AsTensor(); + var exprFields = input.Fields.ToArray().Where(x => x is not TensorConst).ToArray(); + + if (exprFields.Length == 0) + { + return shape; + } + + if ((shape.Shape.Count == 0 || (shape.Shape.Count == 1 && shape.Shape[0] == 1)) && exprFields.Length != 0) + { + return IR.F.ShapeExpr.BroadcastShape(exprFields); + } + + return IR.F.ShapeExpr.BroadcastShape(exprFields.Append(shape).ToArray()); + } +} + +[RuleGenerator] +public partial class FoldBroadcastShape : RewriteRule +{ + public override Pattern Pattern => IsCall(IsOp(), IsTuple("input")); + + private Expr? GetReplace(IR.Tuple input) + { + var broadcastShapeList = input.Fields.ToArray().Where(field => field is Call c && c.Target is BroadcastShape).ToArray(); + if (broadcastShapeList.Length > 0) + { + var newFields = input.Fields.ToArray().SelectMany(field => + { + if (field is Call { Target: BroadcastShape } c) + { + return ((Tuple)c.Arguments[0]).Fields.ToArray(); + } + + return new[] { field }; + }).ToArray(); + return IR.F.ShapeExpr.BroadcastShape(newFields); + } + + return null; + } +} diff --git a/src/Nncase.Passes/Rules/ShapeExpr/FoldGetItemShapeOf.cs b/src/Nncase.Passes/Rules/ShapeExpr/FoldGetItemShapeOf.cs new file mode 100644 index 0000000000..e8e6072a78 --- /dev/null +++ b/src/Nncase.Passes/Rules/ShapeExpr/FoldGetItemShapeOf.cs @@ -0,0 +1,41 @@ +// Copyright (c) Canaan Inc. All rights reserved. +// Licensed under the Apache license. See LICENSE file in the project root for full license information. + +using System; +using System.Linq; +using Nncase.IR; +using Nncase.PatternMatch; +using static Nncase.PatternMatch.F.Tensors; +using static Nncase.PatternMatch.Utility; +using GetItem = Nncase.IR.Tensors.GetItem; + +namespace Nncase.Passes.Rules.ShapeExpr +{ + [RuleGenerator] + public partial class FoldGetItemShapeOf : RewriteRule + { + public override Pattern Pattern => IsGetItem(null, "getItem", IsAlt(CastPattern, ShapeOfPattern), IsTensorConst("index")); + + public Pattern CastPattern => IsCast("cast", _ => true, ShapeOfPattern); + + public Pattern ShapeOfPattern => IsShapeOf(IsWildcard("input")); + + private Expr? GetReplace(Expr input, Tensor index, Call getItem) + { + DataType dt = DataTypes.Int64; + + if (getItem.Arguments[GetItem.Input.Index] is Call c && c.Target is IR.Tensors.Cast cast) + { + dt = cast.NewType; + } + + if (index.Shape.IsScalar) + { + var dim = input.CheckedShape[index.ToScalar()]; + return dim.IsFixed ? IR.F.Tensors.Cast(dim.FixedValue, dt) : null; + } + + return input; + } + } +} diff --git a/src/Nncase.Passes/Rules/ShapeExpr/FoldSplitShapeOf.cs b/src/Nncase.Passes/Rules/ShapeExpr/FoldSplitShapeOf.cs new file mode 100644 index 0000000000..737e371356 --- /dev/null +++ b/src/Nncase.Passes/Rules/ShapeExpr/FoldSplitShapeOf.cs @@ -0,0 +1,57 @@ +// Copyright (c) Canaan Inc. All rights reserved. +// Licensed under the Apache license. See LICENSE file in the project root for full license information. + +using System; +using System.Linq; +using Nncase.IR; +using Nncase.IR.Tensors; +using Nncase.PatternMatch; +using static Nncase.PatternMatch.F.Tensors; +using static Nncase.PatternMatch.Utility; +using GetItem = Nncase.IR.Tensors.GetItem; + +namespace Nncase.Passes.Rules.ShapeExpr; + +// shape = ShapeOf(input) +// Stack(cast(shape[0]), cast(shape[1])) -> shape +[RuleGenerator] +public partial class FoldSplitShapeOf : RewriteRule +{ + public override Pattern Pattern => IsStack( + null, + "stack", + IsTuple( + "tuple", + new VArgsPattern( + list => + Enumerable.Range(0, list.Length) + .Select(_ => IsGetItem(InputPattern, IsTensorConst())) + .ToArray(), + "args")), + IsTensorConst(tensor => tensor.Value.ToScalar() == 0)); + + public Pattern InputPattern => IsShapeOf(IsWildcard()); + + private Expr? GetReplace(IR.Tuple tuple) + { + var getItemList = tuple.Fields.ToArray().OfType().ToArray(); + var getItemIndices = getItemList.Select(x => x.Arguments[GetItem.Index.Index]).OfType().Select(x => x.Value.ToScalar()).ToArray(); + if (getItemIndices.Length == 0) + { + return null; + } + + var shapeOf = getItemList[0].Arguments[GetItem.Input.Index]; + if (!shapeOf.CheckedShape[0].IsFixed) + { + return null; + } + + if (getItemIndices.SequenceEqual(Enumerable.Range(0, shapeOf.CheckedShape[0].FixedValue))) + { + return shapeOf; + } + + return null; + } +} diff --git a/src/Nncase.Passes/Rules/ShapeExpr/GatherToGetItem.cs b/src/Nncase.Passes/Rules/ShapeExpr/GatherToGetItem.cs new file mode 100644 index 0000000000..2a1453f3c9 --- /dev/null +++ b/src/Nncase.Passes/Rules/ShapeExpr/GatherToGetItem.cs @@ -0,0 +1,24 @@ +// Copyright (c) Canaan Inc. All rights reserved. +// Licensed under the Apache license. See LICENSE file in the project root for full license information. + +using System.Linq; +using Nncase.IR; +using Nncase.PatternMatch; +using static Nncase.IR.TypePatternUtility; +using static Nncase.PatternMatch.F.Tensors; +using static Nncase.PatternMatch.Utility; + +namespace Nncase.Passes.Rules.ShapeExpr; + +[RuleGenerator] +public sealed partial class GatherToGetItem : RewriteRule +{ + // (Gather(input, 0, 0) -> GetItem(input) + public override Pattern Pattern => IsGather( + IsWildcard("input"), IsTensorConst("axis"), IsTensorConst("index") with { TypePattern = IsScalar() }); + + private Expr? GetReplace(Expr input, int axis, int index) + { + return input[index]; + } +} diff --git a/src/Nncase.Passes/Rules/ShapeExpr/SliceToGetItem.cs b/src/Nncase.Passes/Rules/ShapeExpr/SliceToGetItem.cs new file mode 100644 index 0000000000..dd158f54ff --- /dev/null +++ b/src/Nncase.Passes/Rules/ShapeExpr/SliceToGetItem.cs @@ -0,0 +1,44 @@ +// Copyright (c) Canaan Inc. All rights reserved. +// Licensed under the Apache license. See LICENSE file in the project root for full license information. + +using System; +using System.Collections.Generic; +using System.Collections.Immutable; +using System.Linq; +using Nncase.IR; +using Nncase.IR.Math; +using Nncase.IR.Tensors; +using Nncase.Passes; +using Nncase.PatternMatch; +using static Nncase.IR.F.Math; +using static Nncase.IR.F.Tensors; +using static Nncase.IR.TypePatternUtility; +using static Nncase.PatternMatch.F.Math; +using static Nncase.PatternMatch.F.Tensors; +using static Nncase.PatternMatch.Utility; + +namespace Nncase.Passes.Rules.Neutral; + +// Slice(shape, 1, 2, 1, 1) -> shape[1] +[RuleGenerator] +public partial class SliceToGetItem : RewriteRule +{ + public override Pattern Pattern => IsSqueeze( + IsSlice( + IsWildcard("input") with { TypePattern = HasRank(1) }, + IsTensorConst("begins"), + IsTensorConst("ends"), + IsTensorConst("axes"), + IsTensorConst("strides", strides => strides.Value.ToArray()[0] == 1)), + IsTensorConst("dims")); + + private Expr? GetReplace(Expr input, int[] begins, int[] ends) + { + if ((ends[0] - begins[0]) == 1) + { + return input[begins[0]]; + } + + return null; + } +} diff --git a/src/Nncase.Tests.TestFixture/TransformTestBase.cs b/src/Nncase.Tests.TestFixture/TransformTestBase.cs index 44abc38dac..9f1f8435c3 100644 --- a/src/Nncase.Tests.TestFixture/TransformTestBase.cs +++ b/src/Nncase.Tests.TestFixture/TransformTestBase.cs @@ -88,6 +88,7 @@ public Expr TestMatchedCore(Function pre, IReadOnlyDictionary? feed public Expr TestMatchedCore(Expr pre, IReadOnlyDictionary? feeds = null, params IRewriteRule[] rules) { + pre.InferenceType(); Assert.True(pre.InferenceType(), "TestInferFailed:" + pre.CheckedType); if (rules.Length == 0) { diff --git a/src/Nncase.Tests/Importer/UnitTestUtil.cs b/src/Nncase.Tests/Importer/UnitTestUtil.cs index 9e1bc419a5..30622d79d3 100644 --- a/src/Nncase.Tests/Importer/UnitTestUtil.cs +++ b/src/Nncase.Tests/Importer/UnitTestUtil.cs @@ -34,23 +34,6 @@ public void TestZeroTensor() Assert.Equal(new TensorConst(Tensor.From(new[] { 0 })), Util.ZeroTensor()); } - [Fact] - public void TestGetPaddings() - { - var input = OrtKI.Random(1, 2, 4, 8).ToTensor(); - var weights = OrtKI.Random(3, 3, 2, 2).ToTensor(); - var stride = new long[] { 1, 1, 1, 1 }; - var dilation = new long[] { 1, 1 }; - var expr = Util.GetPaddings(input, weights, stride, dilation, true); - - var (inH, inW) = Util.GetHW(input); - var (fH, fW) = Util.GetHW(weights); - var padH = Util.GetWindowedPadding(inH, fH, (int)stride[0], (int)dilation[0], true); - var padW = Util.GetWindowedPadding(inW, fW, (int)stride[1], (int)dilation[1], true); - var expect = Util.ConcatPadding(padH, padW); - Assert.Equal(expect, expr); - } - [Fact] public void TestComputeSplit() { diff --git a/src/Nncase.Tests/Rules/Neutral/UnitTestFoldSqueeze.cs b/src/Nncase.Tests/Rules/Neutral/UnitTestFoldSqueeze.cs new file mode 100644 index 0000000000..3f30ee7dc8 --- /dev/null +++ b/src/Nncase.Tests/Rules/Neutral/UnitTestFoldSqueeze.cs @@ -0,0 +1,33 @@ +// Copyright (c) Canaan Inc. All rights reserved. +// Licensed under the Apache license. See LICENSE file in the project root for full license information. + +using System.Collections.Generic; +using Nncase.IR; +using Nncase.Passes.Rules.Neutral; +using Nncase.Tests.TestFixture; +using Xunit; +using static Nncase.IR.F.Tensors; + +namespace Nncase.Tests.Rules.NeutralTest; + +[AutoSetupTestMethod(InitSession = true)] +public class UnitTestFoldSqueeze : TransformTestBase +{ + [Fact] + public void TestFoldSqueezeUnsqueeze() + { + var input = Testing.Rand(1, 3, 24); + var inputVar = new Var(new TensorType(input.ElementType, input.Shape)); + var expr = Squeeze(Unsqueeze(inputVar, new[] { -3 }), new[] { 1 }); + TestMatched(expr, new Dictionary { { inputVar, Value.FromTensor(input) } }); + } + + [Fact] + public void TestFoldUnsqueezeSqueeze() + { + var input = Testing.Rand(1, 1, 3, 24); + var inputVar = new Var(new TensorType(input.ElementType, input.Shape)); + var expr = Unsqueeze(Squeeze(inputVar, new[] { 1 }), new[] { -3 }); + TestMatched(expr, new Dictionary { { inputVar, Value.FromTensor(input) } }); + } +} diff --git a/src/Nncase.Tests/Rules/Neutral/UnitTestSplitSpaceToBatch.cs b/src/Nncase.Tests/Rules/Neutral/UnitTestSplitSpaceToBatch.cs new file mode 100644 index 0000000000..4ef0186aad --- /dev/null +++ b/src/Nncase.Tests/Rules/Neutral/UnitTestSplitSpaceToBatch.cs @@ -0,0 +1,39 @@ +// Copyright (c) Canaan Inc. All rights reserved. +// Licensed under the Apache license. See LICENSE file in the project root for full license information. + +using Nncase.Diagnostics; +using Nncase.IR; +using Nncase.IR.NN; +using Nncase.Passes.Rules.Neutral; +using Nncase.Tests.TestFixture; +using Xunit; +using static Nncase.IR.F.NN; + +namespace Nncase.Tests.Rules.NeutralTest; + +[AutoSetupTestMethod(InitSession = true)] +public class UnitTestSpaceToBatch : TransformTestBase +{ + [Fact] + public void TestSplitSpaceToBatch() + { + var i = SpaceToBatch(Testing.Rand(1, 206, 192), new[] { 3 }, new[,] { { 0, 1 } }); + var originEvaluateResult = i.Evaluate(); + var newBody = TestMatched(i); + var ev = newBody.Evaluate(); + _ = Comparator.CosSimilarity(originEvaluateResult, ev); + var dumpDir = Dumpper.Directory; + var (_, kmodel) = Testing.BuildKModel("kmodel", new IRModule(new Function(newBody, System.Array.Empty())), CompileSession); + var inputs = System.Array.Empty(); + var result = Testing.RunKModel(kmodel, dumpDir, inputs); + var v = Comparator.CosSimilarity(ev, result); + Assert.True(v[0] > 0.99f); + } + + [Fact] + public void TestSplitBatchToSpace() + { + var i = BatchToSpace(Testing.Rand(3, 192, 67), new[] { 3 }, new[,] { { 0, 1 } }); + TestMatched(i); + } +} diff --git a/src/Nncase.Tests/Rules/ShapeBucket/ShapeBucketTest.cs b/src/Nncase.Tests/Rules/ShapeBucket/ShapeBucketTest.cs index b014ad2d6f..a65c520bf1 100644 --- a/src/Nncase.Tests/Rules/ShapeBucket/ShapeBucketTest.cs +++ b/src/Nncase.Tests/Rules/ShapeBucket/ShapeBucketTest.cs @@ -24,6 +24,7 @@ using static Nncase.IR.F.NN; using static Nncase.IR.F.Tensors; using static Nncase.Tests.Rules.ShapeBucket.ShapeBucketTestHelper; +using Reshape = Nncase.IR.Tensors.Reshape; namespace Nncase.Tests.Rules.ShapeBucket; @@ -60,7 +61,157 @@ public void TestBucketPad() Assert.True(cos > 0.999); } - private Var Scalar(string name) => new Var(new TensorType(DataTypes.Int32, Shape.Scalar)); + [Fact] + public async Task TestSingleVarFusionBucket() + { + var mainVar = new Var(new TensorType(DataTypes.Float32, new[] { 1, Dimension.Unknown, 24, 24 })); + var dimVar = Scalar("dimVar"); + CompileOptions.ShapeBucketOptions.Enable = true; + CompileOptions.ShapeBucketOptions.SegmentsCount = 2; + CompileOptions.ShapeBucketOptions.RangeInfo = + new Dictionary { { "dimVar", (1, 20) } }; + CompileOptions.ShapeBucketOptions.VarMap = new Dictionary { { mainVar, new Expr[] { 1, dimVar, 24, 24 } } }; + + var input = Testing.Rand(1, 3, 24, 24); + var fusionVar = new Var(new TensorType(DataTypes.Float32, new[] { 1, Dimension.Unknown, 24, 24 })); + var f = new BucketFusion("MatMul_0", "stackvm", IR.F.Math.MatMul(fusionVar, fusionVar), new[] { fusionVar }, new[] { dimVar }); + var main = new Function("main", new Call(f, mainVar), mainVar); + var shape = new Dictionary(); + await new RecordFusionShape(shape).RunAsync(main, new()); + TestMatchedCore( + main.Body!, + new Dictionary { { mainVar, Value.FromTensor(input) } }, + new FusionBucket(shape)); + } + + [Fact] + public async Task TestRebuild() + { + var mainVar = new Var(new TensorType(DataTypes.Float32, new[] { 1, Dimension.Unknown, 24, 24 })); + var dimVar = Scalar("dimVar"); + CompileOptions.ShapeBucketOptions.Enable = true; + CompileOptions.ShapeBucketOptions.SegmentsCount = 2; + CompileOptions.ShapeBucketOptions.RangeInfo = + new Dictionary { { "dimVar", (1, 20) } }; + CompileOptions.ShapeBucketOptions.VarMap = new Dictionary { { mainVar, new Expr[] { 1, dimVar, 24, 24 } } }; + + var input = Testing.Rand(1, 3, 24, 24); + var fusionVar = new Var(new TensorType(DataTypes.Float32, new[] { 1, Dimension.Unknown, 24, 24 })); + var shapeVar = new Var(new TensorType(DataTypes.Int64, new[] { 4 })); + var body = IR.F.Math.MatMul(Reshape(fusionVar, shapeVar), fusionVar); + var f = new BucketFusion("MatMul_0", "stackvm", body, new[] { fusionVar, shapeVar }, new[] { dimVar }); + var main = new Function("main", new Call(f, mainVar, Stack(new IR.Tuple(new[] { 1L, ShapeOf(mainVar)[1], 24L, 24L }), 0))); + var shape = new Dictionary(); + await new RecordFusionShape(shape).RunAsync(main, new()); + var newBody = TestMatchedCore( + main.Body!, + new Dictionary { { mainVar, Value.FromTensor(input) } }, + new FusionBucket(shape)); + Assert.True(newBody is Call { Target: IR.Math.MatMul }); + } + + [Fact] + public async Task TestTupleOutput() + { + var mainVar = new Var(new TensorType(DataTypes.Float32, new[] { 1, Dimension.Unknown, 24, 24 })); + var dimVar = Scalar("dimVar"); + CompileOptions.ShapeBucketOptions.Enable = true; + CompileOptions.ShapeBucketOptions.SegmentsCount = 2; + CompileOptions.ShapeBucketOptions.RangeInfo = + new Dictionary { { "dimVar", (1, 20) } }; + CompileOptions.ShapeBucketOptions.VarMap = new Dictionary { { mainVar, new Expr[] { 1, dimVar, 24, 24 } } }; + + var input = Testing.Rand(1, 3, 24, 24); + var fusionVar = new Var(new TensorType(DataTypes.Float32, new[] { 1, Dimension.Unknown, 24, 24 })); + var mm = IR.F.Math.MatMul(fusionVar, fusionVar); + var body = new IR.Tuple(mm, mm); + var f = new BucketFusion("MatMul_0", "stackvm", body, new[] { fusionVar }, new[] { dimVar }); + var main = new Function("main", new Call(f, mainVar), mainVar); + var shape = new Dictionary(); + await new RecordFusionShape(shape).RunAsync(main, new()); + TestMatchedCore( + main.Body!, + new Dictionary { { mainVar, Value.FromTensor(input) } }, + new FusionBucket(shape)); + } + + [Fact] + public async Task TestDoubleVarFusionBucket() + { + var mainVarLhs = new Var(new TensorType(DataTypes.Float32, new[] { 1, Dimension.Unknown, 24, 24 })); + var mainVarRhs = new Var(new TensorType(DataTypes.Float32, new[] { 1, Dimension.Unknown, 24, 24 })); + var dimVar1 = Scalar("dimVar1"); + var dimVar2 = Scalar("dimVar2"); + CompileOptions.ShapeBucketOptions.Enable = true; + CompileOptions.ShapeBucketOptions.SegmentsCount = 5; + CompileOptions.ShapeBucketOptions.RangeInfo = + new Dictionary + { + { "dimVar1", (1, 20) }, + { "dimVar2", (1, 20) }, + }; + CompileOptions.ShapeBucketOptions.VarMap = new Dictionary + { + { mainVarLhs, new Expr[] { 1, dimVar1, 24, 24 } }, + { mainVarRhs, new Expr[] { 1, dimVar2, 24, 24 } }, + }; + + var inputLhs = Testing.Rand(1, 3, 24, 24); + var inputRhs = Testing.Rand(1, 3, 24, 24); + var fusionVar = new Var(new TensorType(DataTypes.Float32, new[] { 1, Dimension.Unknown, 24, 24 })); + var f = new BucketFusion("MatMul_0", "stackvm", IR.F.Math.MatMul(fusionVar, fusionVar), new[] { fusionVar }, new[] { dimVar1 }); + var main = new Function("main", new Call(f, mainVarLhs, mainVarRhs), mainVarLhs, mainVarRhs); + var shape = new Dictionary(); + await new RecordFusionShape(shape).RunAsync(main, new()); + TestMatchedCore( + main.Body!, + new Dictionary + { + { mainVarLhs, Value.FromTensor(inputLhs) }, + { mainVarRhs, Value.FromTensor(inputRhs) }, + }, + new FusionBucket(shape)); + } + + [Fact] + public async Task TestDoubleVarWithMultiDimEffect() + { + var mainVarLhs = new Var(new TensorType(DataTypes.Float32, new[] { 1, Dimension.Unknown, 24, 24 })); + var mainVarRhs = new Var(new TensorType(DataTypes.Float32, new[] { Dimension.Unknown, 1, 24, 24 })); + var dimVar1 = Scalar("dimVar1"); + var dimVar2 = Scalar("dimVar2"); + CompileOptions.ShapeBucketOptions.Enable = true; + CompileOptions.ShapeBucketOptions.SegmentsCount = 5; + CompileOptions.ShapeBucketOptions.RangeInfo = + new Dictionary + { + { "dimVar1", (1, 20) }, + { "dimVar2", (1, 20) }, + }; + CompileOptions.ShapeBucketOptions.VarMap = new Dictionary + { + { mainVarLhs, new Expr[] { 1, dimVar1, 24, 24 } }, + { mainVarRhs, new Expr[] { dimVar2, 1, 24, 24 } }, + }; + + var inputLhs = Testing.Rand(1, 3, 24, 24); + var inputRhs = Testing.Rand(3, 1, 24, 24); + var fusionVar = new Var(new TensorType(DataTypes.Float32, new[] { 1, Dimension.Unknown, 24, 24 })); + var f = new BucketFusion("MatMul_0", "stackvm", IR.F.Math.MatMul(fusionVar, fusionVar), new[] { fusionVar }, new[] { dimVar1 }); + var main = new Function("main", new Call(f, mainVarLhs, mainVarRhs), mainVarLhs, mainVarRhs); + var shape = new Dictionary(); + await new RecordFusionShape(shape).RunAsync(main, new()); + TestMatchedCore( + main.Body!, + new Dictionary + { + { mainVarLhs, Value.FromTensor(inputLhs) }, + { mainVarRhs, Value.FromTensor(inputRhs) }, + }, + new FusionBucket(shape)); + } + + private Var Scalar(string name) => new Var(name, new TensorType(DataTypes.Int32, Shape.Scalar)); } [AutoSetupTestMethod(InitSession = true)] @@ -121,7 +272,7 @@ public void TestBodyMultiInputMergeRight() }); } - [Fact(Skip = "Reshape is not stable")] + [Fact] public void TestPrevMultiInputForDynamicReshape() { // fusion @@ -199,7 +350,7 @@ public void TestAfterMergeSameInput() TestMatched(c, new Dictionary { { inputVar, Value.FromTensor(input) } }); } - [Fact(Skip = "Reshape is not stable")] + [Fact] public void TestMatMulReshape() { // 左边的表达式是右边表达式的一部分 @@ -354,6 +505,17 @@ public void TestMergeInputInTupleWhichHadBeMerged() Assert.Equal(1, call.Arguments.Length); } + [Fact] + public async Task TestFoldNopTuple() + { + var input = (Expr)new[] { 1, 3, 24, 48 }; + var t = new IR.Tuple(new[] { input[0], input[1] }); + var b = t[0] + t[1]; + Dumpper.DumpIR(b, "b"); + var result = await new FoldNopTuple().RunAsync(new Function(b), new()); + Dumpper.DumpIR(result, "result"); + } + private static BucketFusion GetResultFusion(Expr result) { var fusion = (BucketFusion)((Call)result).Target; diff --git a/src/Nncase.Tests/Rules/ShapeExpr/UnitTestFoldBroadcastShape.cs b/src/Nncase.Tests/Rules/ShapeExpr/UnitTestFoldBroadcastShape.cs new file mode 100644 index 0000000000..dfb1b8c415 --- /dev/null +++ b/src/Nncase.Tests/Rules/ShapeExpr/UnitTestFoldBroadcastShape.cs @@ -0,0 +1,31 @@ +// Copyright (c) Canaan Inc. All rights reserved. +// Licensed under the Apache license. See LICENSE file in the project root for full license information. + +using System; +using Nncase.IR; +using Nncase.Passes.Rules.ShapeExpr; +using Nncase.Tests.TestFixture; +using Xunit; +using static Nncase.IR.F.ShapeExpr; + +namespace Nncase.Tests.Rules.ShapeExpr; + +[AutoSetupTestMethod(InitSession = true)] +public class UnitTestFoldBroadcastShape : TransformTestBase +{ + [Fact] + public void TestFoldBroadcastShape() + { + var b1 = BroadcastShape(new[] { (Expr)Tensor.From(new[] { 1, 3 }), Tensor.From(new[] { 1 }) }); + var b2 = BroadcastShape(new[] { (Expr)b1, Tensor.From(new[] { 1, 1 }) }); + TestMatched(b2); + } + + [Fact] + public void TestFoldBroadcastShapeConst() + { + var input = Testing.Rand(1, 3, 1, 1); + var b = BroadcastShape(new Expr[] { new[] { 1, 3 }, Array.Empty(), IR.F.Tensors.ShapeOf(input) }); + TestMatched(b); + } +} diff --git a/src/Nncase.Tests/Rules/ShapeExpr/UnitTestFoldGetItemShapeOf.cs b/src/Nncase.Tests/Rules/ShapeExpr/UnitTestFoldGetItemShapeOf.cs new file mode 100644 index 0000000000..bab7175f5a --- /dev/null +++ b/src/Nncase.Tests/Rules/ShapeExpr/UnitTestFoldGetItemShapeOf.cs @@ -0,0 +1,45 @@ +// Copyright (c) Canaan Inc. All rights reserved. +// Licensed under the Apache license. See LICENSE file in the project root for full license information. + +using System; +using System.Collections.Generic; +using System.Linq; +using System.Threading.Tasks; +using Nncase.Diagnostics; +using Nncase.IR; +using Nncase.Passes.Rules.Neutral; +using Nncase.Passes.Rules.ShapeExpr; +using Xunit; +using Xunit.Abstractions; +using static Nncase.IR.F.Tensors; + +namespace Nncase.Tests.Rules.ShapeExpr; + +[TestFixture.AutoSetupTestMethod(InitSession = true)] +public class UnitTestFoldGetItemShapeOf : TransformTestBase +{ + [Fact] + public void TestFoldGetItemShapeOf() + { + var input = new Var(new TensorType(DataTypes.Float32, new[] { 1, 3, Dimension.Unknown, 24 })); + var data = Testing.Rand(1, 3, 24, 24); + var dict = new Dictionary { { input, Value.FromTensor(data) } }; + TestMatched(ShapeOf(input)[1], dict); + } + + [Fact] + public void TestFoldGetItemShapeOfWithCast() + { + var input = new Var(new TensorType(DataTypes.Float32, new[] { 1, 3, Dimension.Unknown, 24 })); + var data = Testing.Rand(1, 3, 24, 24); + var dict = new Dictionary { { input, Value.FromTensor(data) } }; + TestMatched(Cast(ShapeOf(input), DataTypes.Int32)[1], dict); + } + + [Fact] + public void TestFoldGetItemShapeOfWithDynamic() + { + var input = new Var(new TensorType(DataTypes.Int32, new[] { 1, 3, Dimension.Unknown, 24 })); + TestNotMatch(ShapeOf(input)[2]); + } +} diff --git a/src/Nncase.Tests/Rules/ShapeExpr/UnitTestFoldSplitShapeOf.cs b/src/Nncase.Tests/Rules/ShapeExpr/UnitTestFoldSplitShapeOf.cs new file mode 100644 index 0000000000..845755e2f8 --- /dev/null +++ b/src/Nncase.Tests/Rules/ShapeExpr/UnitTestFoldSplitShapeOf.cs @@ -0,0 +1,28 @@ +// Copyright (c) Canaan Inc. All rights reserved. +// Licensed under the Apache license. See LICENSE file in the project root for full license information. + +using System; +using System.Collections.Generic; +using System.Linq; +using System.Threading.Tasks; +using Nncase.Diagnostics; +using Nncase.IR; +using Nncase.Passes.Rules.ShapeExpr; +using Xunit; +using Xunit.Abstractions; +using static Nncase.IR.F.Tensors; + +namespace Nncase.Tests.Rules.ShapeExpr; + +[TestFixture.AutoSetupTestMethod(InitSession = true)] +public class UnitTestFoldSplitShapeOf : TransformTestBase +{ + [Fact] + public void TestFoldSplitShapeOf() + { + var input = Testing.Rand(1, 3, 24, 24); + var shape = ShapeOf(input); + var newShape = Stack(new IR.Tuple(shape[0], shape[1], shape[2], shape[3]), 0); + TestMatched(newShape); + } +} diff --git a/src/Nncase.Tests/Rules/ShapeExpr/UnitTestGatherToGetItem.cs b/src/Nncase.Tests/Rules/ShapeExpr/UnitTestGatherToGetItem.cs new file mode 100644 index 0000000000..4d2a78bf47 --- /dev/null +++ b/src/Nncase.Tests/Rules/ShapeExpr/UnitTestGatherToGetItem.cs @@ -0,0 +1,35 @@ +// Copyright (c) Canaan Inc. All rights reserved. +// Licensed under the Apache license. See LICENSE file in the project root for full license information. + +using System; +using System.Collections.Generic; +using System.Linq; +using System.Threading.Tasks; +using Nncase.Diagnostics; +using Nncase.IR; +using Nncase.Passes.Rules.ShapeExpr; +using Xunit; +using Xunit.Abstractions; +using static Nncase.IR.F.Tensors; + +namespace Nncase.Tests.Rules.ShapeExpr; + +[TestFixture.AutoSetupTestMethod(InitSession = true)] +public class UnitTestGatherToGetItem : TransformTestBase +{ + [Fact] + public void TestGatherToGetItem() + { + var input = new[] { 1, 2, 3, 4 }; + var gather = Gather(input, 0, 0); + TestMatched(gather); + } + + [Fact] + public void TestIndexNotScalar() + { + var input = new[] { 1, 2, 3, 4 }; + var gather = Gather(input, 0, new[] { 1, 2 }); + TestNotMatch(gather); + } +} diff --git a/src/Nncase.Tests/Rules/ShapeExpr/UnitTestSliceToGetItem.cs b/src/Nncase.Tests/Rules/ShapeExpr/UnitTestSliceToGetItem.cs new file mode 100644 index 0000000000..04c0d1c71b --- /dev/null +++ b/src/Nncase.Tests/Rules/ShapeExpr/UnitTestSliceToGetItem.cs @@ -0,0 +1,36 @@ +// Copyright (c) Canaan Inc. All rights reserved. +// Licensed under the Apache license. See LICENSE file in the project root for full license information. + +using System; +using System.Collections.Generic; +using System.Linq; +using System.Threading.Tasks; +using Nncase.Diagnostics; +using Nncase.IR; +using Nncase.Passes.Rules.Neutral; +using Nncase.Passes.Rules.ShapeExpr; +using Xunit; +using Xunit.Abstractions; +using static Nncase.IR.F.Tensors; + +namespace Nncase.Tests.Rules.ShapeExpr; + +[TestFixture.AutoSetupTestMethod(InitSession = true)] +public class UnitTestSliceToGetItem : TransformTestBase +{ + [Fact] + public void TestSliceToGetItem() + { + var input = new[] { 1, 2, 3, 4 }; + var gather = Squeeze(Slice(input, new[] { 1 }, new[] { 2 }, 1), new[] { 0 }); + TestMatched(gather); + } + + [Fact] + public void TestTooLong() + { + var input = new[] { 1, 2, 3, 4 }; + var gather = Slice(input, new[] { 1 }, new[] { 3 }, 1); + TestNotMatch(gather); + } +} diff --git a/test.md b/test.md deleted file mode 100644 index 05f5b33bb5..0000000000 --- a/test.md +++ /dev/null @@ -1,75 +0,0 @@ -| test | 完成情况 | -|-----------------------------|---------------| -| test_acosh.py | unary | -| test_and.py | err | -| test_argmax.py | err | -| test_argmin.py | err | -| test_asinh.py | unary | -| test_batchnorm.py | n | -| test_binary.py | tuple output | -| test_cast.py | numpy no bf16 | -| test_celu.py | y | -| test_clip.py | n | -| test_concat.py | tuple input | -| test_constantofshape.py | y | -| test_conv.py | err | -| test_conv_transpose.py | n | -| test_cosh.py | unary | -| test_cumsum.py | err | -| test_depthtospace.py | n | -| test_dequantizelinear.py | import | -| test_expand.py | n | -| test_flatten.py | n | -| test_gather_nd.py | err | -| test_gather.py | err | -| test_gemm2.py | x | -| test_gemm.py | x | -| test_hardmax.py | n | -| test_hardsigmoid.py | n | -| test_hardswish.py | y | -| test_identity.py | y | -| test_instancenorm.py | n | -| test_leakyrelu.py | y | -| test_logsoftmax.py | n | -| test_lrn.py | n | -| test_lstm.py | n | -| test_matmul.py | y | -| test_onehot.py | err | -| test_pad.py | err | -| test_pool.py | tuple output | -| test_prelu.py | y | -| test_quantizelinear.py | import | -| test_random_normal_like.py | n | -| test_random_normal.py | n | -| test_random_uniform_like.py | n | -| test_random_uniform.py | n | -| test_reducel1.py | y | -| test_reducel2.py | y | -| test_reduce_log_sum_exp.py | y | -| test_reduce_log_sum.py | y | -| test_reduce.py | y | -| test_reduce_sum_square.py | y | -| test_relu.py | y | -| test_reshape.py | | -| test_resize.py | | -| test_reverse_sequence.py | | -| test_selu.py | | -| test_shape.py | | -| test_sigmoid.py | | -| test_sign.py | | -| test_sinh.py | unary | -| test_size.py | | -| test_slice.py | | -| test_slice_to_conv2d.py | | -| test_softmax.py | | -| test_softplus.py | | -| test_softsign.py | | -| test_spacetodepth.py | | -| test_split.py | | -| test_squeeze.py | n | -| test_sum.py | | -| test_tile.py | n | -| test_transpose.py | err | -| test_unary.py | tuple output | -| test_unsqueeze.py | n | -| test_where.py | n | \ No newline at end of file diff --git a/testEnvironments.json b/testEnvironments.json deleted file mode 100644 index 2c5e92936e..0000000000 --- a/testEnvironments.json +++ /dev/null @@ -1,17 +0,0 @@ -{ - "version": "1", - "environments": [ - // 请参阅 https://aka.ms/remotetesting 获取更多信息 - // 了解如何配置远程环境。 - //{ - // "name": "WSL Ubuntu", - // "type": "wsl", - // "wslDistribution": "Ubuntu" - //}, - //{ - // "name": "Docker dotnet/sdk", - // "type": "docker", - // "dockerImage": "mcr.microsoft.com/dotnet/sdk" - //} - ] -} \ No newline at end of file From c8d94d07ff4a8c8ea6cb9315e224d79b1aa74810 Mon Sep 17 00:00:00 2001 From: Curio Yang Date: Mon, 18 Sep 2023 12:31:53 +0800 Subject: [PATCH 18/25] fix ci error test (#1093) Co-authored-by: yanghaoqi --- .github/workflows/compiler-build.yml | 4 ++-- .github/workflows/compiler-python-release.yml | 4 ++-- .github/workflows/runtime-build.yml | 4 ++-- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/.github/workflows/compiler-build.yml b/.github/workflows/compiler-build.yml index 20f819393d..760a925a6b 100644 --- a/.github/workflows/compiler-build.yml +++ b/.github/workflows/compiler-build.yml @@ -3,8 +3,8 @@ on: [push, pull_request] concurrency: - group: ${{ github.ref }} - cancel-in-progress: true + group: compiler-build-${{ github.ref }} + cancel-in-progress: ${{ github.ref != 'refs/heads/master' && !startsWith(github.ref, 'refs/heads/release/') }} env: NUGET_CERT_REVOCATION_MODE: offline diff --git a/.github/workflows/compiler-python-release.yml b/.github/workflows/compiler-python-release.yml index 65b9d8d450..9176290bd7 100644 --- a/.github/workflows/compiler-python-release.yml +++ b/.github/workflows/compiler-python-release.yml @@ -3,8 +3,8 @@ name: compiler-python-release on: [push, pull_request] concurrency: - group: ${{ github.ref }} - cancel-in-progress: true + group: compiler-python-release-${{ github.ref }} + cancel-in-progress: ${{ github.ref != 'refs/heads/master' && !startsWith(github.ref, 'refs/heads/release/') }} jobs: build-compiler: diff --git a/.github/workflows/runtime-build.yml b/.github/workflows/runtime-build.yml index 1b48c6fa77..0665ff10fb 100644 --- a/.github/workflows/runtime-build.yml +++ b/.github/workflows/runtime-build.yml @@ -3,8 +3,8 @@ name: runtime-build on: [push, pull_request] concurrency: - group: ${{ github.ref }} - cancel-in-progress: true + group: runtime-build-${{ github.ref }} + cancel-in-progress: ${{ github.ref != 'refs/heads/master' && !startsWith(github.ref, 'refs/heads/release/') }} jobs: build-native-runtime: From 77be775f6b0627bc37a6175cf31c7750ac7a169f Mon Sep 17 00:00:00 2001 From: nihui Date: Tue, 19 Sep 2023 16:28:19 +0800 Subject: [PATCH 19/25] ncnn importer (#332) * ncnn importer * convert convolution and convolutiondepthwise * convert innerproduct * pooling and softmax * mobilenetv1 runs * concat and split, squeezenet runs * add ncnn_ops doc * apply code-format changes * Update convolution.cpp * Update CMakeLists.txt * Fix build errors on macos * Fix build errors on macos * Add first ncnn test * Fix type hints * Fix tests folder name * clip hardsigmoid hardswish sigmoid * Fix pooling * Fix test * Add import ncnn api * Add more ops * Pass test * Remove unused code * Fix code format * Fix build * Fix build --------- Co-authored-by: nihui Co-authored-by: sunnycase --- .github/workflows/code-format.yml | 11 +- .github/workflows/compiler-build.yml | 1 + .gitignore | 3 + Directory.Packages.props | 2 +- docs/ncnn_ops.md | 19 + examples/user_guide/test.param | 33 + .../Nncase.Modules.StackVM/packages.lock.json | 12 +- python/nncase/__init__.py | 21 +- python/nncase/native/ffi.cpp | 4 +- requirements.test.txt | 3 +- src/Native/include/nncase/compiler.h | 24 +- src/Nncase.Cli/Commands/Compile.cs | 13 +- src/Nncase.Cli/packages.lock.json | 12 +- src/Nncase.CodeGen/packages.lock.json | 12 +- src/Nncase.Compiler/Compiler.cs | 66 +- src/Nncase.Compiler/CompilerExtensions.cs | 35 + src/Nncase.Compiler/Interop/CApi.cs | 31 +- src/Nncase.Compiler/packages.lock.json | 12 +- src/Nncase.Core/CompileOptions.cs | 5 + src/Nncase.Core/ICompiler.cs | 19 +- src/Nncase.Core/IR/Dimension.cs | 10 + src/Nncase.Core/IR/NN/Functional.cs | 2 + src/Nncase.Core/IR/Shape.cs | 23 + src/Nncase.Core/TensorOfT.cs | 2 + src/Nncase.Core/packages.lock.json | 12 +- src/Nncase.Diagnostics/packages.lock.json | 12 +- src/Nncase.EGraph/packages.lock.json | 12 +- src/Nncase.Evaluator/packages.lock.json | 12 +- src/Nncase.Graph/packages.lock.json | 12 +- src/Nncase.IO/ZeroStream.cs | 51 + src/Nncase.IO/packages.lock.json | 12 +- src/Nncase.Importer/Importers.cs | 15 + src/Nncase.Importer/Ncnn/Concat.cs | 27 + src/Nncase.Importer/Ncnn/Convolution.cs | 101 ++ src/Nncase.Importer/Ncnn/InnerProduct.cs | 43 + src/Nncase.Importer/Ncnn/NcnnImporter.cs | 156 +++ src/Nncase.Importer/Ncnn/NcnnModel.cs | 108 ++ src/Nncase.Importer/Ncnn/NcnnModelBin.cs | 72 + src/Nncase.Importer/Ncnn/ParamDict.cs | 119 ++ src/Nncase.Importer/Ncnn/Pooling.cs | 127 ++ src/Nncase.Importer/Ncnn/ShuffleChannel.cs | 37 + src/Nncase.Importer/Ncnn/Softmax.cs | 27 + src/Nncase.Importer/Ncnn/Split.cs | 25 + src/Nncase.Importer/packages.lock.json | 12 +- .../Rules/ShapeBucket/MergeCallToFusion.cs | 1 + src/Nncase.Passes/packages.lock.json | 12 +- .../Quantization/CalibrationEvaluator.cs | 12 +- src/Nncase.Quantization/packages.lock.json | 12 +- src/Nncase.Schedule/packages.lock.json | 12 +- src/Nncase.Simulator/packages.lock.json | 12 +- src/Nncase.Targets/packages.lock.json | 12 +- src/Nncase.Tests.TestFixture/ModelRunner.cs | 6 +- .../Nncase.Tests.TestFixture.csproj | 11 +- .../packages.lock.json | 1160 +++++++---------- src/Nncase.Tests/Importer/UnitTestImporter.cs | 11 + src/Nncase.Tests/TIR/UnitTestMutators.cs | 2 +- src/Nncase.Tests/packages.lock.json | 641 +-------- tests/importer/ncnn_/__init__.py | 0 tests/importer/ncnn_/basic/__init__.py | 0 tests/importer/ncnn_/basic/test_conv2d.py | 87 ++ tests/ncnn_test_runner.py | 209 +++ third_party/onnx/packages.lock.json | 12 +- third_party/tflite/packages.lock.json | 12 +- .../Nncase.SourceGenerator/packages.lock.json | 12 +- tools/StyleCopAnalyzers.ruleset | 5 +- tools/stackvm_gen/IsaGen/packages.lock.json | 12 +- 66 files changed, 2090 insertions(+), 1530 deletions(-) create mode 100644 docs/ncnn_ops.md create mode 100644 examples/user_guide/test.param create mode 100644 src/Nncase.Compiler/CompilerExtensions.cs create mode 100644 src/Nncase.IO/ZeroStream.cs create mode 100644 src/Nncase.Importer/Ncnn/Concat.cs create mode 100644 src/Nncase.Importer/Ncnn/Convolution.cs create mode 100644 src/Nncase.Importer/Ncnn/InnerProduct.cs create mode 100644 src/Nncase.Importer/Ncnn/NcnnImporter.cs create mode 100644 src/Nncase.Importer/Ncnn/NcnnModel.cs create mode 100644 src/Nncase.Importer/Ncnn/NcnnModelBin.cs create mode 100644 src/Nncase.Importer/Ncnn/ParamDict.cs create mode 100644 src/Nncase.Importer/Ncnn/Pooling.cs create mode 100644 src/Nncase.Importer/Ncnn/ShuffleChannel.cs create mode 100644 src/Nncase.Importer/Ncnn/Softmax.cs create mode 100644 src/Nncase.Importer/Ncnn/Split.cs create mode 100644 tests/importer/ncnn_/__init__.py create mode 100644 tests/importer/ncnn_/basic/__init__.py create mode 100644 tests/importer/ncnn_/basic/test_conv2d.py create mode 100644 tests/ncnn_test_runner.py diff --git a/.github/workflows/code-format.yml b/.github/workflows/code-format.yml index e41866c51d..ef02a4419e 100644 --- a/.github/workflows/code-format.yml +++ b/.github/workflows/code-format.yml @@ -2,11 +2,20 @@ name: code-format on: [pull_request] +concurrency: + group: code-format-${{ github.ref }} + cancel-in-progress: true + +permissions: + contents: read + jobs: code-format: + permissions: + contents: write # for stefanzweifel/git-auto-commit-action to push code in repo runs-on: ubuntu-20.04 steps: - - uses: actions/checkout@v2 + - uses: actions/checkout@v4 - name: Setup .NET uses: actions/setup-dotnet@v1 diff --git a/.github/workflows/compiler-build.yml b/.github/workflows/compiler-build.yml index 760a925a6b..ab9877f341 100644 --- a/.github/workflows/compiler-build.yml +++ b/.github/workflows/compiler-build.yml @@ -261,6 +261,7 @@ jobs: dotnet-coverage collect -s tools/dotnet_coverage.settings.xml -f cobertura -o coverage/tflite_basic.xml pytest tests/importer/tflite_/basic/ --doctest-modules --junitxml=test_results/tflite_basic.xml dotnet-coverage collect -s tools/dotnet_coverage.settings.xml -f cobertura -o coverage/tflite_combine.xml pytest tests/importer/tflite_/combine/ --doctest-modules --junitxml=test_results/tflite_combine.xml dotnet-coverage collect -s tools/dotnet_coverage.settings.xml -f cobertura -o coverage/tflite_model.xml pytest tests/importer/tflite_/model/ --doctest-modules --junitxml=test_results/tflite_model.xml + dotnet-coverage collect -s tools/dotnet_coverage.settings.xml -f cobertura -o coverage/ncnn_basic.xml pytest tests/importer/ncnn_/basic/ --doctest-modules --junitxml=test_results/ncnn_basic.xml dotnet-coverage merge -o coverage.integration.xml -f cobertura -r coverage/*.xml - name: Upload Coverage diff --git a/.gitignore b/.gitignore index e8d3ff9274..2dfd485fbe 100644 --- a/.gitignore +++ b/.gitignore @@ -262,6 +262,9 @@ __pycache__/ # vscode .vscode/ +# clangd +.cache/ + # pip /python/*/dist *egg-info diff --git a/Directory.Packages.props b/Directory.Packages.props index 9f48677feb..3b3a93c2df 100644 --- a/Directory.Packages.props +++ b/Directory.Packages.props @@ -49,7 +49,7 @@ - + diff --git a/docs/ncnn_ops.md b/docs/ncnn_ops.md new file mode 100644 index 0000000000..a48f321b14 --- /dev/null +++ b/docs/ncnn_ops.md @@ -0,0 +1,19 @@ +## Supported ncnn ops + +## 支持的 ncnn 算子 + +| Operator | Is Supported | +|-------|------------------ | +| Input | ✅ | +| Clip | ✅ | +| Concat | ✅ | +| Convolution | ✅ | +| ConvolutionDepthWise | ✅ | +| HardSigmoid | ✅ | +| HardSwish | ✅ | +| Innerproduct | ✅ | +| Pooling | ✅ | +| ReLU | ✅ | +| Sigmoid | ✅ | +| Softmax | ✅ | +| Split | ✅ | diff --git a/examples/user_guide/test.param b/examples/user_guide/test.param new file mode 100644 index 0000000000..50a81d0bc8 --- /dev/null +++ b/examples/user_guide/test.param @@ -0,0 +1,33 @@ +7767517 +31 31 +Input data 0 1 data -23330=4,3,224,224,3 0=224 1=224 2=3 +Convolution conv1 1 1 data conv1_relu1 -23330=4,3,112,112,32 0=32 1=3 3=2 4=1 5=1 6=864 9=1 +ConvolutionDepthWise conv2_1/dw 1 1 conv1_relu1 conv2_1/dw_relu2_1/dw -23330=4,3,112,112,32 0=32 1=3 4=1 5=1 6=288 7=32 9=1 +Convolution conv2_1/sep 1 1 conv2_1/dw_relu2_1/dw conv2_1/sep_relu2_1/sep -23330=4,3,112,112,64 0=64 1=1 5=1 6=2048 9=1 +ConvolutionDepthWise conv2_2/dw 1 1 conv2_1/sep_relu2_1/sep conv2_2/dw_relu2_2/dw -23330=4,3,56,56,64 0=64 1=3 3=2 4=1 5=1 6=576 7=64 9=1 +Convolution conv2_2/sep 1 1 conv2_2/dw_relu2_2/dw conv2_2/sep_relu2_2/sep -23330=4,3,56,56,128 0=128 1=1 5=1 6=8192 9=1 +ConvolutionDepthWise conv3_1/dw 1 1 conv2_2/sep_relu2_2/sep conv3_1/dw_relu3_1/dw -23330=4,3,56,56,128 0=128 1=3 4=1 5=1 6=1152 7=128 9=1 +Convolution conv3_1/sep 1 1 conv3_1/dw_relu3_1/dw conv3_1/sep_relu3_1/sep -23330=4,3,56,56,128 0=128 1=1 5=1 6=16384 9=1 +ConvolutionDepthWise conv3_2/dw 1 1 conv3_1/sep_relu3_1/sep conv3_2/dw_relu3_2/dw -23330=4,3,28,28,128 0=128 1=3 3=2 4=1 5=1 6=1152 7=128 9=1 +Convolution conv3_2/sep 1 1 conv3_2/dw_relu3_2/dw conv3_2/sep_relu3_2/sep -23330=4,3,28,28,256 0=256 1=1 5=1 6=32768 9=1 +ConvolutionDepthWise conv4_1/dw 1 1 conv3_2/sep_relu3_2/sep conv4_1/dw_relu4_1/dw -23330=4,3,28,28,256 0=256 1=3 4=1 5=1 6=2304 7=256 9=1 +Convolution conv4_1/sep 1 1 conv4_1/dw_relu4_1/dw conv4_1/sep_relu4_1/sep -23330=4,3,28,28,256 0=256 1=1 5=1 6=65536 9=1 +ConvolutionDepthWise conv4_2/dw 1 1 conv4_1/sep_relu4_1/sep conv4_2/dw_relu4_2/dw -23330=4,3,14,14,256 0=256 1=3 3=2 4=1 5=1 6=2304 7=256 9=1 +Convolution conv4_2/sep 1 1 conv4_2/dw_relu4_2/dw conv4_2/sep_relu4_2/sep -23330=4,3,14,14,512 0=512 1=1 5=1 6=131072 9=1 +ConvolutionDepthWise conv5_1/dw 1 1 conv4_2/sep_relu4_2/sep conv5_1/dw_relu5_1/dw -23330=4,3,14,14,512 0=512 1=3 4=1 5=1 6=4608 7=512 9=1 +Convolution conv5_1/sep 1 1 conv5_1/dw_relu5_1/dw conv5_1/sep_relu5_1/sep -23330=4,3,14,14,512 0=512 1=1 5=1 6=262144 9=1 +ConvolutionDepthWise conv5_2/dw 1 1 conv5_1/sep_relu5_1/sep conv5_2/dw_relu5_2/dw -23330=4,3,14,14,512 0=512 1=3 4=1 5=1 6=4608 7=512 9=1 +Convolution conv5_2/sep 1 1 conv5_2/dw_relu5_2/dw conv5_2/sep_relu5_2/sep -23330=4,3,14,14,512 0=512 1=1 5=1 6=262144 9=1 +ConvolutionDepthWise conv5_3/dw 1 1 conv5_2/sep_relu5_2/sep conv5_3/dw_relu5_3/dw -23330=4,3,14,14,512 0=512 1=3 4=1 5=1 6=4608 7=512 9=1 +Convolution conv5_3/sep 1 1 conv5_3/dw_relu5_3/dw conv5_3/sep_relu5_3/sep -23330=4,3,14,14,512 0=512 1=1 5=1 6=262144 9=1 +ConvolutionDepthWise conv5_4/dw 1 1 conv5_3/sep_relu5_3/sep conv5_4/dw_relu5_4/dw -23330=4,3,14,14,512 0=512 1=3 4=1 5=1 6=4608 7=512 9=1 +Convolution conv5_4/sep 1 1 conv5_4/dw_relu5_4/dw conv5_4/sep_relu5_4/sep -23330=4,3,14,14,512 0=512 1=1 5=1 6=262144 9=1 +ConvolutionDepthWise conv5_5/dw 1 1 conv5_4/sep_relu5_4/sep conv5_5/dw_relu5_5/dw -23330=4,3,14,14,512 0=512 1=3 4=1 5=1 6=4608 7=512 9=1 +Convolution conv5_5/sep 1 1 conv5_5/dw_relu5_5/dw conv5_5/sep_relu5_5/sep -23330=4,3,14,14,512 0=512 1=1 5=1 6=262144 9=1 +ConvolutionDepthWise conv5_6/dw 1 1 conv5_5/sep_relu5_5/sep conv5_6/dw_relu5_6/dw -23330=4,3,7,7,512 0=512 1=3 3=2 4=1 5=1 6=4608 7=512 9=1 +Convolution conv5_6/sep 1 1 conv5_6/dw_relu5_6/dw conv5_6/sep_relu5_6/sep -23330=4,3,7,7,1024 0=1024 1=1 5=1 6=524288 9=1 +ConvolutionDepthWise conv6/dw 1 1 conv5_6/sep_relu5_6/sep conv6/dw_relu6/dw -23330=4,3,7,7,1024 0=1024 1=3 4=1 5=1 6=9216 7=1024 9=1 +Convolution conv6/sep 1 1 conv6/dw_relu6/dw conv6/sep_relu6/sep -23330=4,3,7,7,1024 0=1024 1=1 5=1 6=1048576 9=1 +Pooling pool6 1 1 conv6/sep_relu6/sep pool6 -23330=4,1,1024,1,1 0=1 4=1 +InnerProduct fc7 1 1 pool6 fc7 -23330=4,1,1000,1,1 0=1000 1=1 2=1024000 +Softmax prob 1 1 fc7 output -23330=4,1,1000,1,1 diff --git a/modules/Nncase.Modules.StackVM/packages.lock.json b/modules/Nncase.Modules.StackVM/packages.lock.json index 3f4ecb96a0..b69bdc40f8 100644 --- a/modules/Nncase.Modules.StackVM/packages.lock.json +++ b/modules/Nncase.Modules.StackVM/packages.lock.json @@ -4,11 +4,11 @@ "net7.0": { "StyleCop.Analyzers": { "type": "Direct", - "requested": "[1.2.0-beta.435, )", - "resolved": "1.2.0-beta.435", - "contentHash": "TADk7vdGXtfTnYCV7GyleaaRTQjfoSfZXprQrVMm7cSJtJbFc1QIbWPyLvrgrfGdfHbGmUPvaN4ODKNxg2jgPQ==", + "requested": "[1.2.0-beta.507, )", + "resolved": "1.2.0-beta.507", + "contentHash": "/FtugDT66cKJJ+GGH7rNpG6UDrT4iIWz45M6lrXXHobDUFDHw+q5VgkbiR+6ffTO564ge7w6fQh/eoQhVdJO8Q==", "dependencies": { - "StyleCop.Analyzers.Unstable": "1.2.0.435" + "StyleCop.Analyzers.Unstable": "1.2.0.507" } }, "Google.OrTools.runtime.linux-arm64": { @@ -103,8 +103,8 @@ }, "StyleCop.Analyzers.Unstable": { "type": "Transitive", - "resolved": "1.2.0.435", - "contentHash": "ouwPWZxbOV3SmCZxIRqHvljkSzkCyi1tDoMzQtDb/bRP8ctASV/iRJr+A2Gdj0QLaLmWnqTWDrH82/iP+X80Lg==" + "resolved": "1.2.0.507", + "contentHash": "gTY3IQdRqDJ4hbhSA3e/R48oE8b/OiKfvwkt1QdNVfrJK2gMHBV8ldaHJ885jxWZfllK66soa/sdcjh9bX49Tw==" }, "System.Buffers": { "type": "Transitive", diff --git a/python/nncase/__init__.py b/python/nncase/__init__.py index a2376a8717..4d0c57042c 100644 --- a/python/nncase/__init__.py +++ b/python/nncase/__init__.py @@ -186,11 +186,15 @@ def import_caffe(self, model: bytes, prototxt: bytes) -> None: def import_onnx(self, model_content: bytes, options: ImportOptions) -> None: self._compile_options.input_format = "onnx" - self._import_module(model_content) + self._import_onnx_module(model_content) def import_tflite(self, model_content: bytes, options: ImportOptions) -> None: self._compile_options.input_format = "tflite" - self._import_module(model_content) + self._import_tflite_module(model_content) + + def import_ncnn(self, model_param: bytes, model_bin : bytes, options: ImportOptions) -> None: + self._compile_options.input_format = "ncnn" + self._import_ncnn_module(model_param, model_bin) def use_ptq(self, ptq_dataset_options: PTQTensorOptions) -> None: dataset = [_nncase.RTValue.from_runtime_tensor( @@ -275,9 +279,18 @@ def __process_compile_options(self, compile_options: CompileOptions) -> ClCompil self._compile_options.dump_flags = dump_flags self._compile_options.dump_dir = compile_options.dump_dir - def _import_module(self, model_content: bytes | io.RawIOBase) -> None: + def _import_onnx_module(self, model_content: bytes | io.RawIOBase) -> None: + stream = io.BytesIO(model_content) if isinstance(model_content, bytes) else model_content + self._module = IRModule(self._compiler.import_onnx_module(stream)) + + def _import_tflite_module(self, model_content: bytes | io.RawIOBase) -> None: stream = io.BytesIO(model_content) if isinstance(model_content, bytes) else model_content - self._module = IRModule(self._compiler.import_module(stream)) + self._module = IRModule(self._compiler.import_tflite_module(stream)) + + def _import_ncnn_module(self, model_param: bytes | io.RawIOBase, model_bin: bytes | io.RawIOBase) -> None: + param_stream = io.BytesIO(model_param) if isinstance(model_param, bytes) else model_param + bin_stream = io.BytesIO(model_bin) if isinstance(model_bin, bytes) else model_bin + self._module = IRModule(self._compiler.import_ncnn_module(param_stream, bin_stream)) def check_target(target: str): diff --git a/python/nncase/native/ffi.cpp b/python/nncase/native/ffi.cpp index 9ba5e751da..8bd6bd6ba9 100644 --- a/python/nncase/native/ffi.cpp +++ b/python/nncase/native/ffi.cpp @@ -299,7 +299,9 @@ PYBIND11_MODULE(_nncase, m) { .def_property_readonly("entry", &ir_module::entry); py::class_(m, "Compiler") - .def("import_module", &compiler::import_module) + .def("import_tflite_module", &compiler::import_tflite_module) + .def("import_onnx_module", &compiler::import_onnx_module) + .def("import_ncnn_module", &compiler::import_ncnn_module) .def("compile", &compiler::compile) .def("gencode", &compiler::gencode); diff --git a/requirements.test.txt b/requirements.test.txt index 5afc08e761..2e5eabae04 100644 --- a/requirements.test.txt +++ b/requirements.test.txt @@ -6,6 +6,7 @@ onnx==1.12.0 onnx-simplifier==0.3.6 onnxoptimizer==0.2.6 onnxruntime==1.12.0 +ncnn==1.0.20230816 numpy==1.21.0 torch==1.9.0 torchvision==0.10.0 @@ -15,8 +16,6 @@ kendryte-caffe pytest pytest-xdist pyyaml -pythonnet==3.0.1 -clr_loader==0.2.4 toml==0.10.2 pandas tabulate diff --git a/src/Native/include/nncase/compiler.h b/src/Native/include/nncase/compiler.h index 0412b270d1..6b7b33ef92 100644 --- a/src/Native/include/nncase/compiler.h +++ b/src/Native/include/nncase/compiler.h @@ -159,8 +159,13 @@ typedef struct { clr_object_handle_t (*compile_session_get_compiler)( clr_object_handle_t compile_session); void (*compiler_initialize)(); - clr_object_handle_t (*compiler_import_module)(clr_object_handle_t compiler, - clr_object_handle_t stream); + clr_object_handle_t (*compiler_import_tflite_module)( + clr_object_handle_t compiler, clr_object_handle_t stream); + clr_object_handle_t (*compiler_import_onnx_module)( + clr_object_handle_t compiler, clr_object_handle_t stream); + clr_object_handle_t (*compiler_import_ncnn_module)( + clr_object_handle_t compiler, clr_object_handle_t param_stream, + clr_object_handle_t bin_stream); void (*compiler_compile)(clr_object_handle_t compiler); void (*compiler_gencode)(clr_object_handle_t compiler, clr_object_handle_t stream); @@ -642,9 +647,20 @@ class compiler : public clr_object_base { public: using clr_object_base::clr_object_base; - ir_module import_module(cstream &stream) { + ir_module import_tflite_module(cstream &stream) { + return {std::in_place, nncase_clr_api()->compiler_import_tflite_module( + get(), stream.get())}; + } + + ir_module import_onnx_module(cstream &stream) { + return {std::in_place, nncase_clr_api()->compiler_import_onnx_module( + get(), stream.get())}; + } + + ir_module import_ncnn_module(cstream ¶m_stream, cstream &bin_stream) { return {std::in_place, - nncase_clr_api()->compiler_import_module(get(), stream.get())}; + nncase_clr_api()->compiler_import_ncnn_module( + get(), param_stream.get(), bin_stream.get())}; } void compile() { nncase_clr_api()->compiler_compile(obj_.get()); } diff --git a/src/Nncase.Cli/Commands/Compile.cs b/src/Nncase.Cli/Commands/Compile.cs index 3110b7dcf7..69a8cf0c54 100644 --- a/src/Nncase.Cli/Commands/Compile.cs +++ b/src/Nncase.Cli/Commands/Compile.cs @@ -86,6 +86,10 @@ public Compile() alias: "--calib-method", description: $"model quant options, default is {Quantization.CalibMethod.Kld}", getDefaultValue: () => Quantization.CalibMethod.Kld)); + AddOption(new Option( + alias: "--benchmark-only", + description: $"benchmark only", + getDefaultValue: () => false)); Handler = CommandHandler.Create(RunAsync); } @@ -138,17 +142,14 @@ private async Task RunAsync(CliCompileOptions cliOptions, IHost host) }, ModelQuantMode = cliOptions.ModelQuantMode, }, + IsBenchmarkOnly = cliOptions.BenchmarkOnly, }; // 2. import the model var target = CompilerServices.GetTarget(cliOptions.Target); using var compileSession = CompileSession.Create(target, compileOptions); var compiler = compileSession.Compiler; - IRModule module; - using (var model_stream = File.OpenRead(compileOptions.InputFile)) - { - module = await compiler.ImportModuleAsync(model_stream); - } + var module = await compiler.ImportModuleAsync(compileOptions.InputFormat, compileOptions.InputFile, compileOptions.IsBenchmarkOnly); // 3. create the calib dataset if (compileOptions.QuantizeOptions.ModelQuantMode == Quantization.ModelQuantMode.UsePTQ) @@ -206,6 +207,8 @@ internal sealed class CliCompileOptions public string Dataset { get; set; } public DatasetFormat DatasetFormat { get; set; } + + public bool BenchmarkOnly { get; set; } } #pragma warning restore CS8618 diff --git a/src/Nncase.Cli/packages.lock.json b/src/Nncase.Cli/packages.lock.json index e44016380c..b438ba9cc6 100644 --- a/src/Nncase.Cli/packages.lock.json +++ b/src/Nncase.Cli/packages.lock.json @@ -33,11 +33,11 @@ }, "StyleCop.Analyzers": { "type": "Direct", - "requested": "[1.2.0-beta.435, )", - "resolved": "1.2.0-beta.435", - "contentHash": "TADk7vdGXtfTnYCV7GyleaaRTQjfoSfZXprQrVMm7cSJtJbFc1QIbWPyLvrgrfGdfHbGmUPvaN4ODKNxg2jgPQ==", + "requested": "[1.2.0-beta.507, )", + "resolved": "1.2.0-beta.507", + "contentHash": "/FtugDT66cKJJ+GGH7rNpG6UDrT4iIWz45M6lrXXHobDUFDHw+q5VgkbiR+6ffTO564ge7w6fQh/eoQhVdJO8Q==", "dependencies": { - "StyleCop.Analyzers.Unstable": "1.2.0.435" + "StyleCop.Analyzers.Unstable": "1.2.0.507" } }, "System.CommandLine.Hosting": { @@ -344,8 +344,8 @@ }, "StyleCop.Analyzers.Unstable": { "type": "Transitive", - "resolved": "1.2.0.435", - "contentHash": "ouwPWZxbOV3SmCZxIRqHvljkSzkCyi1tDoMzQtDb/bRP8ctASV/iRJr+A2Gdj0QLaLmWnqTWDrH82/iP+X80Lg==" + "resolved": "1.2.0.507", + "contentHash": "gTY3IQdRqDJ4hbhSA3e/R48oE8b/OiKfvwkt1QdNVfrJK2gMHBV8ldaHJ885jxWZfllK66soa/sdcjh9bX49Tw==" }, "System.Buffers": { "type": "Transitive", diff --git a/src/Nncase.CodeGen/packages.lock.json b/src/Nncase.CodeGen/packages.lock.json index b6602bf240..b618b5504c 100644 --- a/src/Nncase.CodeGen/packages.lock.json +++ b/src/Nncase.CodeGen/packages.lock.json @@ -10,11 +10,11 @@ }, "StyleCop.Analyzers": { "type": "Direct", - "requested": "[1.2.0-beta.435, )", - "resolved": "1.2.0-beta.435", - "contentHash": "TADk7vdGXtfTnYCV7GyleaaRTQjfoSfZXprQrVMm7cSJtJbFc1QIbWPyLvrgrfGdfHbGmUPvaN4ODKNxg2jgPQ==", + "requested": "[1.2.0-beta.507, )", + "resolved": "1.2.0-beta.507", + "contentHash": "/FtugDT66cKJJ+GGH7rNpG6UDrT4iIWz45M6lrXXHobDUFDHw+q5VgkbiR+6ffTO564ge7w6fQh/eoQhVdJO8Q==", "dependencies": { - "StyleCop.Analyzers.Unstable": "1.2.0.435" + "StyleCop.Analyzers.Unstable": "1.2.0.507" } }, "Microsoft.Extensions.Configuration.Abstractions": { @@ -53,8 +53,8 @@ }, "StyleCop.Analyzers.Unstable": { "type": "Transitive", - "resolved": "1.2.0.435", - "contentHash": "ouwPWZxbOV3SmCZxIRqHvljkSzkCyi1tDoMzQtDb/bRP8ctASV/iRJr+A2Gdj0QLaLmWnqTWDrH82/iP+X80Lg==" + "resolved": "1.2.0.507", + "contentHash": "gTY3IQdRqDJ4hbhSA3e/R48oE8b/OiKfvwkt1QdNVfrJK2gMHBV8ldaHJ885jxWZfllK66soa/sdcjh9bX49Tw==" }, "System.Buffers": { "type": "Transitive", diff --git a/src/Nncase.Compiler/Compiler.cs b/src/Nncase.Compiler/Compiler.cs index f4014fa047..9895f6e0b5 100644 --- a/src/Nncase.Compiler/Compiler.cs +++ b/src/Nncase.Compiler/Compiler.cs @@ -48,27 +48,22 @@ public Compiler(CompileSession compileSession, IModelBuilder modelBuilder, IDump /// public void ImportIRModule(IRModule module) => _module = module; - public async Task ImportModuleAsync(Stream content) + public Task ImportTFLiteModuleAsync(Stream content) { - var module = ImportModel(content); - if (_dumpper.IsEnabled(DumpFlags.Compile)) - { - _dumpper.DumpModule(module, "IRImport"); - } - - var preprocess_option = _compileSession.CompileOptions; - - await RunPassAsync(pmg => BroadcastOutputNamesAfterImportPass(pmg), "BroadcastOutputNamesAfterImport"); - await RunPassAsync(pmg => pmg.Add(), "ShapeInferAfterImport"); - await RunPassAsync(pmg => AddPreAndPostProcess(pmg), "AddPreAndPostProcessAfterImport"); + var module = Importers.ImportTFLite(content, _compileSession); + return InitializeModuleAsync(module); + } - var inferSucc = CompilerServices.InferenceType(module.Entry!); - if (!inferSucc) - { - throw new InvalidOperationException("InferShape Failed For This Model!"); - } + public Task ImportOnnxModuleAsync(Stream content) + { + var module = Importers.ImportOnnx(content, _compileSession); + return InitializeModuleAsync(module); + } - return module; + public Task ImportNcnnModuleAsync(Stream ncnnParam, Stream ncnnBin) + { + var module = Importers.ImportNcnn(ncnnParam, ncnnBin, _compileSession); + return InitializeModuleAsync(module); } public void BroadcastOutputNamesAfterImportPass(IPassManager passManager) @@ -277,6 +272,30 @@ public void Gencode(Stream output) linkedModel.Serialize(output); } + private async Task InitializeModuleAsync(IRModule module) + { + _module = module; + + if (_dumpper.IsEnabled(DumpFlags.Compile)) + { + _dumpper.DumpModule(module, "IRImport"); + } + + var preprocess_option = _compileSession.CompileOptions; + + await RunPassAsync(pmg => BroadcastOutputNamesAfterImportPass(pmg), "BroadcastOutputNamesAfterImport"); + await RunPassAsync(pmg => pmg.Add(), "ShapeInferAfterImport"); + await RunPassAsync(pmg => AddPreAndPostProcess(pmg), "AddPreAndPostProcessAfterImport"); + + var inferSucc = CompilerServices.InferenceType(module.Entry!); + if (!inferSucc) + { + throw new InvalidOperationException("InferShape Failed For This Model!"); + } + + return module; + } + private void RegisterTargetIndependQuantPass(IPassManager passManager) { var quantMode = _compileSession.CompileOptions.QuantizeOptions.ModelQuantMode; @@ -290,17 +309,6 @@ private void RegisterTargetIndependQuantPass(IPassManager passManager) } } - private IRModule ImportModel(Stream content) - { - _module = _compileSession.CompileOptions.InputFormat switch - { - "tflite" => Importers.ImportTFLite(content, _compileSession), - "onnx" => Importers.ImportOnnx(content, _compileSession), - var inputFormat => throw new NotImplementedException($"Not Implement {inputFormat} Importer!"), - }; - return _module; - } - private async Task RunPassAsync(Action register, string name) { var newName = $"{_runPassCount++}_" + name; diff --git a/src/Nncase.Compiler/CompilerExtensions.cs b/src/Nncase.Compiler/CompilerExtensions.cs new file mode 100644 index 0000000000..431acb2674 --- /dev/null +++ b/src/Nncase.Compiler/CompilerExtensions.cs @@ -0,0 +1,35 @@ +// Copyright (c) Canaan Inc. All rights reserved. +// Licensed under the Apache license. See LICENSE file in the project root for full license information. + +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using Nncase.IO; +using Nncase.IR; + +namespace Nncase; + +public static class CompilerExtensions +{ + public static async Task ImportModuleAsync(this ICompiler compiler, string modelFormat, string fileName, bool isBenchmarkOnly = false) + { + using var fileStream = File.OpenRead(fileName); + switch (modelFormat.ToUpperInvariant()) + { + case "TFLITE": + return await compiler.ImportTFLiteModuleAsync(fileStream); + case "ONNX": + return await compiler.ImportOnnxModuleAsync(fileStream); + case "NCNN": + { + using var binStream = isBenchmarkOnly ? (Stream)new ZeroStream() : File.OpenRead(Path.ChangeExtension(fileName, "bin")); + return await compiler.ImportNcnnModuleAsync(fileStream, binStream); + } + + default: + throw new NotSupportedException($"Unsupported model format: {modelFormat}"); + } + } +} diff --git a/src/Nncase.Compiler/Interop/CApi.cs b/src/Nncase.Compiler/Interop/CApi.cs index 88032210b3..3ce2d0e289 100644 --- a/src/Nncase.Compiler/Interop/CApi.cs +++ b/src/Nncase.Compiler/Interop/CApi.cs @@ -63,7 +63,9 @@ public unsafe struct CApiMT public delegate* unmanaged CompileSessionCreatePtr; public delegate* unmanaged CompileSessionGetCompilerPtr; public delegate* unmanaged CompilerInitializePtr; - public delegate* unmanaged CompilerImportModulePtr; + public delegate* unmanaged CompilerImportTFLiteModulePtr; + public delegate* unmanaged CompilerImportOnnxModulePtr; + public delegate* unmanaged CompilerImportNcnnModulePtr; public delegate* unmanaged CompilerCompilePtr; public delegate* unmanaged CompilerGencodePtr; public delegate* unmanaged DataTypeFromTypeCodePtr; @@ -131,7 +133,9 @@ public static void Initialize(CApiMT* mt) mt->CompileSessionCreatePtr = &CompileSessionCreate; mt->CompileSessionGetCompilerPtr = &CompileSessionGetCompiler; mt->CompilerInitializePtr = &CompilerInitialize; - mt->CompilerImportModulePtr = &CompilerImportModule; + mt->CompilerImportTFLiteModulePtr = &CompilerImportTFLiteModule; + mt->CompilerImportOnnxModulePtr = &CompilerImportOnnxModule; + mt->CompilerImportNcnnModulePtr = &CompilerImportNcnnModule; mt->CompilerCompilePtr = &CompilerCompile; mt->CompilerGencodePtr = &CompilerGencode; mt->DataTypeFromTypeCodePtr = &DataTypeFromTypeCode; @@ -395,11 +399,30 @@ private static void CompilerInitialize() } [UnmanagedCallersOnly] - private static IntPtr CompilerImportModule(IntPtr compilerHandle, IntPtr streamHandle) + private static IntPtr CompilerImportTFLiteModule(IntPtr compilerHandle, IntPtr streamHandle) { var compiler = Get(compilerHandle); var stream = Get(streamHandle); - var module = compiler.ImportModuleAsync(stream).Result; + var module = compiler.ImportTFLiteModuleAsync(stream).Result; + return GCHandle.ToIntPtr(GCHandle.Alloc(module)); + } + + [UnmanagedCallersOnly] + private static IntPtr CompilerImportOnnxModule(IntPtr compilerHandle, IntPtr streamHandle) + { + var compiler = Get(compilerHandle); + var stream = Get(streamHandle); + var module = compiler.ImportOnnxModuleAsync(stream).Result; + return GCHandle.ToIntPtr(GCHandle.Alloc(module)); + } + + [UnmanagedCallersOnly] + private static IntPtr CompilerImportNcnnModule(IntPtr compilerHandle, IntPtr ncnnParamHandle, IntPtr ncnnBinHandle) + { + var compiler = Get(compilerHandle); + var ncnnParam = Get(ncnnParamHandle); + var ncnnBin = Get(ncnnBinHandle); + var module = compiler.ImportNcnnModuleAsync(ncnnParam, ncnnBin).Result; return GCHandle.ToIntPtr(GCHandle.Alloc(module)); } diff --git a/src/Nncase.Compiler/packages.lock.json b/src/Nncase.Compiler/packages.lock.json index 5e1125683e..639bb6a9bc 100644 --- a/src/Nncase.Compiler/packages.lock.json +++ b/src/Nncase.Compiler/packages.lock.json @@ -49,11 +49,11 @@ }, "StyleCop.Analyzers": { "type": "Direct", - "requested": "[1.2.0-beta.435, )", - "resolved": "1.2.0-beta.435", - "contentHash": "TADk7vdGXtfTnYCV7GyleaaRTQjfoSfZXprQrVMm7cSJtJbFc1QIbWPyLvrgrfGdfHbGmUPvaN4ODKNxg2jgPQ==", + "requested": "[1.2.0-beta.507, )", + "resolved": "1.2.0-beta.507", + "contentHash": "/FtugDT66cKJJ+GGH7rNpG6UDrT4iIWz45M6lrXXHobDUFDHw+q5VgkbiR+6ffTO564ge7w6fQh/eoQhVdJO8Q==", "dependencies": { - "StyleCop.Analyzers.Unstable": "1.2.0.435" + "StyleCop.Analyzers.Unstable": "1.2.0.507" } }, "Google.OrTools.runtime.linux-arm64": { @@ -350,8 +350,8 @@ }, "StyleCop.Analyzers.Unstable": { "type": "Transitive", - "resolved": "1.2.0.435", - "contentHash": "ouwPWZxbOV3SmCZxIRqHvljkSzkCyi1tDoMzQtDb/bRP8ctASV/iRJr+A2Gdj0QLaLmWnqTWDrH82/iP+X80Lg==" + "resolved": "1.2.0.507", + "contentHash": "gTY3IQdRqDJ4hbhSA3e/R48oE8b/OiKfvwkt1QdNVfrJK2gMHBV8ldaHJ885jxWZfllK66soa/sdcjh9bX49Tw==" }, "System.Buffers": { "type": "Transitive", diff --git a/src/Nncase.Core/CompileOptions.cs b/src/Nncase.Core/CompileOptions.cs index 94ba4d7c89..5d7b3cb058 100644 --- a/src/Nncase.Core/CompileOptions.cs +++ b/src/Nncase.Core/CompileOptions.cs @@ -114,4 +114,9 @@ public sealed record CompileOptions /// Gets or sets quant options. ///
public ShapeBucketOptions ShapeBucketOptions { get; set; } = ShapeBucketOptions.Default; + + /// + /// Gets or sets a value indicating whether is benchmark only. + /// + public bool IsBenchmarkOnly { get; set; } } diff --git a/src/Nncase.Core/ICompiler.cs b/src/Nncase.Core/ICompiler.cs index e49afabf9d..2368b4a7df 100644 --- a/src/Nncase.Core/ICompiler.cs +++ b/src/Nncase.Core/ICompiler.cs @@ -16,11 +16,26 @@ namespace Nncase; public interface ICompiler { /// - /// Import DL model as ir module. + /// Import TFLite model as ir module. /// /// Model content. /// Imported ir module. - Task ImportModuleAsync(Stream content); + Task ImportTFLiteModuleAsync(Stream content); + + /// + /// Import Onnx model as ir module. + /// + /// Model content. + /// Imported ir module. + Task ImportOnnxModuleAsync(Stream content); + + /// + /// Import Ncnn model as ir module. + /// + /// Ncnn param stream. + /// Ncnn bin stream. + /// Imported ir module. + Task ImportNcnnModuleAsync(Stream ncnnParam, Stream ncnnBin); /// /// import ir module into compiler. diff --git a/src/Nncase.Core/IR/Dimension.cs b/src/Nncase.Core/IR/Dimension.cs index f799e3a8b5..83b1395ec0 100644 --- a/src/Nncase.Core/IR/Dimension.cs +++ b/src/Nncase.Core/IR/Dimension.cs @@ -150,5 +150,15 @@ public bool HasFixedValue(Predicate predicate) { return Value.HasValue && predicate(Value.Value); } + + public bool IsAssignableFrom(Dimension dimension) + { + if (IsUnknown) + { + return true; + } + + return dimension.Kind == DimensionKind.Fixed && Value == dimension.Value; + } } } diff --git a/src/Nncase.Core/IR/NN/Functional.cs b/src/Nncase.Core/IR/NN/Functional.cs index a93a68e1fd..30b4005388 100644 --- a/src/Nncase.Core/IR/NN/Functional.cs +++ b/src/Nncase.Core/IR/NN/Functional.cs @@ -44,6 +44,8 @@ public static class NN public static Call LRN(Expr input, Expr alpha, Expr beta, Expr bias, Expr size) => new Call(new LRN(), input, alpha, beta, bias, size); + public static Call Mish(Expr input) => input * Math.Tanh(Softplus(input)); + public static Call HardSigmoid(Expr input, Expr alpha, Expr beta) => new Call(new HardSigmoid(), input, alpha, beta); public static Call HardSwish(Expr input) => new Call(new HardSwish(), input); diff --git a/src/Nncase.Core/IR/Shape.cs b/src/Nncase.Core/IR/Shape.cs index 49ca06b096..c89541194b 100644 --- a/src/Nncase.Core/IR/Shape.cs +++ b/src/Nncase.Core/IR/Shape.cs @@ -316,6 +316,29 @@ public override bool Equals(object? other) return other is Shape shape && Equals(shape); } + public bool IsAssignableFrom(Shape shape) + { + if (IsUnranked) + { + return true; + } + + if (shape.IsUnranked || Rank != shape.Rank) + { + return false; + } + + for (int i = 0; i < _dimensions.Length; i++) + { + if (!_dimensions[i].IsAssignableFrom(shape[i])) + { + return false; + } + } + + return true; + } + private static ShapeKind KindOf(ReadOnlySpan dimensions) { return dimensions.AsValueEnumerable().Any(x => x.IsUnknown) ? ShapeKind.HasUnknownDimension : ShapeKind.Fixed; diff --git a/src/Nncase.Core/TensorOfT.cs b/src/Nncase.Core/TensorOfT.cs index 399521b2be..307af29180 100644 --- a/src/Nncase.Core/TensorOfT.cs +++ b/src/Nncase.Core/TensorOfT.cs @@ -60,6 +60,8 @@ public Tensor(Memory buffer, ReadOnlySpan dimensions) Buffer = buffer; } + public static Tensor Empty { get; } = new Tensor(0); + /// /// Gets memory storing backing values of this tensor. /// diff --git a/src/Nncase.Core/packages.lock.json b/src/Nncase.Core/packages.lock.json index 6d48777d94..b2543377b5 100644 --- a/src/Nncase.Core/packages.lock.json +++ b/src/Nncase.Core/packages.lock.json @@ -60,11 +60,11 @@ }, "StyleCop.Analyzers": { "type": "Direct", - "requested": "[1.2.0-beta.435, )", - "resolved": "1.2.0-beta.435", - "contentHash": "TADk7vdGXtfTnYCV7GyleaaRTQjfoSfZXprQrVMm7cSJtJbFc1QIbWPyLvrgrfGdfHbGmUPvaN4ODKNxg2jgPQ==", + "requested": "[1.2.0-beta.507, )", + "resolved": "1.2.0-beta.507", + "contentHash": "/FtugDT66cKJJ+GGH7rNpG6UDrT4iIWz45M6lrXXHobDUFDHw+q5VgkbiR+6ffTO564ge7w6fQh/eoQhVdJO8Q==", "dependencies": { - "StyleCop.Analyzers.Unstable": "1.2.0.435" + "StyleCop.Analyzers.Unstable": "1.2.0.507" } }, "System.Reactive": { @@ -109,8 +109,8 @@ }, "StyleCop.Analyzers.Unstable": { "type": "Transitive", - "resolved": "1.2.0.435", - "contentHash": "ouwPWZxbOV3SmCZxIRqHvljkSzkCyi1tDoMzQtDb/bRP8ctASV/iRJr+A2Gdj0QLaLmWnqTWDrH82/iP+X80Lg==" + "resolved": "1.2.0.507", + "contentHash": "gTY3IQdRqDJ4hbhSA3e/R48oE8b/OiKfvwkt1QdNVfrJK2gMHBV8ldaHJ885jxWZfllK66soa/sdcjh9bX49Tw==" }, "System.Buffers": { "type": "Transitive", diff --git a/src/Nncase.Diagnostics/packages.lock.json b/src/Nncase.Diagnostics/packages.lock.json index b3f4cb2588..93fabe1e48 100644 --- a/src/Nncase.Diagnostics/packages.lock.json +++ b/src/Nncase.Diagnostics/packages.lock.json @@ -4,11 +4,11 @@ "net7.0": { "StyleCop.Analyzers": { "type": "Direct", - "requested": "[1.2.0-beta.435, )", - "resolved": "1.2.0-beta.435", - "contentHash": "TADk7vdGXtfTnYCV7GyleaaRTQjfoSfZXprQrVMm7cSJtJbFc1QIbWPyLvrgrfGdfHbGmUPvaN4ODKNxg2jgPQ==", + "requested": "[1.2.0-beta.507, )", + "resolved": "1.2.0-beta.507", + "contentHash": "/FtugDT66cKJJ+GGH7rNpG6UDrT4iIWz45M6lrXXHobDUFDHw+q5VgkbiR+6ffTO564ge7w6fQh/eoQhVdJO8Q==", "dependencies": { - "StyleCop.Analyzers.Unstable": "1.2.0.435" + "StyleCop.Analyzers.Unstable": "1.2.0.507" } }, "Microsoft.Extensions.Configuration.Abstractions": { @@ -47,8 +47,8 @@ }, "StyleCop.Analyzers.Unstable": { "type": "Transitive", - "resolved": "1.2.0.435", - "contentHash": "ouwPWZxbOV3SmCZxIRqHvljkSzkCyi1tDoMzQtDb/bRP8ctASV/iRJr+A2Gdj0QLaLmWnqTWDrH82/iP+X80Lg==" + "resolved": "1.2.0.507", + "contentHash": "gTY3IQdRqDJ4hbhSA3e/R48oE8b/OiKfvwkt1QdNVfrJK2gMHBV8ldaHJ885jxWZfllK66soa/sdcjh9bX49Tw==" }, "System.Buffers": { "type": "Transitive", diff --git a/src/Nncase.EGraph/packages.lock.json b/src/Nncase.EGraph/packages.lock.json index 7004606929..83470253e5 100644 --- a/src/Nncase.EGraph/packages.lock.json +++ b/src/Nncase.EGraph/packages.lock.json @@ -41,11 +41,11 @@ }, "StyleCop.Analyzers": { "type": "Direct", - "requested": "[1.2.0-beta.435, )", - "resolved": "1.2.0-beta.435", - "contentHash": "TADk7vdGXtfTnYCV7GyleaaRTQjfoSfZXprQrVMm7cSJtJbFc1QIbWPyLvrgrfGdfHbGmUPvaN4ODKNxg2jgPQ==", + "requested": "[1.2.0-beta.507, )", + "resolved": "1.2.0-beta.507", + "contentHash": "/FtugDT66cKJJ+GGH7rNpG6UDrT4iIWz45M6lrXXHobDUFDHw+q5VgkbiR+6ffTO564ge7w6fQh/eoQhVdJO8Q==", "dependencies": { - "StyleCop.Analyzers.Unstable": "1.2.0.435" + "StyleCop.Analyzers.Unstable": "1.2.0.507" } }, "Google.OrTools.runtime.linux-arm64": { @@ -140,8 +140,8 @@ }, "StyleCop.Analyzers.Unstable": { "type": "Transitive", - "resolved": "1.2.0.435", - "contentHash": "ouwPWZxbOV3SmCZxIRqHvljkSzkCyi1tDoMzQtDb/bRP8ctASV/iRJr+A2Gdj0QLaLmWnqTWDrH82/iP+X80Lg==" + "resolved": "1.2.0.507", + "contentHash": "gTY3IQdRqDJ4hbhSA3e/R48oE8b/OiKfvwkt1QdNVfrJK2gMHBV8ldaHJ885jxWZfllK66soa/sdcjh9bX49Tw==" }, "System.Buffers": { "type": "Transitive", diff --git a/src/Nncase.Evaluator/packages.lock.json b/src/Nncase.Evaluator/packages.lock.json index 78887df6a5..78fc35c9da 100644 --- a/src/Nncase.Evaluator/packages.lock.json +++ b/src/Nncase.Evaluator/packages.lock.json @@ -13,11 +13,11 @@ }, "StyleCop.Analyzers": { "type": "Direct", - "requested": "[1.2.0-beta.435, )", - "resolved": "1.2.0-beta.435", - "contentHash": "TADk7vdGXtfTnYCV7GyleaaRTQjfoSfZXprQrVMm7cSJtJbFc1QIbWPyLvrgrfGdfHbGmUPvaN4ODKNxg2jgPQ==", + "requested": "[1.2.0-beta.507, )", + "resolved": "1.2.0-beta.507", + "contentHash": "/FtugDT66cKJJ+GGH7rNpG6UDrT4iIWz45M6lrXXHobDUFDHw+q5VgkbiR+6ffTO564ge7w6fQh/eoQhVdJO8Q==", "dependencies": { - "StyleCop.Analyzers.Unstable": "1.2.0.435" + "StyleCop.Analyzers.Unstable": "1.2.0.507" } }, "libortki": { @@ -87,8 +87,8 @@ }, "StyleCop.Analyzers.Unstable": { "type": "Transitive", - "resolved": "1.2.0.435", - "contentHash": "ouwPWZxbOV3SmCZxIRqHvljkSzkCyi1tDoMzQtDb/bRP8ctASV/iRJr+A2Gdj0QLaLmWnqTWDrH82/iP+X80Lg==" + "resolved": "1.2.0.507", + "contentHash": "gTY3IQdRqDJ4hbhSA3e/R48oE8b/OiKfvwkt1QdNVfrJK2gMHBV8ldaHJ885jxWZfllK66soa/sdcjh9bX49Tw==" }, "System.Buffers": { "type": "Transitive", diff --git a/src/Nncase.Graph/packages.lock.json b/src/Nncase.Graph/packages.lock.json index 4ece9f52bb..a439ce21fd 100644 --- a/src/Nncase.Graph/packages.lock.json +++ b/src/Nncase.Graph/packages.lock.json @@ -4,11 +4,11 @@ "net7.0": { "StyleCop.Analyzers": { "type": "Direct", - "requested": "[1.2.0-beta.435, )", - "resolved": "1.2.0-beta.435", - "contentHash": "TADk7vdGXtfTnYCV7GyleaaRTQjfoSfZXprQrVMm7cSJtJbFc1QIbWPyLvrgrfGdfHbGmUPvaN4ODKNxg2jgPQ==", + "requested": "[1.2.0-beta.507, )", + "resolved": "1.2.0-beta.507", + "contentHash": "/FtugDT66cKJJ+GGH7rNpG6UDrT4iIWz45M6lrXXHobDUFDHw+q5VgkbiR+6ffTO564ge7w6fQh/eoQhVdJO8Q==", "dependencies": { - "StyleCop.Analyzers.Unstable": "1.2.0.435" + "StyleCop.Analyzers.Unstable": "1.2.0.507" } }, "libortki": { @@ -78,8 +78,8 @@ }, "StyleCop.Analyzers.Unstable": { "type": "Transitive", - "resolved": "1.2.0.435", - "contentHash": "ouwPWZxbOV3SmCZxIRqHvljkSzkCyi1tDoMzQtDb/bRP8ctASV/iRJr+A2Gdj0QLaLmWnqTWDrH82/iP+X80Lg==" + "resolved": "1.2.0.507", + "contentHash": "gTY3IQdRqDJ4hbhSA3e/R48oE8b/OiKfvwkt1QdNVfrJK2gMHBV8ldaHJ885jxWZfllK66soa/sdcjh9bX49Tw==" }, "System.Buffers": { "type": "Transitive", diff --git a/src/Nncase.IO/ZeroStream.cs b/src/Nncase.IO/ZeroStream.cs new file mode 100644 index 0000000000..c9a18cb43e --- /dev/null +++ b/src/Nncase.IO/ZeroStream.cs @@ -0,0 +1,51 @@ +// Copyright (c) Canaan Inc. All rights reserved. +// Licensed under the Apache license. See LICENSE file in the project root for full license information. + +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace Nncase.IO; + +public sealed class ZeroStream : Stream +{ + public override bool CanRead => true; + + public override bool CanSeek => true; + + public override bool CanWrite => false; + + public override long Length => 0; + + public override long Position { get; set; } + + public override void Flush() + { + } + + public override int Read(byte[] buffer, int offset, int count) => count; + + public override long Seek(long offset, SeekOrigin origin) + { + switch (origin) + { + case SeekOrigin.Begin: + Position = offset; + break; + case SeekOrigin.Current: + Position += offset; + break; + case SeekOrigin.End: + Position = 0; + break; + } + + return Position; + } + + public override void SetLength(long value) => throw new NotSupportedException(); + + public override void Write(byte[] buffer, int offset, int count) => throw new NotSupportedException(); +} diff --git a/src/Nncase.IO/packages.lock.json b/src/Nncase.IO/packages.lock.json index ef24cbccbb..eb0c4a8b7c 100644 --- a/src/Nncase.IO/packages.lock.json +++ b/src/Nncase.IO/packages.lock.json @@ -4,17 +4,17 @@ "net7.0": { "StyleCop.Analyzers": { "type": "Direct", - "requested": "[1.2.0-beta.435, )", - "resolved": "1.2.0-beta.435", - "contentHash": "TADk7vdGXtfTnYCV7GyleaaRTQjfoSfZXprQrVMm7cSJtJbFc1QIbWPyLvrgrfGdfHbGmUPvaN4ODKNxg2jgPQ==", + "requested": "[1.2.0-beta.507, )", + "resolved": "1.2.0-beta.507", + "contentHash": "/FtugDT66cKJJ+GGH7rNpG6UDrT4iIWz45M6lrXXHobDUFDHw+q5VgkbiR+6ffTO564ge7w6fQh/eoQhVdJO8Q==", "dependencies": { - "StyleCop.Analyzers.Unstable": "1.2.0.435" + "StyleCop.Analyzers.Unstable": "1.2.0.507" } }, "StyleCop.Analyzers.Unstable": { "type": "Transitive", - "resolved": "1.2.0.435", - "contentHash": "ouwPWZxbOV3SmCZxIRqHvljkSzkCyi1tDoMzQtDb/bRP8ctASV/iRJr+A2Gdj0QLaLmWnqTWDrH82/iP+X80Lg==" + "resolved": "1.2.0.507", + "contentHash": "gTY3IQdRqDJ4hbhSA3e/R48oE8b/OiKfvwkt1QdNVfrJK2gMHBV8ldaHJ885jxWZfllK66soa/sdcjh9bX49Tw==" } } } diff --git a/src/Nncase.Importer/Importers.cs b/src/Nncase.Importer/Importers.cs index dabfef37a9..1c3cce1459 100644 --- a/src/Nncase.Importer/Importers.cs +++ b/src/Nncase.Importer/Importers.cs @@ -8,6 +8,7 @@ using System.Text; using System.Threading.Tasks; using Nncase.Importer; +using Nncase.Importer.Ncnn; using Nncase.Importer.TFLite; using Nncase.IR; @@ -45,4 +46,18 @@ public static IRModule ImportOnnx(Stream onnx, CompileSession compileSession) var importer = new OnnxImporter(onnx, compileSession); return importer.Import(); } + + /// + /// Import ncnn model. + /// + /// Ncnn param stream. + /// Ncnn bin stream. + /// compile session. + /// Imported IR module. + public static IRModule ImportNcnn(Stream ncnnParam, Stream ncnnBin, CompileSession compileSession) + { + compileSession.CompileOptions.ModelLayout = "NCHW"; + var importer = new NcnnImporter(ncnnParam, ncnnBin, compileSession); + return importer.Import(); + } } diff --git a/src/Nncase.Importer/Ncnn/Concat.cs b/src/Nncase.Importer/Ncnn/Concat.cs new file mode 100644 index 0000000000..2363144d4c --- /dev/null +++ b/src/Nncase.Importer/Ncnn/Concat.cs @@ -0,0 +1,27 @@ +// Copyright (c) Canaan Inc. All rights reserved. +// Licensed under the Apache license. See LICENSE file in the project root for full license information. + +using System; +using System.Collections.Generic; +using System.IO; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using Nncase.IR; +using Nncase.IR.Buffers; +using Nncase.IR.F; +using Nncase.IR.NN; + +namespace Nncase.Importer.Ncnn; + +public partial class NcnnImporter +{ + private Expr VisitConcat(NcnnLayer layer) + { + var axis = layer.ParamDict.Get(0, 0); + + var inputs = GetInputExprs(layer).ToArray(); + var output = Tensors.Concat(new IR.Tuple(inputs), axis); + return output; + } +} diff --git a/src/Nncase.Importer/Ncnn/Convolution.cs b/src/Nncase.Importer/Ncnn/Convolution.cs new file mode 100644 index 0000000000..5885feef46 --- /dev/null +++ b/src/Nncase.Importer/Ncnn/Convolution.cs @@ -0,0 +1,101 @@ +// Copyright (c) Canaan Inc. All rights reserved. +// Licensed under the Apache license. See LICENSE file in the project root for full license information. + +using System; +using System.Collections.Generic; +using System.IO; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using Microsoft.Extensions.Options; +using Nncase.IR; +using Nncase.IR.Buffers; +using Nncase.IR.F; +using Nncase.IR.NN; + +namespace Nncase.Importer.Ncnn; + +public partial class NcnnImporter +{ + private Expr VisitConvolution(NcnnLayer layer) + { + var numOutput = layer.ParamDict.Get(0, 0); + var kernelW = layer.ParamDict.Get(1, 0); + var kernelH = layer.ParamDict.Get(11, kernelW); + var dilationW = layer.ParamDict.Get(2, 1); + var dilationH = layer.ParamDict.Get(12, dilationW); + var strideW = layer.ParamDict.Get(3, 1); + var strideH = layer.ParamDict.Get(13, strideW); + var padLeft = layer.ParamDict.Get(4, 0); + var padRight = layer.ParamDict.Get(15, padLeft); + var padTop = layer.ParamDict.Get(14, padLeft); + var padBottom = layer.ParamDict.Get(16, padTop); + var padValue = layer.ParamDict.Get(18, 0.0f); + var biasTerm = layer.ParamDict.Get(5, 0); + var weightDataSize = layer.ParamDict.Get(6, 0); + var group = layer.ParamDict.Get(7, 1); + var activationType = layer.ParamDict.Get(9, 0); + var activationParams = layer.ParamDict.Get(10, Tensor.Empty).Buffer.Span; + + var numInput = weightDataSize / numOutput / kernelW / kernelH; + var kernelExtentW = (dilationW * (kernelW - 1)) + 1; + var kernelExtentH = (dilationH * (kernelH - 1)) + 1; + + if (padValue != 0) + { + throw new NotSupportedException($"Unsupported pad value: {padValue}."); + } + + var input = CHWToNCHW(GetInputExprs(layer, 0)); + + Expr[] paddingH; + Expr[] paddingW; + + if (padLeft is -233 or -234) + { + var inShape = Tensors.ShapeOf(input); + var w = inShape[3]; + var h = inShape[2]; + var padW = kernelExtentW + ((w - 1) / strideW * strideW) - w; + var padH = kernelExtentH + ((h - 1) / strideH * strideH) - h; + + if (padLeft == -233) + { + // SAME_UPPER + paddingH = new[] { padH / 2, padH - (padH / 2) }; + paddingW = new[] { padW / 2, padW - (padW / 2) }; + } + else + { + // SAME_LOWER + paddingH = new[] { padH - (padH / 2), padH / 2 }; + paddingW = new[] { padW - (padW / 2), padW / 2 }; + } + } + else + { + paddingH = new Expr[] { padTop, padBottom }; + paddingW = new Expr[] { padLeft, padRight }; + } + + var stride = Tensor.From(new[] { strideH, strideW }, new[] { 2 }); + var dilation = Tensor.From(new[] { dilationH, dilationW }, new[] { 2 }); + var clampRange = ToFloatClampRange(activationType, activationParams); + var clamp = Tensor.From(new[] { clampRange.Min, clampRange.Max }, new[] { 2 }); + var padding = Util.ConcatPadding(paddingH, paddingW); + var weights = _modelBin.LoadFloat32(new[] { numOutput, numInput, kernelH, kernelW }, true); + var bias = biasTerm != 0 ? _modelBin.LoadFloat32(new[] { numOutput }, false) : Tensor.FromScalar(0f, numOutput); + + var conv2d = NN.Conv2D(input, weights, bias, stride, padding, dilation, PadMode.Constant, group, clamp); + conv2d = activationType switch + { + 0 or 1 or 3 => conv2d, + 2 => NN.LeakyRelu(conv2d, activationParams[0]), + 4 => NN.Sigmoid(conv2d), + 5 => NN.Mish(conv2d), + _ => throw new NotSupportedException($"Unsupported activation type: {activationType}."), + }; + var output = NCHWToCHW(conv2d); + return output; + } +} diff --git a/src/Nncase.Importer/Ncnn/InnerProduct.cs b/src/Nncase.Importer/Ncnn/InnerProduct.cs new file mode 100644 index 0000000000..80aeb98bb2 --- /dev/null +++ b/src/Nncase.Importer/Ncnn/InnerProduct.cs @@ -0,0 +1,43 @@ +// Copyright (c) Canaan Inc. All rights reserved. +// Licensed under the Apache license. See LICENSE file in the project root for full license information. + +using System; +using System.Collections.Generic; +using System.IO; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using Microsoft.Extensions.Options; +using Nncase.IR; +using Nncase.IR.Buffers; +using Nncase.IR.F; +using Nncase.IR.NN; + +namespace Nncase.Importer.Ncnn; + +public partial class NcnnImporter +{ + private Expr VisitInnerProduct(NcnnLayer layer) + { + var numOutput = layer.ParamDict.Get(0, 0); + var biasTerm = layer.ParamDict.Get(1, 0) != 0; + var weightDataSize = layer.ParamDict.Get(2, 0); + var activationType = layer.ParamDict.Get(9, 0); + var activationParams = layer.ParamDict.Get(10, Tensor.Empty).Buffer.Span; + + var numInput = weightDataSize / numOutput; + + var input = Tensors.Unsqueeze(GetInputExprs(layer, 0), new[] { 0 }); + var weights = Tensors.Transpose(_modelBin.LoadFloat32(new[] { numOutput, numInput }, true), new[] { 1, 0 }); + + Expr output = IR.F.Math.MatMul(input, weights); + if (biasTerm) + { + output += _modelBin.LoadFloat32(new[] { numOutput }, false); + } + + output = ApplyActivation(output, activationType, activationParams); + output = Tensors.Squeeze(output, new[] { 0 }); + return output; + } +} diff --git a/src/Nncase.Importer/Ncnn/NcnnImporter.cs b/src/Nncase.Importer/Ncnn/NcnnImporter.cs new file mode 100644 index 0000000000..a67542aeab --- /dev/null +++ b/src/Nncase.Importer/Ncnn/NcnnImporter.cs @@ -0,0 +1,156 @@ +// Copyright (c) Canaan Inc. All rights reserved. +// Licensed under the Apache license. See LICENSE file in the project root for full license information. + +using System; +using System.Collections.Generic; +using System.Collections.Immutable; +using System.Diagnostics; +using System.IO; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using FlatBuffers; +using LanguageExt; +using NetFabric.Hyperlinq; +using Nncase.IR; +using Nncase.IR.F; +using Nncase.IR.Math; +using Nncase.IR.NN; +using Nncase.IR.Tensors; +using Math = System.Math; +using Tuple = Nncase.IR.Tuple; + +namespace Nncase.Importer.Ncnn; + +/// +/// Ncnn importer. +/// +public sealed partial class NcnnImporter : BaseImporter +{ + private static readonly Dictionary _typeMap = new() + { + { tflite.TensorType.BOOL, DataTypes.Boolean }, + { tflite.TensorType.FLOAT16, DataTypes.Float16 }, + { tflite.TensorType.FLOAT32, DataTypes.Float32 }, + { tflite.TensorType.FLOAT64, DataTypes.Float64 }, + { tflite.TensorType.INT16, DataTypes.Int16 }, + { tflite.TensorType.INT32, DataTypes.Int32 }, + { tflite.TensorType.INT64, DataTypes.Int64 }, + { tflite.TensorType.INT8, DataTypes.Int8 }, + { tflite.TensorType.STRING, DataTypes.Utf8Char }, + { tflite.TensorType.UINT32, DataTypes.UInt32 }, + { tflite.TensorType.UINT64, DataTypes.UInt64 }, + { tflite.TensorType.UINT8, DataTypes.UInt8 }, + }; + + private readonly NcnnModel _model; + private readonly NcnnModelBin _modelBin; + private readonly Dictionary _outputTensors = new Dictionary(); + + /// + /// Initializes a new instance of the class. + /// + /// Ncnn param stream. + /// Ncnn bin stream. + /// Compile session. + public NcnnImporter(Stream ncnnParam, Stream ncnnBin, CompileSession compileSession) + : base(compileSession) + { + _model = NcnnModel.ParseFromStream(ncnnParam); + _modelBin = new NcnnModelBin(ncnnBin); + } + + /// + protected override (IEnumerable Inputs, Dictionary VarMap) CreateInputs() + { + var inputs = new List(); + var varMap = new Dictionary(); + + foreach (var layer in _model.Layers.Where(x => x.Type == "Input")) + { + var input = new Var(layer.Name, TensorType.Unranked(DataTypes.Float32)); + inputs.Add(input); + _outputTensors.Add(layer.Name, input); + } + + return (inputs, varMap); + } + + protected override void ConvertOp() + { + foreach (var layer in _model.Layers.Where(x => x.Type != "Input")) + { + Visit(layer); + } + } + + protected override Expr CreateOutputs() + { + var outputTensors = (from l in _model.Layers + from t in l.Tops + select t).Select((x, i) => (x.Name, i)).ToDictionary(x => x.Name, x => x.i); + var unusedTensors = (from t in outputTensors.Keys.Except(from l in _model.Layers + from t in l.Bottoms + select t.Name) + orderby outputTensors[t] + select t).ToArray(); + var outputs = unusedTensors.Select(x => _outputTensors[x]).ToArray(); + var body = outputs.Length > 1 ? new IR.Tuple(outputs) : outputs[0]; + return body; + } + + private static Expr CHWToNCHW(Expr expr) => + Tensors.Unsqueeze(expr, new[] { 0 }); + + private static Expr NCHWToCHW(Expr expr) => + Tensors.Squeeze(expr, new[] { 0 }); + + private static ValueRange ToFloatClampRange(int activationType, ReadOnlySpan activationParams) => + activationType switch + { + 1 => new(0, float.PositiveInfinity), + 3 => new(activationParams[0], activationParams[1]), + _ => ValueRange.Full, + }; + + private static Expr ApplyActivation(Expr input, int activationType, ReadOnlySpan activationParams) => + activationType switch + { + 0 => input, + 1 => NN.Relu(input), + 2 => NN.LeakyRelu(input, activationParams[0]), + 3 => IR.F.Math.Clamp(input, activationParams[0], activationParams[1]), + 4 => NN.Sigmoid(input), + 5 => NN.Mish(input), + _ => throw new NotSupportedException($"Unsupported activation type: {activationType}."), + }; + + private void Visit(NcnnLayer layer) + { + var output = layer.Type switch + { + "Concat" => VisitConcat(layer), + "Convolution" => VisitConvolution(layer), + "ConvolutionDepthWise" => VisitConvolution(layer), + "InnerProduct" => VisitInnerProduct(layer), + "Pooling" => VisitPooling(layer), + "ShuffleChannel" => VisitShuffleChannel(layer), + "Softmax" => VisitSoftmax(layer), + "Split" => VisitSplit(layer), + _ => UnSupportedOp(layer.Type), + }; + + var outputNames = layer.Tops.Select(x => x.Name).ToArray(); + output.Metadata.OutputNames = outputNames; + AddToOutputs(_outputTensors, outputNames, output); + } + + private Expr GetInputExprs(NcnnLayer layer, int index) => + _outputTensors[layer.Bottoms[index].Name]; + + private (Expr Expr0, Expr Expr1) GetInputExprs(NcnnLayer layer, int index0, int index1) => + (GetInputExprs(layer, index0), GetInputExprs(layer, index1)); + + private IEnumerable GetInputExprs(NcnnLayer layer) => + layer.Bottoms.Select(x => _outputTensors[x.Name]); +} diff --git a/src/Nncase.Importer/Ncnn/NcnnModel.cs b/src/Nncase.Importer/Ncnn/NcnnModel.cs new file mode 100644 index 0000000000..488e191ad4 --- /dev/null +++ b/src/Nncase.Importer/Ncnn/NcnnModel.cs @@ -0,0 +1,108 @@ +// Copyright (c) Canaan Inc. All rights reserved. +// Licensed under the Apache license. See LICENSE file in the project root for full license information. + +using System; +using System.Collections.Generic; +using System.IO; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using Nncase.IR; + +namespace Nncase.Importer.Ncnn; + +internal class NcnnTensor +{ + public string Name { get; set; } = string.Empty; + + public Shape ShapeHint { get; set; } = Shape.Unranked; + + public override string ToString() => $"{Name}: {ShapeHint}"; +} + +internal class NcnnLayer +{ + public NcnnLayer(string type, string name, int bottomCount, int topCount) + { + Type = type; + Name = name; + Bottoms = new NcnnTensor[bottomCount]; + Tops = new NcnnTensor[topCount]; + } + + public string Type { get; } + + public string Name { get; } + + public NcnnTensor[] Bottoms { get; } + + public NcnnTensor[] Tops { get; } + + public ParamDict ParamDict { get; } = new(); + + public override string ToString() => $"[{Type}] {Name}"; +} + +internal class NcnnModel +{ + public static readonly int ExpectedMagic = 7767517; + + public NcnnModel(int magic, IReadOnlyList layers) + { + Magic = magic; + Layers = layers; + } + + public int Magic { get; } + + public IReadOnlyList Layers { get; } + + public static NcnnModel ParseFromStream(Stream stream) + { + using var reader = new StreamReader(stream, leaveOpen: true); + if (reader.ReadLine() is not string magicStr) + { + throw new InvalidDataException("parse magic failed"); + } + + if (reader.ReadLine()?.Split(' ', StringSplitOptions.RemoveEmptyEntries | StringSplitOptions.TrimEntries) is not [var layerCountStr, var blobCountStr]) + { + throw new InvalidDataException("parse layer_count or blob_count failed"); + } + + var magic = int.Parse(magicStr); + if (magic != ExpectedMagic) + { + throw new InvalidDataException("param is too old, please regenerate"); + } + + var layerCount = int.Parse(layerCountStr); + var blobCount = int.Parse(blobCountStr); + if (layerCount <= 0 || blobCount <= 0) + { + throw new InvalidDataException("invalid layer_count or blob_count"); + } + + var layers = new NcnnLayer[layerCount]; + foreach (ref var layer in layers.AsSpan()) + { + var fields = reader.ReadLine()!.Split(' ', StringSplitOptions.RemoveEmptyEntries | StringSplitOptions.TrimEntries); + layer = new NcnnLayer(fields[0], fields[1], int.Parse(fields[2]), int.Parse(fields[3])); + + int cntFieldIndex = 4; + foreach (ref var bottom in layer.Bottoms.AsSpan()) + { + bottom = new NcnnTensor { Name = fields[cntFieldIndex++] }; + } + + foreach (ref var top in layer.Tops.AsSpan()) + { + top = new NcnnTensor { Name = fields[cntFieldIndex++] }; + } + + layer.ParamDict.LoadFrom(fields.AsSpan(cntFieldIndex)); + } + + return new NcnnModel(magic, layers); + } +} diff --git a/src/Nncase.Importer/Ncnn/NcnnModelBin.cs b/src/Nncase.Importer/Ncnn/NcnnModelBin.cs new file mode 100644 index 0000000000..a0d60bdc03 --- /dev/null +++ b/src/Nncase.Importer/Ncnn/NcnnModelBin.cs @@ -0,0 +1,72 @@ +// Copyright (c) Canaan Inc. All rights reserved. +// Licensed under the Apache license. See LICENSE file in the project root for full license information. + +using System; +using System.Collections.Generic; +using System.IO; +using System.Linq; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; +using System.Text; +using System.Threading.Tasks; +using Microsoft.Toolkit.HighPerformance; + +namespace Nncase.Importer.Ncnn; + +internal class NcnnModelBin +{ + private readonly Stream _stream; + + public NcnnModelBin(Stream stream) + { + _stream = stream; + } + + public Tensor LoadFloat32(ReadOnlySpan shape, bool detectType) + { + if (!detectType) + { + var tensor = new Tensor(shape); + _stream.ReadExactly(tensor.BytesBuffer); + return tensor; + } + else + { + return LoadAuto(shape).Cast(); + } + } + + public Tensor LoadAuto(ReadOnlySpan shape) + { + uint tag; + Unsafe.SkipInit(out tag); + _stream.ReadExactly(MemoryMarshal.CreateSpan(ref tag, 1).AsBytes()); + + if (tag == 0x01306B47) + { + // half-precision data + var tensor = new Tensor(shape); + _stream.ReadExactly(tensor.BytesBuffer); + AlignStream(_stream, tensor.BytesBuffer.Length, 4); + return tensor.Cast(CastMode.KDefault); + } + else if (tag == 0) + { + // raw data + var tensor = new Tensor(shape); + _stream.ReadExactly(tensor.BytesBuffer); + return tensor; + } + else + { + throw new NotSupportedException($"Unsupported weight tag: {tag}."); + } + } + + private static void AlignStream(Stream stream, int size, int alignment) + { + var rem = size % alignment; + var offset = rem == 0 ? 0 : alignment - rem; + stream.Seek(offset, SeekOrigin.Current); + } +} diff --git a/src/Nncase.Importer/Ncnn/ParamDict.cs b/src/Nncase.Importer/Ncnn/ParamDict.cs new file mode 100644 index 0000000000..954525ea48 --- /dev/null +++ b/src/Nncase.Importer/Ncnn/ParamDict.cs @@ -0,0 +1,119 @@ +// Copyright (c) Canaan Inc. All rights reserved. +// Licensed under the Apache license. See LICENSE file in the project root for full license information. + +using System; +using System.Collections.Generic; +using System.IO; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using Google.Protobuf.WellKnownTypes; +using Nncase.IR; + +namespace Nncase.Importer.Ncnn; + +internal enum ParamKind +{ + Null, + IntOrFloat, + Int, + Float, + ArrayOfIntOrFloat, + ArrayOfInt, + ArrayOfFloat, +} + +internal struct ParamValue +{ + public ParamKind Kind; + + public int IntValue; + + public float FloatValue; + + public Tensor? TensorValue; +} + +internal class ParamDict +{ + public static readonly int NcnnMaxParamCount = 32; + + private readonly Dictionary _values = new(); + + public void LoadFrom(ReadOnlySpan fields) + { + foreach (var field in fields) + { + if (field.Split('=', StringSplitOptions.RemoveEmptyEntries | StringSplitOptions.TrimEntries) is not [var idStr, var valueStr]) + { + break; + } + + var id = int.Parse(idStr); + if (id >= NcnnMaxParamCount) + { + throw new InvalidDataException($"id < NCNN_MAX_PARAM_COUNT failed (id={id}, NCNN_MAX_PARAM_COUNT={NcnnMaxParamCount})"); + } + + var paramValue = default(ParamValue); + var isArray = id <= -23300; + var isFloat = valueStr.AsSpan().IndexOfAny('.', 'e', 'E') != -1; + if (isArray) + { + id = -id - 23300; + var elements = valueStr.Split(',', StringSplitOptions.RemoveEmptyEntries | StringSplitOptions.TrimEntries); + if (elements == null || elements.Length == 0) + { + throw new InvalidDataException("ParamDict read array length failed"); + } + + var length = int.Parse(elements[0]); + if (isFloat) + { + var value = new Tensor(length); + for (var i = 0; i < length; i++) + { + value[i] = float.Parse(elements[i + 1]); + } + + paramValue.Kind = ParamKind.ArrayOfFloat; + paramValue.TensorValue = value; + } + else + { + var value = new Tensor(length); + for (var i = 1; i < length; i++) + { + value[i] = int.Parse(elements[i + 1]); + } + + paramValue.Kind = ParamKind.ArrayOfInt; + paramValue.TensorValue = value; + } + } + else + { + if (isFloat) + { + paramValue.Kind = ParamKind.Float; + paramValue.FloatValue = float.Parse(valueStr); + } + else + { + paramValue.Kind = ParamKind.Int; + paramValue.IntValue = int.Parse(valueStr); + } + } + + _values.Add(id, paramValue); + } + } + + public int Get(int id, int defaultValue) => _values.TryGetValue(id, out var value) ? value.IntValue : defaultValue; + + public float Get(int id, float defaultValue) => _values.TryGetValue(id, out var value) ? value.FloatValue : defaultValue; + + public Tensor Get(int id, Tensor defaultValue) + where T : unmanaged, IEquatable + => _values.TryGetValue(id, out var value) ? value.TensorValue!.Cast() : defaultValue; +} diff --git a/src/Nncase.Importer/Ncnn/Pooling.cs b/src/Nncase.Importer/Ncnn/Pooling.cs new file mode 100644 index 0000000000..edc486d71d --- /dev/null +++ b/src/Nncase.Importer/Ncnn/Pooling.cs @@ -0,0 +1,127 @@ +// Copyright (c) Canaan Inc. All rights reserved. +// Licensed under the Apache license. See LICENSE file in the project root for full license information. + +using System; +using System.Collections.Generic; +using System.IO; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using Nncase.IR; +using Nncase.IR.Buffers; +using Nncase.IR.F; +using Nncase.IR.NN; + +namespace Nncase.Importer.Ncnn; + +public partial class NcnnImporter +{ + private Expr VisitPooling(NcnnLayer layer) + { + var poolingType = layer.ParamDict.Get(0, 0); + var kernelW = layer.ParamDict.Get(1, 0); + var kernelH = layer.ParamDict.Get(11, kernelW); + var strideW = layer.ParamDict.Get(2, 1); + var strideH = layer.ParamDict.Get(12, strideW); + var padLeft = layer.ParamDict.Get(3, 0); + var padRight = layer.ParamDict.Get(14, padLeft); + var padTop = layer.ParamDict.Get(13, padLeft); + var padBottom = layer.ParamDict.Get(15, padTop); + var globalPooling = layer.ParamDict.Get(4, 0) != 0; + var padMode = layer.ParamDict.Get(5, 0); + var avgpoolCountIncludePad = layer.ParamDict.Get(6, 0) != 0; + var adaptivePooling = layer.ParamDict.Get(7, 0) != 0; + var outW = layer.ParamDict.Get(8, 0); + var outH = layer.ParamDict.Get(18, outW); + + Expr pooling; + var input = CHWToNCHW(GetInputExprs(layer, 0)); + (var reduceOp, var initValue) = poolingType switch + { + 0 => (ReduceOp.Max, float.NegativeInfinity), + 1 => (ReduceOp.Mean, 0f), + _ => throw new NotSupportedException($"Unsupported pooling type: {poolingType}."), + }; + var filter = Tensor.From(new[] { kernelH, kernelW }, new[] { 2 }); + var stride = Tensor.From(new[] { strideH, strideW }, new[] { 2 }); + var dilation = Tensor.FromScalar(0, new[] { 2, 2 }); + + if (globalPooling) + { + pooling = Tensors.Reduce(reduceOp, input, new[] { 2, 3 }, initValue, false); + } + else if (adaptivePooling) + { + var padding = Tensor.FromScalar(0, new[] { 2, 2 }); + var inShape = Tensors.ShapeOf(input); + var w = inShape[3]; + var h = inShape[2]; + var kernelExtentH = h - outH + 1; + var kernelExtentW = w - outW + 1; + var adaptiveFilter = Tensors.Stack(new IR.Tuple(kernelExtentH, kernelExtentW), 0); + var adaptiveStride = Tensor.FromScalar(1, 2); + + pooling = NN.ReduceWindow2D(reduceOp, input, initValue, adaptiveFilter, adaptiveStride, padding, dilation, false, avgpoolCountIncludePad); + } + else + { + Expr[] paddingH; + Expr[] paddingW; + + if (padMode == 1) + { + // valid padding + paddingH = new Expr[] { padTop, padBottom }; + paddingW = new Expr[] { padLeft, padRight }; + } + else + { + var inShape = Tensors.ShapeOf(input); + var w = inShape[3]; + var h = inShape[2]; + + if (padMode == 0) + { + // full padding + var tailW = (w + padLeft + padRight - kernelW) % strideW; + var tailH = (h + padTop + padBottom - kernelH) % strideH; + + var tailPadW = IR.F.Math.Select(IR.F.Math.Equal(tailW, 0), 0, tailW); + var tailPadH = IR.F.Math.Select(IR.F.Math.Equal(tailH, 0), 0, tailH); + + paddingH = new Expr[] { padTop, padBottom + tailPadH }; + paddingW = new Expr[] { padLeft, padRight + tailPadW }; + } + else if (padMode is 2 or 3) + { + // valid padding + var padH = kernelH + ((h - 1) / strideH * strideH) - h; + var padW = kernelW + ((w - 1) / strideW * strideW) - w; + + if (padMode == 2) + { + // tensorflow padding=SAME or onnx padding=SAME_UPPER + paddingH = new Expr[] { padH / 2, padH - (padH / 2) }; + paddingW = new Expr[] { padW / 2, padW - (padW / 2) }; + } + else + { + // onnx padding=SAME_LOWER + paddingH = new Expr[] { padH - (padH / 2), padH / 2 }; + paddingW = new Expr[] { padW - (padW / 2), padW / 2 }; + } + } + else + { + throw new NotSupportedException($"Unsupported pad mode: {padMode}."); + } + } + + var padding = Util.ConcatPadding(paddingH, paddingW); + pooling = NN.ReduceWindow2D(reduceOp, input, initValue, filter, stride, padding, dilation, false, avgpoolCountIncludePad); + } + + var output = NCHWToCHW(pooling); + return output; + } +} diff --git a/src/Nncase.Importer/Ncnn/ShuffleChannel.cs b/src/Nncase.Importer/Ncnn/ShuffleChannel.cs new file mode 100644 index 0000000000..dd4f760951 --- /dev/null +++ b/src/Nncase.Importer/Ncnn/ShuffleChannel.cs @@ -0,0 +1,37 @@ +// Copyright (c) Canaan Inc. All rights reserved. +// Licensed under the Apache license. See LICENSE file in the project root for full license information. + +using System; +using System.Collections.Generic; +using System.IO; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using Nncase.IR; +using Nncase.IR.Buffers; +using Nncase.IR.F; +using Nncase.IR.NN; + +namespace Nncase.Importer.Ncnn; + +public partial class NcnnImporter +{ + private Expr VisitShuffleChannel(NcnnLayer layer) + { + var group = layer.ParamDict.Get(0, 1); + var reverse = layer.ParamDict.Get(1, 0) != 0; + + var input = GetInputExprs(layer, 0); + var inShape = Tensors.ShapeOf(input); + var channels = inShape[0]; + var h = inShape[1]; + var w = inShape[2]; + var realGroup = reverse ? channels / group : (Expr)group; + var channelsPerGroup = channels / realGroup; + + var rshape1 = Tensors.Reshape(input, Tensors.Stack(new IR.Tuple(realGroup, channelsPerGroup, h, w), 0)); + var tp = Tensors.Transpose(rshape1, new[] { 1, 0, 2, 3 }); + var output = Tensors.Reshape(tp, Tensors.Stack(new IR.Tuple(channels, h, w), 0)); + return output; + } +} diff --git a/src/Nncase.Importer/Ncnn/Softmax.cs b/src/Nncase.Importer/Ncnn/Softmax.cs new file mode 100644 index 0000000000..0e1744992b --- /dev/null +++ b/src/Nncase.Importer/Ncnn/Softmax.cs @@ -0,0 +1,27 @@ +// Copyright (c) Canaan Inc. All rights reserved. +// Licensed under the Apache license. See LICENSE file in the project root for full license information. + +using System; +using System.Collections.Generic; +using System.IO; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using Nncase.IR; +using Nncase.IR.Buffers; +using Nncase.IR.F; +using Nncase.IR.NN; + +namespace Nncase.Importer.Ncnn; + +public partial class NcnnImporter +{ + private Expr VisitSoftmax(NcnnLayer layer) + { + var axis = layer.ParamDict.Get(0, 0); + + var input = GetInputExprs(layer, 0); + var output = NN.Softmax(input, axis); + return output; + } +} diff --git a/src/Nncase.Importer/Ncnn/Split.cs b/src/Nncase.Importer/Ncnn/Split.cs new file mode 100644 index 0000000000..a6327ee653 --- /dev/null +++ b/src/Nncase.Importer/Ncnn/Split.cs @@ -0,0 +1,25 @@ +// Copyright (c) Canaan Inc. All rights reserved. +// Licensed under the Apache license. See LICENSE file in the project root for full license information. + +using System; +using System.Collections.Generic; +using System.IO; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using Nncase.IR; +using Nncase.IR.Buffers; +using Nncase.IR.F; +using Nncase.IR.NN; + +namespace Nncase.Importer.Ncnn; + +public partial class NcnnImporter +{ + private Expr VisitSplit(NcnnLayer layer) + { + var input = GetInputExprs(layer, 0); + var output = new IR.Tuple(Enumerable.Repeat(input, layer.Tops.Length).ToArray()); + return output; + } +} diff --git a/src/Nncase.Importer/packages.lock.json b/src/Nncase.Importer/packages.lock.json index e903580b70..845d535c0e 100644 --- a/src/Nncase.Importer/packages.lock.json +++ b/src/Nncase.Importer/packages.lock.json @@ -22,11 +22,11 @@ }, "StyleCop.Analyzers": { "type": "Direct", - "requested": "[1.2.0-beta.435, )", - "resolved": "1.2.0-beta.435", - "contentHash": "TADk7vdGXtfTnYCV7GyleaaRTQjfoSfZXprQrVMm7cSJtJbFc1QIbWPyLvrgrfGdfHbGmUPvaN4ODKNxg2jgPQ==", + "requested": "[1.2.0-beta.507, )", + "resolved": "1.2.0-beta.507", + "contentHash": "/FtugDT66cKJJ+GGH7rNpG6UDrT4iIWz45M6lrXXHobDUFDHw+q5VgkbiR+6ffTO564ge7w6fQh/eoQhVdJO8Q==", "dependencies": { - "StyleCop.Analyzers.Unstable": "1.2.0.435" + "StyleCop.Analyzers.Unstable": "1.2.0.507" } }, "Microsoft.Bcl.AsyncInterfaces": { @@ -85,8 +85,8 @@ }, "StyleCop.Analyzers.Unstable": { "type": "Transitive", - "resolved": "1.2.0.435", - "contentHash": "ouwPWZxbOV3SmCZxIRqHvljkSzkCyi1tDoMzQtDb/bRP8ctASV/iRJr+A2Gdj0QLaLmWnqTWDrH82/iP+X80Lg==" + "resolved": "1.2.0.507", + "contentHash": "gTY3IQdRqDJ4hbhSA3e/R48oE8b/OiKfvwkt1QdNVfrJK2gMHBV8ldaHJ885jxWZfllK66soa/sdcjh9bX49Tw==" }, "System.Buffers": { "type": "Transitive", diff --git a/src/Nncase.Passes/Rules/ShapeBucket/MergeCallToFusion.cs b/src/Nncase.Passes/Rules/ShapeBucket/MergeCallToFusion.cs index bac3b6f135..08e232585e 100644 --- a/src/Nncase.Passes/Rules/ShapeBucket/MergeCallToFusion.cs +++ b/src/Nncase.Passes/Rules/ShapeBucket/MergeCallToFusion.cs @@ -16,6 +16,7 @@ using static Nncase.Utilities.ReplaceUtility; namespace Nncase.Passes.Rules.ShapeBucket; + public abstract class MergeFusionBase : RewriteRule { protected int Counter { get; set; } diff --git a/src/Nncase.Passes/packages.lock.json b/src/Nncase.Passes/packages.lock.json index 4ceb9735d5..a910d30fa5 100644 --- a/src/Nncase.Passes/packages.lock.json +++ b/src/Nncase.Passes/packages.lock.json @@ -4,11 +4,11 @@ "net7.0": { "StyleCop.Analyzers": { "type": "Direct", - "requested": "[1.2.0-beta.435, )", - "resolved": "1.2.0-beta.435", - "contentHash": "TADk7vdGXtfTnYCV7GyleaaRTQjfoSfZXprQrVMm7cSJtJbFc1QIbWPyLvrgrfGdfHbGmUPvaN4ODKNxg2jgPQ==", + "requested": "[1.2.0-beta.507, )", + "resolved": "1.2.0-beta.507", + "contentHash": "/FtugDT66cKJJ+GGH7rNpG6UDrT4iIWz45M6lrXXHobDUFDHw+q5VgkbiR+6ffTO564ge7w6fQh/eoQhVdJO8Q==", "dependencies": { - "StyleCop.Analyzers.Unstable": "1.2.0.435" + "StyleCop.Analyzers.Unstable": "1.2.0.507" } }, "Google.OrTools.runtime.linux-arm64": { @@ -103,8 +103,8 @@ }, "StyleCop.Analyzers.Unstable": { "type": "Transitive", - "resolved": "1.2.0.435", - "contentHash": "ouwPWZxbOV3SmCZxIRqHvljkSzkCyi1tDoMzQtDb/bRP8ctASV/iRJr+A2Gdj0QLaLmWnqTWDrH82/iP+X80Lg==" + "resolved": "1.2.0.507", + "contentHash": "gTY3IQdRqDJ4hbhSA3e/R48oE8b/OiKfvwkt1QdNVfrJK2gMHBV8ldaHJ885jxWZfllK66soa/sdcjh9bX49Tw==" }, "System.Buffers": { "type": "Transitive", diff --git a/src/Nncase.Quantization/Quantization/CalibrationEvaluator.cs b/src/Nncase.Quantization/Quantization/CalibrationEvaluator.cs index d9e2a89f68..8f4096d88a 100644 --- a/src/Nncase.Quantization/Quantization/CalibrationEvaluator.cs +++ b/src/Nncase.Quantization/Quantization/CalibrationEvaluator.cs @@ -113,19 +113,9 @@ public void Dispose() }; } - private bool ShapeChecker(Shape current, Shape target) - { - if (current.Count != target.Count) - { - return false; - } - - return current.Zip(target).All(p => p.Second.IsUnknown ? true : p.Second.FixedValue == p.First.FixedValue); - } - private bool TypeChecker(IRType cur_type, IRType target_type) => (cur_type, target_type) switch { - (TensorType a, TensorType b) => a.DType == b.DType && ShapeChecker(a.Shape, b.Shape), + (TensorType a, TensorType b) => a.DType == b.DType && b.Shape.IsAssignableFrom(a.Shape), (TupleType a, TupleType b) => a.Zip(b).All(p => TypeChecker(p.First, p.Second)), (_, _) => true, }; diff --git a/src/Nncase.Quantization/packages.lock.json b/src/Nncase.Quantization/packages.lock.json index b128fc2fc3..ccc991e111 100644 --- a/src/Nncase.Quantization/packages.lock.json +++ b/src/Nncase.Quantization/packages.lock.json @@ -19,11 +19,11 @@ }, "StyleCop.Analyzers": { "type": "Direct", - "requested": "[1.2.0-beta.435, )", - "resolved": "1.2.0-beta.435", - "contentHash": "TADk7vdGXtfTnYCV7GyleaaRTQjfoSfZXprQrVMm7cSJtJbFc1QIbWPyLvrgrfGdfHbGmUPvaN4ODKNxg2jgPQ==", + "requested": "[1.2.0-beta.507, )", + "resolved": "1.2.0-beta.507", + "contentHash": "/FtugDT66cKJJ+GGH7rNpG6UDrT4iIWz45M6lrXXHobDUFDHw+q5VgkbiR+6ffTO564ge7w6fQh/eoQhVdJO8Q==", "dependencies": { - "StyleCop.Analyzers.Unstable": "1.2.0.435" + "StyleCop.Analyzers.Unstable": "1.2.0.507" } }, "System.Linq.Async": { @@ -132,8 +132,8 @@ }, "StyleCop.Analyzers.Unstable": { "type": "Transitive", - "resolved": "1.2.0.435", - "contentHash": "ouwPWZxbOV3SmCZxIRqHvljkSzkCyi1tDoMzQtDb/bRP8ctASV/iRJr+A2Gdj0QLaLmWnqTWDrH82/iP+X80Lg==" + "resolved": "1.2.0.507", + "contentHash": "gTY3IQdRqDJ4hbhSA3e/R48oE8b/OiKfvwkt1QdNVfrJK2gMHBV8ldaHJ885jxWZfllK66soa/sdcjh9bX49Tw==" }, "System.Buffers": { "type": "Transitive", diff --git a/src/Nncase.Schedule/packages.lock.json b/src/Nncase.Schedule/packages.lock.json index b3f4cb2588..93fabe1e48 100644 --- a/src/Nncase.Schedule/packages.lock.json +++ b/src/Nncase.Schedule/packages.lock.json @@ -4,11 +4,11 @@ "net7.0": { "StyleCop.Analyzers": { "type": "Direct", - "requested": "[1.2.0-beta.435, )", - "resolved": "1.2.0-beta.435", - "contentHash": "TADk7vdGXtfTnYCV7GyleaaRTQjfoSfZXprQrVMm7cSJtJbFc1QIbWPyLvrgrfGdfHbGmUPvaN4ODKNxg2jgPQ==", + "requested": "[1.2.0-beta.507, )", + "resolved": "1.2.0-beta.507", + "contentHash": "/FtugDT66cKJJ+GGH7rNpG6UDrT4iIWz45M6lrXXHobDUFDHw+q5VgkbiR+6ffTO564ge7w6fQh/eoQhVdJO8Q==", "dependencies": { - "StyleCop.Analyzers.Unstable": "1.2.0.435" + "StyleCop.Analyzers.Unstable": "1.2.0.507" } }, "Microsoft.Extensions.Configuration.Abstractions": { @@ -47,8 +47,8 @@ }, "StyleCop.Analyzers.Unstable": { "type": "Transitive", - "resolved": "1.2.0.435", - "contentHash": "ouwPWZxbOV3SmCZxIRqHvljkSzkCyi1tDoMzQtDb/bRP8ctASV/iRJr+A2Gdj0QLaLmWnqTWDrH82/iP+X80Lg==" + "resolved": "1.2.0.507", + "contentHash": "gTY3IQdRqDJ4hbhSA3e/R48oE8b/OiKfvwkt1QdNVfrJK2gMHBV8ldaHJ885jxWZfllK66soa/sdcjh9bX49Tw==" }, "System.Buffers": { "type": "Transitive", diff --git a/src/Nncase.Simulator/packages.lock.json b/src/Nncase.Simulator/packages.lock.json index b3f4cb2588..93fabe1e48 100644 --- a/src/Nncase.Simulator/packages.lock.json +++ b/src/Nncase.Simulator/packages.lock.json @@ -4,11 +4,11 @@ "net7.0": { "StyleCop.Analyzers": { "type": "Direct", - "requested": "[1.2.0-beta.435, )", - "resolved": "1.2.0-beta.435", - "contentHash": "TADk7vdGXtfTnYCV7GyleaaRTQjfoSfZXprQrVMm7cSJtJbFc1QIbWPyLvrgrfGdfHbGmUPvaN4ODKNxg2jgPQ==", + "requested": "[1.2.0-beta.507, )", + "resolved": "1.2.0-beta.507", + "contentHash": "/FtugDT66cKJJ+GGH7rNpG6UDrT4iIWz45M6lrXXHobDUFDHw+q5VgkbiR+6ffTO564ge7w6fQh/eoQhVdJO8Q==", "dependencies": { - "StyleCop.Analyzers.Unstable": "1.2.0.435" + "StyleCop.Analyzers.Unstable": "1.2.0.507" } }, "Microsoft.Extensions.Configuration.Abstractions": { @@ -47,8 +47,8 @@ }, "StyleCop.Analyzers.Unstable": { "type": "Transitive", - "resolved": "1.2.0.435", - "contentHash": "ouwPWZxbOV3SmCZxIRqHvljkSzkCyi1tDoMzQtDb/bRP8ctASV/iRJr+A2Gdj0QLaLmWnqTWDrH82/iP+X80Lg==" + "resolved": "1.2.0.507", + "contentHash": "gTY3IQdRqDJ4hbhSA3e/R48oE8b/OiKfvwkt1QdNVfrJK2gMHBV8ldaHJ885jxWZfllK66soa/sdcjh9bX49Tw==" }, "System.Buffers": { "type": "Transitive", diff --git a/src/Nncase.Targets/packages.lock.json b/src/Nncase.Targets/packages.lock.json index 5d676dd547..4a17a6364e 100644 --- a/src/Nncase.Targets/packages.lock.json +++ b/src/Nncase.Targets/packages.lock.json @@ -4,11 +4,11 @@ "net7.0": { "StyleCop.Analyzers": { "type": "Direct", - "requested": "[1.2.0-beta.435, )", - "resolved": "1.2.0-beta.435", - "contentHash": "TADk7vdGXtfTnYCV7GyleaaRTQjfoSfZXprQrVMm7cSJtJbFc1QIbWPyLvrgrfGdfHbGmUPvaN4ODKNxg2jgPQ==", + "requested": "[1.2.0-beta.507, )", + "resolved": "1.2.0-beta.507", + "contentHash": "/FtugDT66cKJJ+GGH7rNpG6UDrT4iIWz45M6lrXXHobDUFDHw+q5VgkbiR+6ffTO564ge7w6fQh/eoQhVdJO8Q==", "dependencies": { - "StyleCop.Analyzers.Unstable": "1.2.0.435" + "StyleCop.Analyzers.Unstable": "1.2.0.507" } }, "Microsoft.Extensions.Configuration.Abstractions": { @@ -47,8 +47,8 @@ }, "StyleCop.Analyzers.Unstable": { "type": "Transitive", - "resolved": "1.2.0.435", - "contentHash": "ouwPWZxbOV3SmCZxIRqHvljkSzkCyi1tDoMzQtDb/bRP8ctASV/iRJr+A2Gdj0QLaLmWnqTWDrH82/iP+X80Lg==" + "resolved": "1.2.0.507", + "contentHash": "gTY3IQdRqDJ4hbhSA3e/R48oE8b/OiKfvwkt1QdNVfrJK2gMHBV8ldaHJ885jxWZfllK66soa/sdcjh9bX49Tw==" }, "System.Buffers": { "type": "Transitive", diff --git a/src/Nncase.Tests.TestFixture/ModelRunner.cs b/src/Nncase.Tests.TestFixture/ModelRunner.cs index 76f61721ca..f11934abf0 100644 --- a/src/Nncase.Tests.TestFixture/ModelRunner.cs +++ b/src/Nncase.Tests.TestFixture/ModelRunner.cs @@ -42,9 +42,9 @@ public async Task TestRunner() CompileOptions.QuantizeOptions.UseSquant = false; CompileOptions.DumpFlags = DumpFlags.Rewrite; - using var file = File.OpenRead(ModelPath()); - CompileOptions.InputFormat = Path.GetExtension(file.Name).Trim('.'); - var m = await CompileSession.Compiler.ImportModuleAsync(file); + var modelPath = ModelPath(); + CompileOptions.InputFormat = Path.GetExtension(modelPath).Trim('.'); + var m = await CompileSession.Compiler.ImportModuleAsync(CompileOptions.InputFormat, modelPath); var types = m.Entry!.ParameterTypes.Select(type => (TensorType)type!).ToArray(); var shapes = types.Select(x => x.Shape).ToArray(); var isDynamic = shapes.Any(shape => !shape.IsFixed); diff --git a/src/Nncase.Tests.TestFixture/Nncase.Tests.TestFixture.csproj b/src/Nncase.Tests.TestFixture/Nncase.Tests.TestFixture.csproj index 3e1336e99c..18e43d118d 100644 --- a/src/Nncase.Tests.TestFixture/Nncase.Tests.TestFixture.csproj +++ b/src/Nncase.Tests.TestFixture/Nncase.Tests.TestFixture.csproj @@ -4,13 +4,15 @@ enable Nncase.Tests - + + - all - runtime; build; native; contentfiles; analyzers; buildtransitive + all + runtime; build; native; contentfiles; analyzers; buildtransitive + @@ -20,9 +22,10 @@ - + + diff --git a/src/Nncase.Tests.TestFixture/packages.lock.json b/src/Nncase.Tests.TestFixture/packages.lock.json index 13a2baae60..a7d3cc2c05 100644 --- a/src/Nncase.Tests.TestFixture/packages.lock.json +++ b/src/Nncase.Tests.TestFixture/packages.lock.json @@ -17,13 +17,22 @@ "Fody": "6.0.5" } }, + "NETStandard.Library": { + "type": "Direct", + "requested": "[2.0.3, )", + "resolved": "2.0.3", + "contentHash": "st47PosZSHrjECdjeIzZQbzivYBJFv6P2nv4cj2ypdI204DO+vZ7l5raGMiX4eXMJ53RfOIg+/s4DHVZ54Nu2A==", + "dependencies": { + "Microsoft.NETCore.Platforms": "1.1.0" + } + }, "StyleCop.Analyzers": { "type": "Direct", - "requested": "[1.2.0-beta.435, )", - "resolved": "1.2.0-beta.435", - "contentHash": "TADk7vdGXtfTnYCV7GyleaaRTQjfoSfZXprQrVMm7cSJtJbFc1QIbWPyLvrgrfGdfHbGmUPvaN4ODKNxg2jgPQ==", + "requested": "[1.2.0-beta.507, )", + "resolved": "1.2.0-beta.507", + "contentHash": "/FtugDT66cKJJ+GGH7rNpG6UDrT4iIWz45M6lrXXHobDUFDHw+q5VgkbiR+6ffTO564ge7w6fQh/eoQhVdJO8Q==", "dependencies": { - "StyleCop.Analyzers.Unstable": "1.2.0.435" + "StyleCop.Analyzers.Unstable": "1.2.0.507" } }, "System.Linq.Async": { @@ -134,12 +143,18 @@ "resolved": "6.0.0", "contentHash": "UcSjPsst+DfAdJGVDsu346FX0ci0ah+lw3WRtn18NUwEqRt70HaOQ7lI72vy3+1LxtqI3T5GWwV39rQSrCzAeg==" }, + "Microsoft.CSharp": { + "type": "Transitive", + "resolved": "4.7.0", + "contentHash": "pTj+D3uJWyN3My70i2Hqo+OXixq3Os2D1nJ2x92FFo6sk8fYS1m1WLNTs0Dc1uPaViH0YvEEwvzddQ7y4rhXmA==" + }, "Microsoft.Extensions.Configuration": { "type": "Transitive", - "resolved": "2.1.0", - "contentHash": "SS8ce1GYQTkZoOq5bskqQ+m7xiXQjnKRiGfVNZkkX2SX0HpXNRsKnSUaywRRuCje3v2KT9xeacsM3J9/G2exsQ==", + "resolved": "6.0.0", + "contentHash": "tq2wXyh3fL17EMF2bXgRhU7JrbO3on93MRKYxzz4JzzvuGSA1l0W3GI9/tl8EO89TH+KWEymP7bcFway6z9fXg==", "dependencies": { - "Microsoft.Extensions.Configuration.Abstractions": "2.1.0" + "Microsoft.Extensions.Configuration.Abstractions": "6.0.0", + "Microsoft.Extensions.Primitives": "6.0.0" } }, "Microsoft.Extensions.Configuration.Abstractions": { @@ -152,418 +167,340 @@ }, "Microsoft.Extensions.Configuration.Binder": { "type": "Transitive", - "resolved": "2.1.0", - "contentHash": "Fls0O54Ielz1DiVYpcmiUpeizN1iKGGI5yAWAoShfmUvMcQ8jAGOK1a+DaflHA5hN9IOKvmSos0yewDYAIY0ZA==", + "resolved": "6.0.0", + "contentHash": "b3ErKzND8LIC7o08QAVlKfaEIYEvLJbtmVbFZVBRXeu9YkKfSSzLZfR1SUfQPBIy9mKLhEtJgGYImkcMNaKE0A==", "dependencies": { - "Microsoft.Extensions.Configuration": "2.1.0" + "Microsoft.Extensions.Configuration.Abstractions": "6.0.0" } }, - "Microsoft.Extensions.DependencyInjection": { + "Microsoft.Extensions.Configuration.CommandLine": { "type": "Transitive", - "resolved": "2.1.0", - "contentHash": "gqQviLfuA31PheEGi+XJoZc1bc9H9RsPa9Gq9XuDct7XGWSR9eVXjK5Sg7CSUPhTFHSuxUFY12wcTYLZ4zM1hg==", + "resolved": "6.0.0", + "contentHash": "3nL1qCkZ1Oxx14ZTzgo4MmlO7tso7F+TtMZAY2jUAtTLyAcDp+EDjk3RqafoKiNaePyPvvlleEcBxh3b2Hzl1g==", "dependencies": { - "Microsoft.Extensions.DependencyInjection.Abstractions": "2.1.0" + "Microsoft.Extensions.Configuration": "6.0.0", + "Microsoft.Extensions.Configuration.Abstractions": "6.0.0" } }, - "Microsoft.Extensions.DependencyInjection.Abstractions": { + "Microsoft.Extensions.Configuration.EnvironmentVariables": { "type": "Transitive", "resolved": "6.0.0", - "contentHash": "xlzi2IYREJH3/m6+lUrQlujzX8wDitm4QGnUu6kUXTQAWPuZY8i+ticFJbzfqaetLA6KR/rO6Ew/HuYD+bxifg==" + "contentHash": "DjYkzqvhiHCq38LW71PcIxXk6nhtV6VySP9yDcSO0goPl7YCU1VG1f2Wbgy58lkA10pWkjHCblZPUyboCB93ZA==", + "dependencies": { + "Microsoft.Extensions.Configuration": "6.0.0", + "Microsoft.Extensions.Configuration.Abstractions": "6.0.0" + } }, - "Microsoft.Extensions.FileProviders.Abstractions": { + "Microsoft.Extensions.Configuration.FileExtensions": { "type": "Transitive", "resolved": "6.0.0", - "contentHash": "0pd4/fho0gC12rQswaGQxbU34jOS1TPS8lZPpkFCH68ppQjHNHYle9iRuHeev1LhrJ94YPvzcRd8UmIuFk23Qw==", + "contentHash": "V4Dth2cYMZpw3HhGw9XUDIijpI6gN+22LDt0AhufIgOppCUfpWX4483OmN+dFXRJkJLc8Tv0Q8QK+1ingT2+KQ==", "dependencies": { + "Microsoft.Extensions.Configuration": "6.0.0", + "Microsoft.Extensions.Configuration.Abstractions": "6.0.0", + "Microsoft.Extensions.FileProviders.Abstractions": "6.0.0", + "Microsoft.Extensions.FileProviders.Physical": "6.0.0", "Microsoft.Extensions.Primitives": "6.0.0" } }, - "Microsoft.Extensions.FileProviders.Physical": { + "Microsoft.Extensions.Configuration.Json": { "type": "Transitive", - "resolved": "2.1.0", - "contentHash": "A9xLomqD4tNFqDfleapx2C14ZcSjCTzn/4Od0W/wBYdlLF2tYDJ204e75HjpWDVTkr03kgdZbM3QZ6ZeDsrBYg==", + "resolved": "6.0.0", + "contentHash": "GJGery6QytCzS/BxJ96klgG9in3uH26KcUBbiVG/coNDXCRq6LGVVlUT4vXq34KPuM+R2av+LeYdX9h4IZOCUg==", "dependencies": { - "Microsoft.Extensions.FileProviders.Abstractions": "2.1.0", - "Microsoft.Extensions.FileSystemGlobbing": "2.1.0" + "Microsoft.Extensions.Configuration": "6.0.0", + "Microsoft.Extensions.Configuration.Abstractions": "6.0.0", + "Microsoft.Extensions.Configuration.FileExtensions": "6.0.0", + "Microsoft.Extensions.FileProviders.Abstractions": "6.0.0", + "System.Text.Json": "6.0.0" } }, - "Microsoft.Extensions.FileSystemGlobbing": { - "type": "Transitive", - "resolved": "2.1.0", - "contentHash": "JEwwhwbVTEXJu4W4l/FFx7FG9Fh5R8999mZl6qJImjM/LY4DxQsFYzpSkziMdY022n7TQpNUxJlH9bKZc7TqWw==" - }, - "Microsoft.Extensions.Logging": { + "Microsoft.Extensions.Configuration.UserSecrets": { "type": "Transitive", - "resolved": "2.1.0", - "contentHash": "kuZbZMMHb7ibzhLdn9/R1+PAAFKntlF10tOw4loB8VuQkHvSrBE6IzW1rhBLsEdmLXOgi2zFbwcXFrxzSM6ybA==", + "resolved": "6.0.0", + "contentHash": "lB0Hb2V4+RUHy+LjEcqEr4EcV4RWc9EnjAV2GdtWQEdljQX+R4hGREftI7sInU9okP93pDrJiaj6QUJ6ZsslOA==", "dependencies": { - "Microsoft.Extensions.Configuration.Binder": "2.1.0", - "Microsoft.Extensions.DependencyInjection.Abstractions": "2.1.0", - "Microsoft.Extensions.Logging.Abstractions": "2.1.0", - "Microsoft.Extensions.Options": "2.1.0" + "Microsoft.Extensions.Configuration.Abstractions": "6.0.0", + "Microsoft.Extensions.Configuration.Json": "6.0.0", + "Microsoft.Extensions.FileProviders.Abstractions": "6.0.0", + "Microsoft.Extensions.FileProviders.Physical": "6.0.0" } }, - "Microsoft.Extensions.Primitives": { + "Microsoft.Extensions.DependencyInjection": { "type": "Transitive", "resolved": "6.0.0", - "contentHash": "9+PnzmQFfEFNR9J2aDTfJGGupShHjOuGw4VUv+JB044biSHrnmCIMD+mJHmb2H7YryrfBEXDurxQ47gJZdCKNQ==", + "contentHash": "k6PWQMuoBDGGHOQTtyois2u4AwyVcIwL2LaSLlTZQm2CYcJ1pxbt6jfAnpWmzENA/wfrYRI/X9DTLoUkE4AsLw==", "dependencies": { + "Microsoft.Extensions.DependencyInjection.Abstractions": "6.0.0", "System.Runtime.CompilerServices.Unsafe": "6.0.0" } }, - "Microsoft.NETCore.Platforms": { - "type": "Transitive", - "resolved": "1.0.1", - "contentHash": "2G6OjjJzwBfNOO8myRV/nFrbTw5iA+DEm0N+qUqhrOmaVtn4pC77h38I1jsXGw5VH55+dPfQsqHD0We9sCl9FQ==" - }, - "Microsoft.NETCore.Targets": { + "Microsoft.Extensions.DependencyInjection.Abstractions": { "type": "Transitive", - "resolved": "1.0.1", - "contentHash": "rkn+fKobF/cbWfnnfBOQHKVKIOpxMZBvlSHkqDWgBpwGDcLRduvs3D9OLGeV6GWGvVwNlVi2CBbTjuPmtHvyNw==" + "resolved": "6.0.0", + "contentHash": "xlzi2IYREJH3/m6+lUrQlujzX8wDitm4QGnUu6kUXTQAWPuZY8i+ticFJbzfqaetLA6KR/rO6Ew/HuYD+bxifg==" }, - "Microsoft.Win32.Primitives": { + "Microsoft.Extensions.FileProviders.Abstractions": { "type": "Transitive", - "resolved": "4.0.1", - "contentHash": "fQnBHO9DgcmkC9dYSJoBqo6sH1VJwJprUHh8F3hbcRlxiQiBUuTntdk8tUwV490OqC2kQUrinGwZyQHTieuXRA==", + "resolved": "6.0.0", + "contentHash": "0pd4/fho0gC12rQswaGQxbU34jOS1TPS8lZPpkFCH68ppQjHNHYle9iRuHeev1LhrJ94YPvzcRd8UmIuFk23Qw==", "dependencies": { - "Microsoft.NETCore.Platforms": "1.0.1", - "Microsoft.NETCore.Targets": "1.0.1", - "System.Runtime": "4.1.0" + "Microsoft.Extensions.Primitives": "6.0.0" } }, - "NetFabric.Hyperlinq.Abstractions": { - "type": "Transitive", - "resolved": "1.3.0", - "contentHash": "WXnEcGwmXfa8gW9N2MlcaPNUzM3NLMwnAhacbtH554F8YcoXbIkTB+uGa1Aa+9gyb/9JZgYVHnmADgJUKP52nA==" - }, - "NETStandard.Library": { + "Microsoft.Extensions.FileProviders.Physical": { "type": "Transitive", - "resolved": "1.6.0", - "contentHash": "ypsCvIdCZ4IoYASJHt6tF2fMo7N30NLgV1EbmC+snO490OMl9FvVxmumw14rhReWU3j3g7BYudG6YCrchwHJlA==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.0.1", - "Microsoft.Win32.Primitives": "4.0.1", - "System.AppContext": "4.1.0", - "System.Collections": "4.0.11", - "System.Collections.Concurrent": "4.0.12", - "System.Console": "4.0.0", - "System.Diagnostics.Debug": "4.0.11", - "System.Diagnostics.Tools": "4.0.1", - "System.Diagnostics.Tracing": "4.1.0", - "System.Globalization": "4.0.11", - "System.Globalization.Calendars": "4.0.1", - "System.IO": "4.1.0", - "System.IO.Compression": "4.1.0", - "System.IO.Compression.ZipFile": "4.0.1", - "System.IO.FileSystem": "4.0.1", - "System.IO.FileSystem.Primitives": "4.0.1", - "System.Linq": "4.1.0", - "System.Linq.Expressions": "4.1.0", - "System.Net.Http": "4.1.0", - "System.Net.Primitives": "4.0.11", - "System.Net.Sockets": "4.1.0", - "System.ObjectModel": "4.0.12", - "System.Reflection": "4.1.0", - "System.Reflection.Extensions": "4.0.1", - "System.Reflection.Primitives": "4.0.1", - "System.Resources.ResourceManager": "4.0.1", - "System.Runtime": "4.1.0", - "System.Runtime.Extensions": "4.1.0", - "System.Runtime.Handles": "4.0.1", - "System.Runtime.InteropServices": "4.1.0", - "System.Runtime.InteropServices.RuntimeInformation": "4.0.0", - "System.Runtime.Numerics": "4.0.1", - "System.Security.Cryptography.Algorithms": "4.2.0", - "System.Security.Cryptography.Encoding": "4.0.0", - "System.Security.Cryptography.Primitives": "4.0.0", - "System.Security.Cryptography.X509Certificates": "4.1.0", - "System.Text.Encoding": "4.0.11", - "System.Text.Encoding.Extensions": "4.0.11", - "System.Text.RegularExpressions": "4.1.0", - "System.Threading": "4.0.11", - "System.Threading.Tasks": "4.0.11", - "System.Threading.Timer": "4.0.1", - "System.Xml.ReaderWriter": "4.0.11", - "System.Xml.XDocument": "4.0.11" - } - }, - "runtime.native.System": { - "type": "Transitive", - "resolved": "4.0.0", - "contentHash": "QfS/nQI7k/BLgmLrw7qm7YBoULEvgWnPI+cYsbfCVFTW8Aj+i8JhccxcFMu1RWms0YZzF+UHguNBK4Qn89e2Sg==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.0.1", - "Microsoft.NETCore.Targets": "1.0.1" - } - }, - "runtime.native.System.IO.Compression": { - "type": "Transitive", - "resolved": "4.1.0", - "contentHash": "Ob7nvnJBox1aaB222zSVZSkf4WrebPG4qFscfK7vmD7P7NxoSxACQLtO7ytWpqXDn2wcd/+45+EAZ7xjaPip8A==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.0.1", - "Microsoft.NETCore.Targets": "1.0.1" - } - }, - "runtime.native.System.Net.Http": { - "type": "Transitive", - "resolved": "4.0.1", - "contentHash": "Nh0UPZx2Vifh8r+J+H2jxifZUD3sBrmolgiFWJd2yiNrxO0xTa6bAw3YwRn1VOiSen/tUXMS31ttNItCZ6lKuA==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.0.1", - "Microsoft.NETCore.Targets": "1.0.1" - } - }, - "runtime.native.System.Security.Cryptography": { - "type": "Transitive", - "resolved": "4.0.0", - "contentHash": "2CQK0jmO6Eu7ZeMgD+LOFbNJSXHFVQbCJJkEyEwowh1SCgYnrn9W9RykMfpeeVGw7h4IBvYikzpGUlmZTUafJw==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.0.1", - "Microsoft.NETCore.Targets": "1.0.1" + "resolved": "6.0.0", + "contentHash": "QvkL7l0nM8udt3gfyu0Vw8bbCXblxaKOl7c2oBfgGy4LCURRaL9XWZX1FWJrQc43oMokVneVxH38iz+bY1sbhg==", + "dependencies": { + "Microsoft.Extensions.FileProviders.Abstractions": "6.0.0", + "Microsoft.Extensions.FileSystemGlobbing": "6.0.0", + "Microsoft.Extensions.Primitives": "6.0.0" } }, - "StyleCop.Analyzers.Unstable": { + "Microsoft.Extensions.FileSystemGlobbing": { "type": "Transitive", - "resolved": "1.2.0.435", - "contentHash": "ouwPWZxbOV3SmCZxIRqHvljkSzkCyi1tDoMzQtDb/bRP8ctASV/iRJr+A2Gdj0QLaLmWnqTWDrH82/iP+X80Lg==" + "resolved": "6.0.0", + "contentHash": "ip8jnL1aPiaPeKINCqaTEbvBFDmVx9dXQEBZ2HOBRXPD1eabGNqP/bKlsIcp7U2lGxiXd5xIhoFcmY8nM4Hdiw==" }, - "System.AppContext": { + "Microsoft.Extensions.Logging": { "type": "Transitive", - "resolved": "4.1.0", - "contentHash": "3QjO4jNV7PdKkmQAVp9atA+usVnKRwI3Kx1nMwJ93T0LcQfx7pKAYk0nKz5wn1oP5iqlhZuy6RXOFdhr7rDwow==", + "resolved": "6.0.0", + "contentHash": "eIbyj40QDg1NDz0HBW0S5f3wrLVnKWnDJ/JtZ+yJDFnDj90VoPuoPmFkeaXrtu+0cKm5GRAwoDf+dBWXK0TUdg==", "dependencies": { - "System.Runtime": "4.1.0" + "Microsoft.Extensions.DependencyInjection": "6.0.0", + "Microsoft.Extensions.DependencyInjection.Abstractions": "6.0.0", + "Microsoft.Extensions.Logging.Abstractions": "6.0.0", + "Microsoft.Extensions.Options": "6.0.0", + "System.Diagnostics.DiagnosticSource": "6.0.0" } }, - "System.Buffers": { + "Microsoft.Extensions.Logging.Configuration": { "type": "Transitive", - "resolved": "4.5.1", - "contentHash": "Rw7ijyl1qqRS0YQD/WycNst8hUUMgrMH4FCn1nNm27M4VxchZ1js3fVjQaANHO5f3sN4isvP4a+Met9Y4YomAg==" + "resolved": "6.0.0", + "contentHash": "ZDskjagmBAbv+K8rYW9VhjPplhbOE63xUD0DiuydZJwt15dRyoqicYklLd86zzeintUc7AptDkHn+YhhYkYo8A==", + "dependencies": { + "Microsoft.Extensions.Configuration": "6.0.0", + "Microsoft.Extensions.Configuration.Abstractions": "6.0.0", + "Microsoft.Extensions.Configuration.Binder": "6.0.0", + "Microsoft.Extensions.DependencyInjection.Abstractions": "6.0.0", + "Microsoft.Extensions.Logging": "6.0.0", + "Microsoft.Extensions.Logging.Abstractions": "6.0.0", + "Microsoft.Extensions.Options": "6.0.0", + "Microsoft.Extensions.Options.ConfigurationExtensions": "6.0.0" + } }, - "System.Collections": { + "Microsoft.Extensions.Logging.Console": { "type": "Transitive", - "resolved": "4.0.11", - "contentHash": "YUJGz6eFKqS0V//mLt25vFGrrCvOnsXjlvFQs+KimpwNxug9x0Pzy4PlFMU3Q2IzqAa9G2L4LsK3+9vCBK7oTg==", + "resolved": "6.0.0", + "contentHash": "gsqKzOEdsvq28QiXFxagmn1oRB9GeI5GgYCkoybZtQA0IUb7QPwf1WmN3AwJeNIsadTvIFQCiVK0OVIgKfOBGg==", "dependencies": { - "Microsoft.NETCore.Platforms": "1.0.1", - "Microsoft.NETCore.Targets": "1.0.1", - "System.Runtime": "4.1.0" + "Microsoft.Extensions.DependencyInjection.Abstractions": "6.0.0", + "Microsoft.Extensions.Logging": "6.0.0", + "Microsoft.Extensions.Logging.Abstractions": "6.0.0", + "Microsoft.Extensions.Logging.Configuration": "6.0.0", + "Microsoft.Extensions.Options": "6.0.0", + "System.Text.Json": "6.0.0" } }, - "System.Collections.Concurrent": { + "Microsoft.Extensions.Logging.Debug": { "type": "Transitive", - "resolved": "4.0.12", - "contentHash": "2gBcbb3drMLgxlI0fBfxMA31ec6AEyYCHygGse4vxceJan8mRIWeKJ24BFzN7+bi/NFTgdIgufzb94LWO5EERQ==", + "resolved": "6.0.0", + "contentHash": "M9g/JixseSZATJE9tcMn9uzoD4+DbSglivFqVx8YkRJ7VVPmnvCEbOZ0AAaxsL1EKyI4cz07DXOOJExxNsUOHw==", "dependencies": { - "System.Collections": "4.0.11", - "System.Diagnostics.Debug": "4.0.11", - "System.Diagnostics.Tracing": "4.1.0", - "System.Globalization": "4.0.11", - "System.Reflection": "4.1.0", - "System.Resources.ResourceManager": "4.0.1", - "System.Runtime": "4.1.0", - "System.Runtime.Extensions": "4.1.0", - "System.Threading": "4.0.11", - "System.Threading.Tasks": "4.0.11" + "Microsoft.Extensions.DependencyInjection.Abstractions": "6.0.0", + "Microsoft.Extensions.Logging": "6.0.0", + "Microsoft.Extensions.Logging.Abstractions": "6.0.0" } }, - "System.Collections.Immutable": { + "Microsoft.Extensions.Logging.EventLog": { "type": "Transitive", - "resolved": "7.0.0", - "contentHash": "dQPcs0U1IKnBdRDBkrCTi1FoajSTBzLcVTpjO4MBCMC7f4pDOIPzgBoX8JjG7X6uZRJ8EBxsi8+DR1JuwjnzOQ==" + "resolved": "6.0.0", + "contentHash": "rlo0RxlMd0WtLG3CHI0qOTp6fFn7MvQjlrCjucA31RqmiMFCZkF8CHNbe8O7tbBIyyoLGWB1he9CbaA5iyHthg==", + "dependencies": { + "Microsoft.Extensions.DependencyInjection.Abstractions": "6.0.0", + "Microsoft.Extensions.Logging": "6.0.0", + "Microsoft.Extensions.Logging.Abstractions": "6.0.0", + "Microsoft.Extensions.Options": "6.0.0", + "System.Diagnostics.EventLog": "6.0.0" + } }, - "System.Console": { + "Microsoft.Extensions.Logging.EventSource": { "type": "Transitive", - "resolved": "4.0.0", - "contentHash": "qSKUSOIiYA/a0g5XXdxFcUFmv1hNICBD7QZ0QhGYVipPIhvpiydY8VZqr1thmCXvmn8aipMg64zuanB4eotK9A==", + "resolved": "6.0.0", + "contentHash": "BeDyyqt7nkm/nr+Gdk+L8n1tUT/u33VkbXAOesgYSNsxDM9hJ1NOBGoZfj9rCbeD2+9myElI6JOVVFmnzgeWQA==", "dependencies": { - "Microsoft.NETCore.Platforms": "1.0.1", - "Microsoft.NETCore.Targets": "1.0.1", - "System.IO": "4.1.0", - "System.Runtime": "4.1.0", - "System.Text.Encoding": "4.0.11" + "Microsoft.Extensions.DependencyInjection.Abstractions": "6.0.0", + "Microsoft.Extensions.Logging": "6.0.0", + "Microsoft.Extensions.Logging.Abstractions": "6.0.0", + "Microsoft.Extensions.Options": "6.0.0", + "Microsoft.Extensions.Primitives": "6.0.0", + "System.Runtime.CompilerServices.Unsafe": "6.0.0", + "System.Text.Json": "6.0.0" } }, - "System.Diagnostics.Debug": { + "Microsoft.Extensions.Options.ConfigurationExtensions": { "type": "Transitive", - "resolved": "4.0.11", - "contentHash": "w5U95fVKHY4G8ASs/K5iK3J5LY+/dLFd4vKejsnI/ZhBsWS9hQakfx3Zr7lRWKg4tAw9r4iktyvsTagWkqYCiw==", + "resolved": "6.0.0", + "contentHash": "bXWINbTn0vC0FYc9GaQTISbxhQLAMrvtbuvD9N6JelEaIS/Pr62wUCinrq5bf1WRBGczt1v4wDhxFtVFNcMdUQ==", "dependencies": { - "Microsoft.NETCore.Platforms": "1.0.1", - "Microsoft.NETCore.Targets": "1.0.1", - "System.Runtime": "4.1.0" + "Microsoft.Extensions.Configuration.Abstractions": "6.0.0", + "Microsoft.Extensions.Configuration.Binder": "6.0.0", + "Microsoft.Extensions.DependencyInjection.Abstractions": "6.0.0", + "Microsoft.Extensions.Options": "6.0.0", + "Microsoft.Extensions.Primitives": "6.0.0" } }, - "System.Diagnostics.DiagnosticSource": { + "Microsoft.Extensions.Primitives": { "type": "Transitive", "resolved": "6.0.0", - "contentHash": "frQDfv0rl209cKm1lnwTgFPzNigy2EKk1BS3uAvHvlBVKe5cymGyHO+Sj+NLv5VF/AhHsqPIUUwya5oV4CHMUw==", + "contentHash": "9+PnzmQFfEFNR9J2aDTfJGGupShHjOuGw4VUv+JB044biSHrnmCIMD+mJHmb2H7YryrfBEXDurxQ47gJZdCKNQ==", "dependencies": { "System.Runtime.CompilerServices.Unsafe": "6.0.0" } }, - "System.Diagnostics.Tools": { + "Microsoft.NETCore.Platforms": { "type": "Transitive", - "resolved": "4.0.1", - "contentHash": "xBfJ8pnd4C17dWaC9FM6aShzbJcRNMChUMD42I6772KGGrqaFdumwhn9OdM68erj1ueNo3xdQ1EwiFjK5k8p0g==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.0.1", - "Microsoft.NETCore.Targets": "1.0.1", - "System.Runtime": "4.1.0" - } + "resolved": "1.1.0", + "contentHash": "kz0PEW2lhqygehI/d6XsPCQzD7ff7gUJaVGPVETX611eadGsA3A877GdSlU0LRVMCTH/+P3o2iDTak+S08V2+A==" }, - "System.Diagnostics.Tracing": { + "Microsoft.NETCore.Targets": { "type": "Transitive", - "resolved": "4.1.0", - "contentHash": "vDN1PoMZCkkdNjvZLql592oYJZgS7URcJzJ7bxeBgGtx5UtR5leNm49VmfHGqIffX4FKacHbI3H6UyNSHQknBg==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.0.1", - "Microsoft.NETCore.Targets": "1.0.1", - "System.Runtime": "4.1.0" - } + "resolved": "1.1.0", + "contentHash": "aOZA3BWfz9RXjpzt0sRJJMjAscAUm3Hoa4UWAfceV9UTYxgwZ1lZt5nO2myFf+/jetYQo4uTP7zS8sJY67BBxg==" }, - "System.Globalization": { + "NetFabric.Hyperlinq.Abstractions": { "type": "Transitive", - "resolved": "4.0.11", - "contentHash": "B95h0YLEL2oSnwF/XjqSWKnwKOy/01VWkNlsCeMTFJLLabflpGV26nK164eRs5GiaRSBGpOxQ3pKoSnnyZN5pg==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.0.1", - "Microsoft.NETCore.Targets": "1.0.1", - "System.Runtime": "4.1.0" - } + "resolved": "1.3.0", + "contentHash": "WXnEcGwmXfa8gW9N2MlcaPNUzM3NLMwnAhacbtH554F8YcoXbIkTB+uGa1Aa+9gyb/9JZgYVHnmADgJUKP52nA==" }, - "System.Globalization.Calendars": { + "StyleCop.Analyzers.Unstable": { "type": "Transitive", - "resolved": "4.0.1", - "contentHash": "L1c6IqeQ88vuzC1P81JeHmHA8mxq8a18NUBNXnIY/BVb+TCyAaGIFbhpZt60h9FJNmisymoQkHEFSE9Vslja1Q==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.0.1", - "Microsoft.NETCore.Targets": "1.0.1", - "System.Globalization": "4.0.11", - "System.Runtime": "4.1.0" - } + "resolved": "1.2.0.507", + "contentHash": "gTY3IQdRqDJ4hbhSA3e/R48oE8b/OiKfvwkt1QdNVfrJK2gMHBV8ldaHJ885jxWZfllK66soa/sdcjh9bX49Tw==" }, - "System.Globalization.Extensions": { + "System.Buffers": { "type": "Transitive", - "resolved": "4.0.1", - "contentHash": "KKo23iKeOaIg61SSXwjANN7QYDr/3op3OWGGzDzz7mypx0Za0fZSeG0l6cco8Ntp8YMYkIQcAqlk8yhm5/Uhcg==", + "resolved": "4.5.1", + "contentHash": "Rw7ijyl1qqRS0YQD/WycNst8hUUMgrMH4FCn1nNm27M4VxchZ1js3fVjQaANHO5f3sN4isvP4a+Met9Y4YomAg==" + }, + "System.Collections": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "3Dcj85/TBdVpL5Zr+gEEBUuFe2icOnLalmEh9hfck1PTYbbyWuZgh4fmm2ysCLTrqLQw6t3TgTyJ+VLp+Qb+Lw==", "dependencies": { - "Microsoft.NETCore.Platforms": "1.0.1", - "System.Globalization": "4.0.11", - "System.Resources.ResourceManager": "4.0.1", - "System.Runtime": "4.1.0", - "System.Runtime.Extensions": "4.1.0", - "System.Runtime.InteropServices": "4.1.0" + "Microsoft.NETCore.Platforms": "1.1.0", + "Microsoft.NETCore.Targets": "1.1.0", + "System.Runtime": "4.3.0" } }, - "System.IO": { + "System.Collections.Immutable": { + "type": "Transitive", + "resolved": "7.0.0", + "contentHash": "dQPcs0U1IKnBdRDBkrCTi1FoajSTBzLcVTpjO4MBCMC7f4pDOIPzgBoX8JjG7X6uZRJ8EBxsi8+DR1JuwjnzOQ==" + }, + "System.Diagnostics.Contracts": { "type": "Transitive", - "resolved": "4.1.0", - "contentHash": "3KlTJceQc3gnGIaHZ7UBZO26SHL1SHE4ddrmiwumFnId+CEHP+O8r386tZKaE6zlk5/mF8vifMBzHj9SaXN+mQ==", + "resolved": "4.3.0", + "contentHash": "eelRRbnm+OloiQvp9CXS0ixjNQldjjkHO4iIkR5XH2VIP8sUB/SIpa1TdUW6/+HDcQ+MlhP3pNa1u5SbzYuWGA==", "dependencies": { - "Microsoft.NETCore.Platforms": "1.0.1", - "Microsoft.NETCore.Targets": "1.0.1", - "System.Runtime": "4.1.0", - "System.Text.Encoding": "4.0.11", - "System.Threading.Tasks": "4.0.11" + "System.Runtime": "4.3.0" } }, - "System.IO.Compression": { + "System.Diagnostics.Debug": { "type": "Transitive", - "resolved": "4.1.0", - "contentHash": "TjnBS6eztThSzeSib+WyVbLzEdLKUcEHN69VtS3u8aAsSc18FU6xCZlNWWsEd8SKcXAE+y1sOu7VbU8sUeM0sg==", + "resolved": "4.3.0", + "contentHash": "ZUhUOdqmaG5Jk3Xdb8xi5kIyQYAA4PnTNlHx1mu9ZY3qv4ELIdKbnL/akbGaKi2RnNUWaZsAs31rvzFdewTj2g==", "dependencies": { - "Microsoft.NETCore.Platforms": "1.0.1", - "System.Collections": "4.0.11", - "System.Diagnostics.Debug": "4.0.11", - "System.IO": "4.1.0", - "System.Resources.ResourceManager": "4.0.1", - "System.Runtime": "4.1.0", - "System.Runtime.Extensions": "4.1.0", - "System.Runtime.Handles": "4.0.1", - "System.Runtime.InteropServices": "4.1.0", - "System.Text.Encoding": "4.0.11", - "System.Threading": "4.0.11", - "System.Threading.Tasks": "4.0.11", - "runtime.native.System": "4.0.0", - "runtime.native.System.IO.Compression": "4.1.0" + "Microsoft.NETCore.Platforms": "1.1.0", + "Microsoft.NETCore.Targets": "1.1.0", + "System.Runtime": "4.3.0" } }, - "System.IO.Compression.ZipFile": { + "System.Diagnostics.DiagnosticSource": { "type": "Transitive", - "resolved": "4.0.1", - "contentHash": "hBQYJzfTbQURF10nLhd+az2NHxsU6MU7AB8RUf4IolBP5lOAm4Luho851xl+CqslmhI5ZH/el8BlngEk4lBkaQ==", + "resolved": "6.0.0", + "contentHash": "frQDfv0rl209cKm1lnwTgFPzNigy2EKk1BS3uAvHvlBVKe5cymGyHO+Sj+NLv5VF/AhHsqPIUUwya5oV4CHMUw==", "dependencies": { - "System.Buffers": "4.0.0", - "System.IO": "4.1.0", - "System.IO.Compression": "4.1.0", - "System.IO.FileSystem": "4.0.1", - "System.IO.FileSystem.Primitives": "4.0.1", - "System.Resources.ResourceManager": "4.0.1", - "System.Runtime": "4.1.0", - "System.Runtime.Extensions": "4.1.0", - "System.Text.Encoding": "4.0.11" + "System.Runtime.CompilerServices.Unsafe": "6.0.0" } }, - "System.IO.FileSystem": { + "System.Diagnostics.EventLog": { "type": "Transitive", - "resolved": "4.0.1", - "contentHash": "IBErlVq5jOggAD69bg1t0pJcHaDbJbWNUZTPI96fkYWzwYbN6D9wRHMULLDd9dHsl7C2YsxXL31LMfPI1SWt8w==", + "resolved": "6.0.0", + "contentHash": "lcyUiXTsETK2ALsZrX+nWuHSIQeazhqPphLfaRxzdGaG93+0kELqpgEHtwWOlQe7+jSFnKwaCAgL4kjeZCQJnw==" + }, + "System.Globalization": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "kYdVd2f2PAdFGblzFswE4hkNANJBKRmsfa2X5LG2AcWE1c7/4t0pYae1L8vfZ5xvE2nK/R9JprtToA61OSHWIg==", "dependencies": { - "Microsoft.NETCore.Platforms": "1.0.1", - "Microsoft.NETCore.Targets": "1.0.1", - "System.IO": "4.1.0", - "System.IO.FileSystem.Primitives": "4.0.1", - "System.Runtime": "4.1.0", - "System.Runtime.Handles": "4.0.1", - "System.Text.Encoding": "4.0.11", - "System.Threading.Tasks": "4.0.11" + "Microsoft.NETCore.Platforms": "1.1.0", + "Microsoft.NETCore.Targets": "1.1.0", + "System.Runtime": "4.3.0" } }, - "System.IO.FileSystem.Primitives": { + "System.IO": { "type": "Transitive", - "resolved": "4.0.1", - "contentHash": "kWkKD203JJKxJeE74p8aF8y4Qc9r9WQx4C0cHzHPrY3fv/L/IhWnyCHaFJ3H1QPOH6A93whlQ2vG5nHlBDvzWQ==", + "resolved": "4.3.0", + "contentHash": "3qjaHvxQPDpSOYICjUoTsmoq5u6QJAFRUITgeT/4gqkF1bajbSmb1kwSxEA8AHlofqgcKJcM8udgieRNhaJ5Cg==", "dependencies": { - "System.Runtime": "4.1.0" + "Microsoft.NETCore.Platforms": "1.1.0", + "Microsoft.NETCore.Targets": "1.1.0", + "System.Runtime": "4.3.0", + "System.Text.Encoding": "4.3.0", + "System.Threading.Tasks": "4.3.0" } }, "System.Linq": { "type": "Transitive", - "resolved": "4.1.0", - "contentHash": "bQ0iYFOQI0nuTnt+NQADns6ucV4DUvMdwN6CbkB1yj8i7arTGiTN5eok1kQwdnnNWSDZfIUySQY+J3d5KjWn0g==", + "resolved": "4.3.0", + "contentHash": "5DbqIUpsDp0dFftytzuMmc0oeMdQwjcP/EWxsksIz/w1TcFRkZ3yKKz0PqiYFMmEwPSWw+qNVqD7PJ889JzHbw==", "dependencies": { - "System.Collections": "4.0.11", - "System.Diagnostics.Debug": "4.0.11", - "System.Resources.ResourceManager": "4.0.1", - "System.Runtime": "4.1.0", - "System.Runtime.Extensions": "4.1.0" + "System.Collections": "4.3.0", + "System.Diagnostics.Debug": "4.3.0", + "System.Resources.ResourceManager": "4.3.0", + "System.Runtime": "4.3.0", + "System.Runtime.Extensions": "4.3.0" } }, "System.Linq.Expressions": { "type": "Transitive", - "resolved": "4.1.0", - "contentHash": "I+y02iqkgmCAyfbqOmSDOgqdZQ5tTj80Akm5BPSS8EeB0VGWdy6X1KCoYe8Pk6pwDoAKZUOdLVxnTJcExiv5zw==", - "dependencies": { - "System.Collections": "4.0.11", - "System.Diagnostics.Debug": "4.0.11", - "System.Globalization": "4.0.11", - "System.IO": "4.1.0", - "System.Linq": "4.1.0", - "System.ObjectModel": "4.0.12", - "System.Reflection": "4.1.0", - "System.Reflection.Emit": "4.0.1", - "System.Reflection.Emit.ILGeneration": "4.0.1", - "System.Reflection.Emit.Lightweight": "4.0.1", - "System.Reflection.Extensions": "4.0.1", - "System.Reflection.Primitives": "4.0.1", - "System.Reflection.TypeExtensions": "4.1.0", - "System.Resources.ResourceManager": "4.0.1", - "System.Runtime": "4.1.0", - "System.Runtime.Extensions": "4.1.0", - "System.Threading": "4.0.11" + "resolved": "4.3.0", + "contentHash": "PGKkrd2khG4CnlyJwxwwaWWiSiWFNBGlgXvJpeO0xCXrZ89ODrQ6tjEWS/kOqZ8GwEOUATtKtzp1eRgmYNfclg==", + "dependencies": { + "System.Collections": "4.3.0", + "System.Diagnostics.Debug": "4.3.0", + "System.Globalization": "4.3.0", + "System.IO": "4.3.0", + "System.Linq": "4.3.0", + "System.ObjectModel": "4.3.0", + "System.Reflection": "4.3.0", + "System.Reflection.Emit": "4.3.0", + "System.Reflection.Emit.ILGeneration": "4.3.0", + "System.Reflection.Emit.Lightweight": "4.3.0", + "System.Reflection.Extensions": "4.3.0", + "System.Reflection.Primitives": "4.3.0", + "System.Reflection.TypeExtensions": "4.3.0", + "System.Resources.ResourceManager": "4.3.0", + "System.Runtime": "4.3.0", + "System.Runtime.Extensions": "4.3.0", + "System.Threading": "4.3.0" + } + }, + "System.Linq.Queryable": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "In1Bmmvl/j52yPu3xgakQSI0YIckPUr870w4K5+Lak3JCCa8hl+my65lABOuKfYs4ugmZy25ScFerC4nz8+b6g==", + "dependencies": { + "System.Collections": "4.3.0", + "System.Diagnostics.Debug": "4.3.0", + "System.Linq": "4.3.0", + "System.Linq.Expressions": "4.3.0", + "System.Reflection": "4.3.0", + "System.Reflection.Extensions": "4.3.0", + "System.Resources.ResourceManager": "4.3.0", + "System.Runtime": "4.3.0" } }, "System.Memory": { @@ -571,169 +508,112 @@ "resolved": "4.5.5", "contentHash": "XIWiDvKPXaTveaB7HVganDlOCRoj03l+jrwNvcge/t8vhGYKvqV+dMv6G4SAX2NoNmN0wZfVPTAlFwZcZvVOUw==" }, - "System.Net.Http": { - "type": "Transitive", - "resolved": "4.1.0", - "contentHash": "ULq9g3SOPVuupt+Y3U+A37coXzdNisB1neFCSKzBwo182u0RDddKJF8I5+HfyXqK6OhJPgeoAwWXrbiUXuRDsg==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.0.1", - "System.Collections": "4.0.11", - "System.Diagnostics.Debug": "4.0.11", - "System.Diagnostics.DiagnosticSource": "4.0.0", - "System.Diagnostics.Tracing": "4.1.0", - "System.Globalization": "4.0.11", - "System.Globalization.Extensions": "4.0.1", - "System.IO": "4.1.0", - "System.IO.FileSystem": "4.0.1", - "System.Net.Primitives": "4.0.11", - "System.Resources.ResourceManager": "4.0.1", - "System.Runtime": "4.1.0", - "System.Runtime.Extensions": "4.1.0", - "System.Runtime.Handles": "4.0.1", - "System.Runtime.InteropServices": "4.1.0", - "System.Security.Cryptography.Algorithms": "4.2.0", - "System.Security.Cryptography.Encoding": "4.0.0", - "System.Security.Cryptography.OpenSsl": "4.0.0", - "System.Security.Cryptography.Primitives": "4.0.0", - "System.Security.Cryptography.X509Certificates": "4.1.0", - "System.Text.Encoding": "4.0.11", - "System.Threading": "4.0.11", - "System.Threading.Tasks": "4.0.11", - "runtime.native.System": "4.0.0", - "runtime.native.System.Net.Http": "4.0.1", - "runtime.native.System.Security.Cryptography": "4.0.0" - } - }, - "System.Net.Primitives": { - "type": "Transitive", - "resolved": "4.0.11", - "contentHash": "hVvfl4405DRjA2408luZekbPhplJK03j2Y2lSfMlny7GHXlkByw1iLnc9mgKW0GdQn73vvMcWrWewAhylXA4Nw==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.0.1", - "Microsoft.NETCore.Targets": "1.0.1", - "System.Runtime": "4.1.0", - "System.Runtime.Handles": "4.0.1" - } - }, - "System.Net.Sockets": { - "type": "Transitive", - "resolved": "4.1.0", - "contentHash": "xAz0N3dAV/aR/9g8r0Y5oEqU1JRsz29F5EGb/WVHmX3jVSLqi2/92M5hTad2aNWovruXrJpJtgZ9fccPMG9uSw==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.0.1", - "Microsoft.NETCore.Targets": "1.0.1", - "System.IO": "4.1.0", - "System.Net.Primitives": "4.0.11", - "System.Runtime": "4.1.0", - "System.Threading.Tasks": "4.0.11" - } - }, "System.ObjectModel": { "type": "Transitive", - "resolved": "4.0.12", - "contentHash": "tAgJM1xt3ytyMoW4qn4wIqgJYm7L7TShRZG4+Q4Qsi2PCcj96pXN7nRywS9KkB3p/xDUjc2HSwP9SROyPYDYKQ==", + "resolved": "4.3.0", + "contentHash": "bdX+80eKv9bN6K4N+d77OankKHGn6CH711a6fcOpMQu2Fckp/Ft4L/kW9WznHpyR0NRAvJutzOMHNNlBGvxQzQ==", "dependencies": { - "System.Collections": "4.0.11", - "System.Diagnostics.Debug": "4.0.11", - "System.Resources.ResourceManager": "4.0.1", - "System.Runtime": "4.1.0", - "System.Threading": "4.0.11" + "System.Collections": "4.3.0", + "System.Diagnostics.Debug": "4.3.0", + "System.Resources.ResourceManager": "4.3.0", + "System.Runtime": "4.3.0", + "System.Threading": "4.3.0" } }, "System.Reflection": { "type": "Transitive", - "resolved": "4.1.0", - "contentHash": "JCKANJ0TI7kzoQzuwB/OoJANy1Lg338B6+JVacPl4TpUwi3cReg3nMLplMq2uqYfHFQpKIlHAUVAJlImZz/4ng==", + "resolved": "4.3.0", + "contentHash": "KMiAFoW7MfJGa9nDFNcfu+FpEdiHpWgTcS2HdMpDvt9saK3y/G4GwprPyzqjFH9NTaGPQeWNHU+iDlDILj96aQ==", "dependencies": { - "Microsoft.NETCore.Platforms": "1.0.1", - "Microsoft.NETCore.Targets": "1.0.1", - "System.IO": "4.1.0", - "System.Reflection.Primitives": "4.0.1", - "System.Runtime": "4.1.0" + "Microsoft.NETCore.Platforms": "1.1.0", + "Microsoft.NETCore.Targets": "1.1.0", + "System.IO": "4.3.0", + "System.Reflection.Primitives": "4.3.0", + "System.Runtime": "4.3.0" } }, "System.Reflection.Emit": { "type": "Transitive", - "resolved": "4.0.1", - "contentHash": "P2wqAj72fFjpP6wb9nSfDqNBMab+2ovzSDzUZK7MVIm54tBJEPr9jWfSjjoTpPwj1LeKcmX3vr0ttyjSSFM47g==", + "resolved": "4.3.0", + "contentHash": "228FG0jLcIwTVJyz8CLFKueVqQK36ANazUManGaJHkO0icjiIypKW7YLWLIWahyIkdh5M7mV2dJepllLyA1SKg==", "dependencies": { - "System.IO": "4.1.0", - "System.Reflection": "4.1.0", - "System.Reflection.Emit.ILGeneration": "4.0.1", - "System.Reflection.Primitives": "4.0.1", - "System.Runtime": "4.1.0" + "System.IO": "4.3.0", + "System.Reflection": "4.3.0", + "System.Reflection.Emit.ILGeneration": "4.3.0", + "System.Reflection.Primitives": "4.3.0", + "System.Runtime": "4.3.0" } }, "System.Reflection.Emit.ILGeneration": { "type": "Transitive", - "resolved": "4.0.1", - "contentHash": "Ov6dU8Bu15Bc7zuqttgHF12J5lwSWyTf1S+FJouUXVMSqImLZzYaQ+vRr1rQ0OZ0HqsrwWl4dsKHELckQkVpgA==", + "resolved": "4.3.0", + "contentHash": "59tBslAk9733NXLrUJrwNZEzbMAcu8k344OYo+wfSVygcgZ9lgBdGIzH/nrg3LYhXceynyvTc8t5/GD4Ri0/ng==", "dependencies": { - "System.Reflection": "4.1.0", - "System.Reflection.Primitives": "4.0.1", - "System.Runtime": "4.1.0" + "System.Reflection": "4.3.0", + "System.Reflection.Primitives": "4.3.0", + "System.Runtime": "4.3.0" } }, "System.Reflection.Emit.Lightweight": { "type": "Transitive", - "resolved": "4.0.1", - "contentHash": "sSzHHXueZ5Uh0OLpUQprhr+ZYJrLPA2Cmr4gn0wj9+FftNKXx8RIMKvO9qnjk2ebPYUjZ+F2ulGdPOsvj+MEjA==", + "resolved": "4.3.0", + "contentHash": "oadVHGSMsTmZsAF864QYN1t1QzZjIcuKU3l2S9cZOwDdDueNTrqq1yRj7koFfIGEnKpt6NjpL3rOzRhs4ryOgA==", "dependencies": { - "System.Reflection": "4.1.0", - "System.Reflection.Emit.ILGeneration": "4.0.1", - "System.Reflection.Primitives": "4.0.1", - "System.Runtime": "4.1.0" + "System.Reflection": "4.3.0", + "System.Reflection.Emit.ILGeneration": "4.3.0", + "System.Reflection.Primitives": "4.3.0", + "System.Runtime": "4.3.0" } }, "System.Reflection.Extensions": { "type": "Transitive", - "resolved": "4.0.1", - "contentHash": "GYrtRsZcMuHF3sbmRHfMYpvxZoIN2bQGrYGerUiWLEkqdEUQZhH3TRSaC/oI4wO0II1RKBPlpIa1TOMxIcOOzQ==", + "resolved": "4.3.0", + "contentHash": "rJkrJD3kBI5B712aRu4DpSIiHRtr6QlfZSQsb0hYHrDCZORXCFjQfoipo2LaMUHoT9i1B7j7MnfaEKWDFmFQNQ==", "dependencies": { - "Microsoft.NETCore.Platforms": "1.0.1", - "Microsoft.NETCore.Targets": "1.0.1", - "System.Reflection": "4.1.0", - "System.Runtime": "4.1.0" + "Microsoft.NETCore.Platforms": "1.1.0", + "Microsoft.NETCore.Targets": "1.1.0", + "System.Reflection": "4.3.0", + "System.Runtime": "4.3.0" } }, "System.Reflection.Primitives": { "type": "Transitive", - "resolved": "4.0.1", - "contentHash": "4inTox4wTBaDhB7V3mPvp9XlCbeGYWVEM9/fXALd52vNEAVisc1BoVWQPuUuD0Ga//dNbA/WeMy9u9mzLxGTHQ==", + "resolved": "4.3.0", + "contentHash": "5RXItQz5As4xN2/YUDxdpsEkMhvw3e6aNveFXUn4Hl/udNTCNhnKp8lT9fnc3MhvGKh1baak5CovpuQUXHAlIA==", "dependencies": { - "Microsoft.NETCore.Platforms": "1.0.1", - "Microsoft.NETCore.Targets": "1.0.1", - "System.Runtime": "4.1.0" + "Microsoft.NETCore.Platforms": "1.1.0", + "Microsoft.NETCore.Targets": "1.1.0", + "System.Runtime": "4.3.0" } }, "System.Reflection.TypeExtensions": { "type": "Transitive", - "resolved": "4.1.0", - "contentHash": "tsQ/ptQ3H5FYfON8lL4MxRk/8kFyE0A+tGPXmVP967cT/gzLHYxIejIYSxp4JmIeFHVP78g/F2FE1mUUTbDtrg==", + "resolved": "4.3.0", + "contentHash": "7u6ulLcZbyxB5Gq0nMkQttcdBTx57ibzw+4IOXEfR+sXYQoHvjW5LTLyNr8O22UIMrqYbchJQJnos4eooYzYJA==", "dependencies": { - "System.Reflection": "4.1.0", - "System.Runtime": "4.1.0" + "System.Reflection": "4.3.0", + "System.Runtime": "4.3.0" } }, "System.Resources.ResourceManager": { "type": "Transitive", - "resolved": "4.0.1", - "contentHash": "TxwVeUNoTgUOdQ09gfTjvW411MF+w9MBYL7AtNVc+HtBCFlutPLhUCdZjNkjbhj3bNQWMdHboF0KIWEOjJssbA==", + "resolved": "4.3.0", + "contentHash": "/zrcPkkWdZmI4F92gL/TPumP98AVDu/Wxr3CSJGQQ+XN6wbRZcyfSKVoPo17ilb3iOr0cCRqJInGwNMolqhS8A==", "dependencies": { - "Microsoft.NETCore.Platforms": "1.0.1", - "Microsoft.NETCore.Targets": "1.0.1", - "System.Globalization": "4.0.11", - "System.Reflection": "4.1.0", - "System.Runtime": "4.1.0" + "Microsoft.NETCore.Platforms": "1.1.0", + "Microsoft.NETCore.Targets": "1.1.0", + "System.Globalization": "4.3.0", + "System.Reflection": "4.3.0", + "System.Runtime": "4.3.0" } }, "System.Runtime": { "type": "Transitive", - "resolved": "4.1.0", - "contentHash": "v6c/4Yaa9uWsq+JMhnOFewrYkgdNHNG2eMKuNqRn8P733rNXeRCGvV5FkkjBXn2dbVkPXOsO0xjsEeM1q2zC0g==", + "resolved": "4.3.0", + "contentHash": "JufQi0vPQ0xGnAczR13AUFglDyVYt4Kqnz1AZaiKZ5+GICq0/1MH/mO/eAJHt/mHW1zjKBJd7kV26SrxddAhiw==", "dependencies": { - "Microsoft.NETCore.Platforms": "1.0.1", - "Microsoft.NETCore.Targets": "1.0.1" + "Microsoft.NETCore.Platforms": "1.1.0", + "Microsoft.NETCore.Targets": "1.1.0" } }, "System.Runtime.CompilerServices.Unsafe": { @@ -743,256 +623,58 @@ }, "System.Runtime.Extensions": { "type": "Transitive", - "resolved": "4.1.0", - "contentHash": "CUOHjTT/vgP0qGW22U4/hDlOqXmcPq5YicBaXdUR2UiUoLwBT+olO6we4DVbq57jeX5uXH2uerVZhf0qGj+sVQ==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.0.1", - "Microsoft.NETCore.Targets": "1.0.1", - "System.Runtime": "4.1.0" - } - }, - "System.Runtime.Handles": { - "type": "Transitive", - "resolved": "4.0.1", - "contentHash": "nCJvEKguXEvk2ymk1gqj625vVnlK3/xdGzx0vOKicQkoquaTBJTP13AIYkocSUwHCLNBwUbXTqTWGDxBTWpt7g==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.0.1", - "Microsoft.NETCore.Targets": "1.0.1", - "System.Runtime": "4.1.0" - } - }, - "System.Runtime.InteropServices": { - "type": "Transitive", - "resolved": "4.1.0", - "contentHash": "16eu3kjHS633yYdkjwShDHZLRNMKVi/s0bY8ODiqJ2RfMhDMAwxZaUaWVnZ2P71kr/or+X9o/xFWtNqz8ivieQ==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.0.1", - "Microsoft.NETCore.Targets": "1.0.1", - "System.Reflection": "4.1.0", - "System.Reflection.Primitives": "4.0.1", - "System.Runtime": "4.1.0", - "System.Runtime.Handles": "4.0.1" - } - }, - "System.Runtime.InteropServices.RuntimeInformation": { - "type": "Transitive", - "resolved": "4.0.0", - "contentHash": "hWPhJxc453RCa8Z29O91EmfGeZIHX1ZH2A8L6lYQVSaKzku2DfArSfMEb1/MYYzPQRJZeu0c9dmYeJKxW5Fgng==", + "resolved": "4.3.0", + "contentHash": "guW0uK0fn5fcJJ1tJVXYd7/1h5F+pea1r7FLSOz/f8vPEqbR2ZAknuRDvTQ8PzAilDveOxNjSfr0CHfIQfFk8g==", "dependencies": { - "Microsoft.NETCore.Platforms": "1.0.1", - "System.Reflection": "4.1.0", - "System.Resources.ResourceManager": "4.0.1", - "System.Runtime": "4.1.0", - "System.Runtime.InteropServices": "4.1.0", - "System.Threading": "4.0.11", - "runtime.native.System": "4.0.0" - } - }, - "System.Runtime.Numerics": { - "type": "Transitive", - "resolved": "4.0.1", - "contentHash": "+XbKFuzdmLP3d1o9pdHu2nxjNr2OEPqGzKeegPLCUMM71a0t50A/rOcIRmGs9wR7a8KuHX6hYs/7/TymIGLNqg==", - "dependencies": { - "System.Globalization": "4.0.11", - "System.Resources.ResourceManager": "4.0.1", - "System.Runtime": "4.1.0", - "System.Runtime.Extensions": "4.1.0" - } - }, - "System.Security.Cryptography.Algorithms": { - "type": "Transitive", - "resolved": "4.2.0", - "contentHash": "8JQFxbLVdrtIOKMDN38Fn0GWnqYZw/oMlwOUG/qz1jqChvyZlnUmu+0s7wLx7JYua/nAXoESpHA3iw11QFWhXg==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.0.1", - "System.Collections": "4.0.11", - "System.IO": "4.1.0", - "System.Resources.ResourceManager": "4.0.1", - "System.Runtime": "4.1.0", - "System.Runtime.Extensions": "4.1.0", - "System.Runtime.Handles": "4.0.1", - "System.Runtime.InteropServices": "4.1.0", - "System.Runtime.Numerics": "4.0.1", - "System.Security.Cryptography.Encoding": "4.0.0", - "System.Security.Cryptography.Primitives": "4.0.0", - "System.Text.Encoding": "4.0.11", - "runtime.native.System.Security.Cryptography": "4.0.0" - } - }, - "System.Security.Cryptography.Cng": { - "type": "Transitive", - "resolved": "4.2.0", - "contentHash": "cUJ2h+ZvONDe28Szw3st5dOHdjndhJzQ2WObDEXAWRPEQBtVItVoxbXM/OEsTthl3cNn2dk2k0I3y45igCQcLw==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.0.1", - "System.IO": "4.1.0", - "System.Resources.ResourceManager": "4.0.1", - "System.Runtime": "4.1.0", - "System.Runtime.Extensions": "4.1.0", - "System.Runtime.Handles": "4.0.1", - "System.Runtime.InteropServices": "4.1.0", - "System.Security.Cryptography.Algorithms": "4.2.0", - "System.Security.Cryptography.Encoding": "4.0.0", - "System.Security.Cryptography.Primitives": "4.0.0", - "System.Text.Encoding": "4.0.11" - } - }, - "System.Security.Cryptography.Csp": { - "type": "Transitive", - "resolved": "4.0.0", - "contentHash": "/i1Usuo4PgAqgbPNC0NjbO3jPW//BoBlTpcWFD1EHVbidH21y4c1ap5bbEMSGAXjAShhMH4abi/K8fILrnu4BQ==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.0.1", - "System.IO": "4.1.0", - "System.Reflection": "4.1.0", - "System.Resources.ResourceManager": "4.0.1", - "System.Runtime": "4.1.0", - "System.Runtime.Extensions": "4.1.0", - "System.Runtime.Handles": "4.0.1", - "System.Runtime.InteropServices": "4.1.0", - "System.Security.Cryptography.Algorithms": "4.2.0", - "System.Security.Cryptography.Encoding": "4.0.0", - "System.Security.Cryptography.Primitives": "4.0.0", - "System.Text.Encoding": "4.0.11", - "System.Threading": "4.0.11" - } - }, - "System.Security.Cryptography.Encoding": { - "type": "Transitive", - "resolved": "4.0.0", - "contentHash": "FbKgE5MbxSQMPcSVRgwM6bXN3GtyAh04NkV8E5zKCBE26X0vYW0UtTa2FIgkH33WVqBVxRgxljlVYumWtU+HcQ==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.0.1", - "System.Collections": "4.0.11", - "System.Collections.Concurrent": "4.0.12", - "System.Linq": "4.1.0", - "System.Resources.ResourceManager": "4.0.1", - "System.Runtime": "4.1.0", - "System.Runtime.Extensions": "4.1.0", - "System.Runtime.Handles": "4.0.1", - "System.Runtime.InteropServices": "4.1.0", - "System.Security.Cryptography.Primitives": "4.0.0", - "System.Text.Encoding": "4.0.11", - "runtime.native.System.Security.Cryptography": "4.0.0" - } - }, - "System.Security.Cryptography.OpenSsl": { - "type": "Transitive", - "resolved": "4.0.0", - "contentHash": "HUG/zNUJwEiLkoURDixzkzZdB5yGA5pQhDP93ArOpDPQMteURIGERRNzzoJlmTreLBWr5lkFSjjMSk8ySEpQMw==", - "dependencies": { - "System.Collections": "4.0.11", - "System.IO": "4.1.0", - "System.Resources.ResourceManager": "4.0.1", - "System.Runtime": "4.1.0", - "System.Runtime.Extensions": "4.1.0", - "System.Runtime.Handles": "4.0.1", - "System.Runtime.InteropServices": "4.1.0", - "System.Runtime.Numerics": "4.0.1", - "System.Security.Cryptography.Algorithms": "4.2.0", - "System.Security.Cryptography.Encoding": "4.0.0", - "System.Security.Cryptography.Primitives": "4.0.0", - "System.Text.Encoding": "4.0.11", - "runtime.native.System.Security.Cryptography": "4.0.0" - } - }, - "System.Security.Cryptography.Primitives": { - "type": "Transitive", - "resolved": "4.0.0", - "contentHash": "Wkd7QryWYjkQclX0bngpntW5HSlMzeJU24UaLJQ7YTfI8ydAVAaU2J+HXLLABOVJlKTVvAeL0Aj39VeTe7L+oA==", - "dependencies": { - "System.Diagnostics.Debug": "4.0.11", - "System.Globalization": "4.0.11", - "System.IO": "4.1.0", - "System.Resources.ResourceManager": "4.0.1", - "System.Runtime": "4.1.0", - "System.Threading": "4.0.11", - "System.Threading.Tasks": "4.0.11" - } - }, - "System.Security.Cryptography.X509Certificates": { - "type": "Transitive", - "resolved": "4.1.0", - "contentHash": "4HEfsQIKAhA1+ApNn729Gi09zh+lYWwyIuViihoMDWp1vQnEkL2ct7mAbhBlLYm+x/L4Rr/pyGge1lIY635e0w==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.0.1", - "System.Collections": "4.0.11", - "System.Diagnostics.Debug": "4.0.11", - "System.Globalization": "4.0.11", - "System.Globalization.Calendars": "4.0.1", - "System.IO": "4.1.0", - "System.IO.FileSystem": "4.0.1", - "System.IO.FileSystem.Primitives": "4.0.1", - "System.Resources.ResourceManager": "4.0.1", - "System.Runtime": "4.1.0", - "System.Runtime.Extensions": "4.1.0", - "System.Runtime.Handles": "4.0.1", - "System.Runtime.InteropServices": "4.1.0", - "System.Runtime.Numerics": "4.0.1", - "System.Security.Cryptography.Algorithms": "4.2.0", - "System.Security.Cryptography.Cng": "4.2.0", - "System.Security.Cryptography.Csp": "4.0.0", - "System.Security.Cryptography.Encoding": "4.0.0", - "System.Security.Cryptography.OpenSsl": "4.0.0", - "System.Security.Cryptography.Primitives": "4.0.0", - "System.Text.Encoding": "4.0.11", - "System.Threading": "4.0.11", - "runtime.native.System": "4.0.0", - "runtime.native.System.Net.Http": "4.0.1", - "runtime.native.System.Security.Cryptography": "4.0.0" + "Microsoft.NETCore.Platforms": "1.1.0", + "Microsoft.NETCore.Targets": "1.1.0", + "System.Runtime": "4.3.0" } }, "System.Text.Encoding": { "type": "Transitive", - "resolved": "4.0.11", - "contentHash": "U3gGeMlDZXxCEiY4DwVLSacg+DFWCvoiX+JThA/rvw37Sqrku7sEFeVBBBMBnfB6FeZHsyDx85HlKL19x0HtZA==", + "resolved": "4.3.0", + "contentHash": "BiIg+KWaSDOITze6jGQynxg64naAPtqGHBwDrLaCtixsa5bKiR8dpPOHA7ge3C0JJQizJE+sfkz1wV+BAKAYZw==", "dependencies": { - "Microsoft.NETCore.Platforms": "1.0.1", - "Microsoft.NETCore.Targets": "1.0.1", - "System.Runtime": "4.1.0" + "Microsoft.NETCore.Platforms": "1.1.0", + "Microsoft.NETCore.Targets": "1.1.0", + "System.Runtime": "4.3.0" } }, - "System.Text.Encoding.Extensions": { + "System.Text.Encodings.Web": { "type": "Transitive", - "resolved": "4.0.11", - "contentHash": "jtbiTDtvfLYgXn8PTfWI+SiBs51rrmO4AAckx4KR6vFK9Wzf6tI8kcRdsYQNwriUeQ1+CtQbM1W4cMbLXnj/OQ==", + "resolved": "6.0.0", + "contentHash": "Vg8eB5Tawm1IFqj4TVK1czJX89rhFxJo9ELqc/Eiq0eXy13RK00eubyU6TJE6y+GQXjyV5gSfiewDUZjQgSE0w==", "dependencies": { - "Microsoft.NETCore.Platforms": "1.0.1", - "Microsoft.NETCore.Targets": "1.0.1", - "System.Runtime": "4.1.0", - "System.Text.Encoding": "4.0.11" + "System.Runtime.CompilerServices.Unsafe": "6.0.0" } }, - "System.Text.RegularExpressions": { + "System.Text.Json": { "type": "Transitive", - "resolved": "4.1.0", - "contentHash": "i88YCXpRTjCnoSQZtdlHkAOx4KNNik4hMy83n0+Ftlb7jvV6ZiZWMpnEZHhjBp6hQVh8gWd/iKNPzlPF7iyA2g==", + "resolved": "6.0.0", + "contentHash": "zaJsHfESQvJ11vbXnNlkrR46IaMULk/gHxYsJphzSF+07kTjPHv+Oc14w6QEOfo3Q4hqLJgStUaYB9DBl0TmWg==", "dependencies": { - "System.Collections": "4.0.11", - "System.Globalization": "4.0.11", - "System.Resources.ResourceManager": "4.0.1", - "System.Runtime": "4.1.0", - "System.Runtime.Extensions": "4.1.0", - "System.Threading": "4.0.11" + "System.Runtime.CompilerServices.Unsafe": "6.0.0", + "System.Text.Encodings.Web": "6.0.0" } }, "System.Threading": { "type": "Transitive", - "resolved": "4.0.11", - "contentHash": "N+3xqIcg3VDKyjwwCGaZ9HawG9aC6cSDI+s7ROma310GQo8vilFZa86hqKppwTHleR/G0sfOzhvgnUxWCR/DrQ==", + "resolved": "4.3.0", + "contentHash": "VkUS0kOBcUf3Wwm0TSbrevDDZ6BlM+b/HRiapRFWjM5O0NS0LviG0glKmFK+hhPDd1XFeSdU1GmlLhb2CoVpIw==", "dependencies": { - "System.Runtime": "4.1.0", - "System.Threading.Tasks": "4.0.11" + "System.Runtime": "4.3.0", + "System.Threading.Tasks": "4.3.0" } }, "System.Threading.Tasks": { "type": "Transitive", - "resolved": "4.0.11", - "contentHash": "k1S4Gc6IGwtHGT8188RSeGaX86Qw/wnrgNLshJvsdNUOPP9etMmo8S07c+UlOAx4K/xLuN9ivA1bD0LVurtIxQ==", + "resolved": "4.3.0", + "contentHash": "LbSxKEdOUhVe8BezB/9uOGGppt+nZf6e1VFyw6v3DN6lqitm0OSn2uXMOdtP0M3W4iMcqcivm2J6UgqiwwnXiA==", "dependencies": { - "Microsoft.NETCore.Platforms": "1.0.1", - "Microsoft.NETCore.Targets": "1.0.1", - "System.Runtime": "4.1.0" + "Microsoft.NETCore.Platforms": "1.1.0", + "Microsoft.NETCore.Targets": "1.1.0", + "System.Runtime": "4.3.0" } }, "System.Threading.Tasks.Extensions": { @@ -1000,56 +682,10 @@ "resolved": "4.5.4", "contentHash": "zteT+G8xuGu6mS+mzDzYXbzS7rd3K6Fjb9RiZlYlJPam2/hU7JCBZBVEcywNuR+oZ1ncTvc/cq0faRr3P01OVg==" }, - "System.Threading.Timer": { + "System.ValueTuple": { "type": "Transitive", - "resolved": "4.0.1", - "contentHash": "saGfUV8uqVW6LeURiqxcGhZ24PzuRNaUBtbhVeuUAvky1naH395A/1nY0P2bWvrw/BreRtIB/EzTDkGBpqCwEw==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.0.1", - "Microsoft.NETCore.Targets": "1.0.1", - "System.Runtime": "4.1.0" - } - }, - "System.Xml.ReaderWriter": { - "type": "Transitive", - "resolved": "4.0.11", - "contentHash": "ZIiLPsf67YZ9zgr31vzrFaYQqxRPX9cVHjtPSnmx4eN6lbS/yEyYNr2vs1doGDEscF0tjCZFsk9yUg1sC9e8tg==", - "dependencies": { - "System.Collections": "4.0.11", - "System.Diagnostics.Debug": "4.0.11", - "System.Globalization": "4.0.11", - "System.IO": "4.1.0", - "System.IO.FileSystem": "4.0.1", - "System.IO.FileSystem.Primitives": "4.0.1", - "System.Resources.ResourceManager": "4.0.1", - "System.Runtime": "4.1.0", - "System.Runtime.Extensions": "4.1.0", - "System.Runtime.InteropServices": "4.1.0", - "System.Text.Encoding": "4.0.11", - "System.Text.Encoding.Extensions": "4.0.11", - "System.Text.RegularExpressions": "4.1.0", - "System.Threading.Tasks": "4.0.11", - "System.Threading.Tasks.Extensions": "4.0.0" - } - }, - "System.Xml.XDocument": { - "type": "Transitive", - "resolved": "4.0.11", - "contentHash": "Mk2mKmPi0nWaoiYeotq1dgeNK1fqWh61+EK+w4Wu8SWuTYLzpUnschb59bJtGywaPq7SmTuPf44wrXRwbIrukg==", - "dependencies": { - "System.Collections": "4.0.11", - "System.Diagnostics.Debug": "4.0.11", - "System.Diagnostics.Tools": "4.0.1", - "System.Globalization": "4.0.11", - "System.IO": "4.1.0", - "System.Reflection": "4.1.0", - "System.Resources.ResourceManager": "4.0.1", - "System.Runtime": "4.1.0", - "System.Runtime.Extensions": "4.1.0", - "System.Text.Encoding": "4.0.11", - "System.Threading": "4.0.11", - "System.Xml.ReaderWriter": "4.0.11" - } + "resolved": "4.5.0", + "contentHash": "okurQJO6NRE/apDIP23ajJ0hpiNmJ+f0BwOlB/cSqTLQlw5upkf+5+96+iG2Jw40G1fCVCyPz/FhIABUjMR+RQ==" }, "xunit.abstractions": { "type": "Transitive", @@ -1085,6 +721,25 @@ "Nncase.IO": "[1.0.0, )" } }, + "nncase.compiler": { + "type": "Project", + "dependencies": { + "DryIoc.Microsoft.DependencyInjection": "[6.1.0, )", + "DryIoc.dll": "[5.3.1, )", + "Microsoft.Extensions.Hosting": "[6.0.0, )", + "Nncase.CodeGen": "[1.0.0, )", + "Nncase.Core": "[1.0.0, )", + "Nncase.Diagnostics": "[1.0.0, )", + "Nncase.EGraph": "[1.0.0, )", + "Nncase.Evaluator": "[1.0.0, )", + "Nncase.Graph": "[1.0.0, )", + "Nncase.Importer": "[1.0.0, )", + "Nncase.Modules.StackVM": "[1.0.0, )", + "Nncase.Passes": "[1.0.0, )", + "Nncase.Quantization": "[1.0.0, )", + "Nncase.Simulator": "[1.0.0, )" + } + }, "nncase.core": { "type": "Project", "dependencies": { @@ -1098,6 +753,12 @@ "System.Reactive": "[5.0.0, )" } }, + "nncase.diagnostics": { + "type": "Project", + "dependencies": { + "Nncase.Core": "[1.0.0, )" + } + }, "nncase.egraph": { "type": "Project", "dependencies": { @@ -1123,6 +784,15 @@ "Nncase.Evaluator": "[1.0.0, )" } }, + "nncase.importer": { + "type": "Project", + "dependencies": { + "LanguageExt.Core": "[4.4.0, )", + "Nncase.Core": "[1.0.0, )", + "Onnx.Protobuf": "[1.0.0, )", + "TFLite.Schema": "[1.0.0, )" + } + }, "nncase.io": { "type": "Project" }, @@ -1142,18 +812,50 @@ "Nncase.Graph": "[1.0.0, )" } }, + "nncase.quantization": { + "type": "Project", + "dependencies": { + "Newtonsoft.Json": "[13.0.3, )", + "Nncase.Core": "[1.0.0, )", + "Nncase.Passes": "[1.0.0, )", + "OrtKISharp": "[0.0.2, )", + "System.Linq.Async": "[6.0.1, )" + } + }, "nncase.simulator": { "type": "Project", "dependencies": { "Nncase.Core": "[1.0.0, )" } }, + "onnx.protobuf": { + "type": "Project", + "dependencies": { + "Google.Protobuf": "[3.19.4, )" + } + }, + "tflite.schema": { + "type": "Project", + "dependencies": { + "Nncase.FlatBuffers": "[2.0.0, )" + } + }, "DryIoc.dll": { "type": "CentralTransitive", "requested": "[5.3.1, )", "resolved": "5.3.1", "contentHash": "E3zclUh2CIBks1t2uBD1k18pyGFJ1YSKCrbCDbB7qCdl2RAB+k68AyDpjeplhF1ot2XPV82AgyCWBXMf0ggL1g==" }, + "DryIoc.Microsoft.DependencyInjection": { + "type": "CentralTransitive", + "requested": "[6.1.0, )", + "resolved": "6.1.0", + "contentHash": "GJtCx0XgvdRXmZDtJH5FW7vMhaN2nPwOlwV7EIWN+f4+Rw2+eRCfHihtR8l9ozfgVaHkA8+zmA8PpHGKKIflcw==", + "dependencies": { + "DryIoc.dll": "5.2.2", + "Microsoft.Extensions.DependencyInjection.Abstractions": "6.0.0" + } + }, "Extension.Mathematics": { "type": "CentralTransitive", "requested": "[1.2.12, )", @@ -1186,17 +888,51 @@ "resolved": "3.19.4", "contentHash": "fd07/ykL4O4FhqrZIELm5lmiyOHfdPg9+o+hWr6tcfRdS7tHXnImg/2wtogLzlW2eEmr0J7j6ZrZvaWOLiJbxQ==" }, + "LanguageExt.Core": { + "type": "CentralTransitive", + "requested": "[4.4.0, )", + "resolved": "4.4.0", + "contentHash": "3VARp4kl87gaVNO0vg70A9Brk48cEWEVTG6p30cVN0gCI7ftrDBqkEyy8hUCVweBJUqs4J5ZFrw2tu6dp+gnQQ==", + "dependencies": { + "Microsoft.Bcl.AsyncInterfaces": "6.0.0", + "Microsoft.CSharp": "4.7.0", + "System.Diagnostics.Contracts": "4.3.0", + "System.Linq": "4.3.0", + "System.Linq.Queryable": "4.3.0", + "System.Memory": "4.5.4", + "System.Reflection.Emit": "4.3.0", + "System.Reflection.Emit.Lightweight": "4.3.0", + "System.Threading.Tasks.Extensions": "4.5.4", + "System.ValueTuple": "4.5.0" + } + }, "Microsoft.Extensions.Hosting": { "type": "CentralTransitive", "requested": "[6.0.0, )", - "resolved": "2.1.0", - "contentHash": "nqOrLtBqpwRT006vdQ2Vp87uiuYztiZcZAndFqH91ZH4SQgr8wImCVQwzUgTxx1DSrpIW765+xrZTZqsoGtvqg==", + "resolved": "6.0.0", + "contentHash": "M8VzD0ni5VarIRT8njnwK4K2WSAo0kZH4Zc3mKcSGkP4CjDZ91T9ZEFmmwhmo4z7x8AFq+tW0WFi9wX+K2cxkQ==", "dependencies": { - "Microsoft.Extensions.Configuration": "2.1.0", - "Microsoft.Extensions.DependencyInjection": "2.1.0", - "Microsoft.Extensions.FileProviders.Physical": "2.1.0", - "Microsoft.Extensions.Hosting.Abstractions": "2.1.0", - "Microsoft.Extensions.Logging": "2.1.0" + "Microsoft.Extensions.Configuration": "6.0.0", + "Microsoft.Extensions.Configuration.Abstractions": "6.0.0", + "Microsoft.Extensions.Configuration.Binder": "6.0.0", + "Microsoft.Extensions.Configuration.CommandLine": "6.0.0", + "Microsoft.Extensions.Configuration.EnvironmentVariables": "6.0.0", + "Microsoft.Extensions.Configuration.FileExtensions": "6.0.0", + "Microsoft.Extensions.Configuration.Json": "6.0.0", + "Microsoft.Extensions.Configuration.UserSecrets": "6.0.0", + "Microsoft.Extensions.DependencyInjection": "6.0.0", + "Microsoft.Extensions.DependencyInjection.Abstractions": "6.0.0", + "Microsoft.Extensions.FileProviders.Abstractions": "6.0.0", + "Microsoft.Extensions.FileProviders.Physical": "6.0.0", + "Microsoft.Extensions.Hosting.Abstractions": "6.0.0", + "Microsoft.Extensions.Logging": "6.0.0", + "Microsoft.Extensions.Logging.Abstractions": "6.0.0", + "Microsoft.Extensions.Logging.Configuration": "6.0.0", + "Microsoft.Extensions.Logging.Console": "6.0.0", + "Microsoft.Extensions.Logging.Debug": "6.0.0", + "Microsoft.Extensions.Logging.EventLog": "6.0.0", + "Microsoft.Extensions.Logging.EventSource": "6.0.0", + "Microsoft.Extensions.Options": "6.0.0" } }, "Microsoft.Extensions.Hosting.Abstractions": { @@ -1243,6 +979,18 @@ "System.Runtime.CompilerServices.Unsafe": "5.0.0" } }, + "Newtonsoft.Json": { + "type": "CentralTransitive", + "requested": "[13.0.3, )", + "resolved": "13.0.3", + "contentHash": "HrC5BXdl00IP9zeV+0Z848QWPAoCr9P3bDEZguI+gkLcBKAOxix/tLEAAHC+UvDNPv4a2d18lOReHMOagPa+zQ==" + }, + "Nncase.FlatBuffers": { + "type": "CentralTransitive", + "requested": "[2.0.0, )", + "resolved": "2.0.0", + "contentHash": "ir3uek0+7Y8SwOUGUR8y94sgpVDWLAjKGBm9z7cLe/38GyPxWbIYHPnHZHksNTExTsx3Ie9GtwagkgR/jm64hA==" + }, "OrtKISharp": { "type": "CentralTransitive", "requested": "[0.0.2, )", diff --git a/src/Nncase.Tests/Importer/UnitTestImporter.cs b/src/Nncase.Tests/Importer/UnitTestImporter.cs index d708d2ce35..93506aa4e5 100644 --- a/src/Nncase.Tests/Importer/UnitTestImporter.cs +++ b/src/Nncase.Tests/Importer/UnitTestImporter.cs @@ -7,6 +7,7 @@ using System.Linq; using System.Text; using System.Threading.Tasks; +using Nncase.IO; using Nncase.IR; using Nncase.Passes.Transforms; using Nncase.Tests.TestFixture; @@ -37,6 +38,16 @@ public async Task TestImportTFLite() Assert.True(module.Entry!.InferenceType()); } + [Fact] + public async Task TestImportNcnn() + { + using var file = File.OpenRead(Path.Combine(SolutionDirectory, "examples/user_guide/test.param")); + var module = Importers.ImportNcnn(file, new ZeroStream(), CompileSession); + await InferShapeAsync(module); + Assert.NotNull(module.Entry); + Assert.True(module.Entry!.InferenceType()); + } + private Task InferShapeAsync(IRModule module) { var pmgr = CompileSession.CreatePassManager("InferShapePasses"); diff --git a/src/Nncase.Tests/TIR/UnitTestMutators.cs b/src/Nncase.Tests/TIR/UnitTestMutators.cs index 1df67941ae..a90571e8a0 100644 --- a/src/Nncase.Tests/TIR/UnitTestMutators.cs +++ b/src/Nncase.Tests/TIR/UnitTestMutators.cs @@ -80,7 +80,7 @@ public async Task TestFoldConstCallWithTuple() var name = getBuffer(count++, LoadT.GlbPp).Name[^4..]; // System.Console.WriteLine($"{w} {name}"); - if (((w / 9) % 2) == 0) + if ((w / 9 % 2) == 0) { Assert.Equal("ping", name); } diff --git a/src/Nncase.Tests/packages.lock.json b/src/Nncase.Tests/packages.lock.json index dce3ce0116..c722181308 100644 --- a/src/Nncase.Tests/packages.lock.json +++ b/src/Nncase.Tests/packages.lock.json @@ -80,11 +80,11 @@ }, "StyleCop.Analyzers": { "type": "Direct", - "requested": "[1.2.0-beta.435, )", - "resolved": "1.2.0-beta.435", - "contentHash": "TADk7vdGXtfTnYCV7GyleaaRTQjfoSfZXprQrVMm7cSJtJbFc1QIbWPyLvrgrfGdfHbGmUPvaN4ODKNxg2jgPQ==", + "requested": "[1.2.0-beta.507, )", + "resolved": "1.2.0-beta.507", + "contentHash": "/FtugDT66cKJJ+GGH7rNpG6UDrT4iIWz45M6lrXXHobDUFDHw+q5VgkbiR+6ffTO564ge7w6fQh/eoQhVdJO8Q==", "dependencies": { - "StyleCop.Analyzers.Unstable": "1.2.0.435" + "StyleCop.Analyzers.Unstable": "1.2.0.507" } }, "System.Linq.Async": { @@ -470,16 +470,6 @@ "Newtonsoft.Json": "9.0.1" } }, - "Microsoft.Win32.Primitives": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "9ZQKCWxH7Ijp9BfahvL2Zyf1cJIk8XYLF6Yjzr2yi0b2cOut/HQ31qf1ThHAgCc3WiZMdnWcfJCgN82/0UunxA==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "Microsoft.NETCore.Targets": "1.1.0", - "System.Runtime": "4.3.0" - } - }, "NetFabric.Hyperlinq.Abstractions": { "type": "Transitive", "resolved": "1.3.0", @@ -487,53 +477,10 @@ }, "NETStandard.Library": { "type": "Transitive", - "resolved": "1.6.1", - "contentHash": "WcSp3+vP+yHNgS8EV5J7pZ9IRpeDuARBPN28by8zqff1wJQXm26PVU8L3/fYLBJVU7BtDyqNVWq2KlCVvSSR4A==", + "resolved": "2.0.3", + "contentHash": "st47PosZSHrjECdjeIzZQbzivYBJFv6P2nv4cj2ypdI204DO+vZ7l5raGMiX4eXMJ53RfOIg+/s4DHVZ54Nu2A==", "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "Microsoft.Win32.Primitives": "4.3.0", - "System.AppContext": "4.3.0", - "System.Collections": "4.3.0", - "System.Collections.Concurrent": "4.3.0", - "System.Console": "4.3.0", - "System.Diagnostics.Debug": "4.3.0", - "System.Diagnostics.Tools": "4.3.0", - "System.Diagnostics.Tracing": "4.3.0", - "System.Globalization": "4.3.0", - "System.Globalization.Calendars": "4.3.0", - "System.IO": "4.3.0", - "System.IO.Compression": "4.3.0", - "System.IO.Compression.ZipFile": "4.3.0", - "System.IO.FileSystem": "4.3.0", - "System.IO.FileSystem.Primitives": "4.3.0", - "System.Linq": "4.3.0", - "System.Linq.Expressions": "4.3.0", - "System.Net.Http": "4.3.0", - "System.Net.Primitives": "4.3.0", - "System.Net.Sockets": "4.3.0", - "System.ObjectModel": "4.3.0", - "System.Reflection": "4.3.0", - "System.Reflection.Extensions": "4.3.0", - "System.Reflection.Primitives": "4.3.0", - "System.Resources.ResourceManager": "4.3.0", - "System.Runtime": "4.3.0", - "System.Runtime.Extensions": "4.3.0", - "System.Runtime.Handles": "4.3.0", - "System.Runtime.InteropServices": "4.3.0", - "System.Runtime.InteropServices.RuntimeInformation": "4.3.0", - "System.Runtime.Numerics": "4.3.0", - "System.Security.Cryptography.Algorithms": "4.3.0", - "System.Security.Cryptography.Encoding": "4.3.0", - "System.Security.Cryptography.Primitives": "4.3.0", - "System.Security.Cryptography.X509Certificates": "4.3.0", - "System.Text.Encoding": "4.3.0", - "System.Text.Encoding.Extensions": "4.3.0", - "System.Text.RegularExpressions": "4.3.0", - "System.Threading": "4.3.0", - "System.Threading.Tasks": "4.3.0", - "System.Threading.Timer": "4.3.0", - "System.Xml.ReaderWriter": "4.3.0", - "System.Xml.XDocument": "4.3.0" + "Microsoft.NETCore.Platforms": "1.1.0" } }, "NuGet.Frameworks": { @@ -541,125 +488,10 @@ "resolved": "5.0.0", "contentHash": "c5JVjuVAm4f7E9Vj+v09Z9s2ZsqFDjBpcsyS3M9xRo0bEdm/LVZSzLxxNvfvAwRiiE8nwe1h2G4OwiwlzFKXlA==" }, - "runtime.debian.8-x64.runtime.native.System.Security.Cryptography.OpenSsl": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "HdSSp5MnJSsg08KMfZThpuLPJpPwE5hBXvHwoKWosyHHfe8Mh5WKT0ylEOf6yNzX6Ngjxe4Whkafh5q7Ymac4Q==" - }, - "runtime.fedora.23-x64.runtime.native.System.Security.Cryptography.OpenSsl": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "+yH1a49wJMy8Zt4yx5RhJrxO/DBDByAiCzNwiETI+1S4mPdCu0OY4djdciC7Vssk0l22wQaDLrXxXkp+3+7bVA==" - }, - "runtime.fedora.24-x64.runtime.native.System.Security.Cryptography.OpenSsl": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "c3YNH1GQJbfIPJeCnr4avseugSqPrxwIqzthYyZDN6EuOyNOzq+y2KSUfRcXauya1sF4foESTgwM5e1A8arAKw==" - }, - "runtime.native.System": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "c/qWt2LieNZIj1jGnVNsE2Kl23Ya2aSTBuXMD6V7k9KWr6l16Tqdwq+hJScEpWER9753NWC8h96PaVNY5Ld7Jw==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "Microsoft.NETCore.Targets": "1.1.0" - } - }, - "runtime.native.System.IO.Compression": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "INBPonS5QPEgn7naufQFXJEp3zX6L4bwHgJ/ZH78aBTpeNfQMtf7C6VrAFhlq2xxWBveIOWyFzQjJ8XzHMhdOQ==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "Microsoft.NETCore.Targets": "1.1.0" - } - }, - "runtime.native.System.Net.Http": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "ZVuZJqnnegJhd2k/PtAbbIcZ3aZeITq3sj06oKfMBSfphW3HDmk/t4ObvbOk/JA/swGR0LNqMksAh/f7gpTROg==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "Microsoft.NETCore.Targets": "1.1.0" - } - }, - "runtime.native.System.Security.Cryptography.Apple": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "DloMk88juo0OuOWr56QG7MNchmafTLYWvABy36izkrLI5VledI0rq28KGs1i9wbpeT9NPQrx/wTf8U2vazqQ3Q==", - "dependencies": { - "runtime.osx.10.10-x64.runtime.native.System.Security.Cryptography.Apple": "4.3.0" - } - }, - "runtime.native.System.Security.Cryptography.OpenSsl": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "NS1U+700m4KFRHR5o4vo9DSlTmlCKu/u7dtE5sUHVIPB+xpXxYQvgBgA6wEIeCz6Yfn0Z52/72WYsToCEPJnrw==", - "dependencies": { - "runtime.debian.8-x64.runtime.native.System.Security.Cryptography.OpenSsl": "4.3.0", - "runtime.fedora.23-x64.runtime.native.System.Security.Cryptography.OpenSsl": "4.3.0", - "runtime.fedora.24-x64.runtime.native.System.Security.Cryptography.OpenSsl": "4.3.0", - "runtime.opensuse.13.2-x64.runtime.native.System.Security.Cryptography.OpenSsl": "4.3.0", - "runtime.opensuse.42.1-x64.runtime.native.System.Security.Cryptography.OpenSsl": "4.3.0", - "runtime.osx.10.10-x64.runtime.native.System.Security.Cryptography.OpenSsl": "4.3.0", - "runtime.rhel.7-x64.runtime.native.System.Security.Cryptography.OpenSsl": "4.3.0", - "runtime.ubuntu.14.04-x64.runtime.native.System.Security.Cryptography.OpenSsl": "4.3.0", - "runtime.ubuntu.16.04-x64.runtime.native.System.Security.Cryptography.OpenSsl": "4.3.0", - "runtime.ubuntu.16.10-x64.runtime.native.System.Security.Cryptography.OpenSsl": "4.3.0" - } - }, - "runtime.opensuse.13.2-x64.runtime.native.System.Security.Cryptography.OpenSsl": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "b3pthNgxxFcD+Pc0WSEoC0+md3MyhRS6aCEeenvNE3Fdw1HyJ18ZhRFVJJzIeR/O/jpxPboB805Ho0T3Ul7w8A==" - }, - "runtime.opensuse.42.1-x64.runtime.native.System.Security.Cryptography.OpenSsl": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "KeLz4HClKf+nFS7p/6Fi/CqyLXh81FpiGzcmuS8DGi9lUqSnZ6Es23/gv2O+1XVGfrbNmviF7CckBpavkBoIFQ==" - }, - "runtime.osx.10.10-x64.runtime.native.System.Security.Cryptography.Apple": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "kVXCuMTrTlxq4XOOMAysuNwsXWpYeboGddNGpIgNSZmv1b6r/s/DPk0fYMB7Q5Qo4bY68o48jt4T4y5BVecbCQ==" - }, - "runtime.osx.10.10-x64.runtime.native.System.Security.Cryptography.OpenSsl": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "X7IdhILzr4ROXd8mI1BUCQMSHSQwelUlBjF1JyTKCjXaOGn2fB4EKBxQbCK2VjO3WaWIdlXZL3W6TiIVnrhX4g==" - }, - "runtime.rhel.7-x64.runtime.native.System.Security.Cryptography.OpenSsl": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "nyFNiCk/r+VOiIqreLix8yN+q3Wga9+SE8BCgkf+2BwEKiNx6DyvFjCgkfV743/grxv8jHJ8gUK4XEQw7yzRYg==" - }, - "runtime.ubuntu.14.04-x64.runtime.native.System.Security.Cryptography.OpenSsl": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "ytoewC6wGorL7KoCAvRfsgoJPJbNq+64k2SqW6JcOAebWsFUvCCYgfzQMrnpvPiEl4OrblUlhF2ji+Q1+SVLrQ==" - }, - "runtime.ubuntu.16.04-x64.runtime.native.System.Security.Cryptography.OpenSsl": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "I8bKw2I8k58Wx7fMKQJn2R8lamboCAiHfHeV/pS65ScKWMMI0+wJkLYlEKvgW1D/XvSl/221clBoR2q9QNNM7A==" - }, - "runtime.ubuntu.16.10-x64.runtime.native.System.Security.Cryptography.OpenSsl": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "VB5cn/7OzUfzdnC8tqAIMQciVLiq2epm2NrAm1E9OjNRyG4lVhfR61SMcLizejzQP8R8Uf/0l5qOIbUEi+RdEg==" - }, "StyleCop.Analyzers.Unstable": { "type": "Transitive", - "resolved": "1.2.0.435", - "contentHash": "ouwPWZxbOV3SmCZxIRqHvljkSzkCyi1tDoMzQtDb/bRP8ctASV/iRJr+A2Gdj0QLaLmWnqTWDrH82/iP+X80Lg==" - }, - "System.AppContext": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "fKC+rmaLfeIzUhagxY17Q9siv/sPrjjKcfNg1Ic8IlQkZLipo8ljcaZQu4VtI4Jqbzjc2VTjzGLF6WmsRXAEgA==", - "dependencies": { - "System.Runtime": "4.3.0" - } + "resolved": "1.2.0.507", + "contentHash": "gTY3IQdRqDJ4hbhSA3e/R48oE8b/OiKfvwkt1QdNVfrJK2gMHBV8ldaHJ885jxWZfllK66soa/sdcjh9bX49Tw==" }, "System.Buffers": { "type": "Transitive", @@ -676,40 +508,11 @@ "System.Runtime": "4.3.0" } }, - "System.Collections.Concurrent": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "ztl69Xp0Y/UXCL+3v3tEU+lIy+bvjKNUmopn1wep/a291pVPK7dxBd6T7WnlQqRog+d1a/hSsgRsmFnIBKTPLQ==", - "dependencies": { - "System.Collections": "4.3.0", - "System.Diagnostics.Debug": "4.3.0", - "System.Diagnostics.Tracing": "4.3.0", - "System.Globalization": "4.3.0", - "System.Reflection": "4.3.0", - "System.Resources.ResourceManager": "4.3.0", - "System.Runtime": "4.3.0", - "System.Runtime.Extensions": "4.3.0", - "System.Threading": "4.3.0", - "System.Threading.Tasks": "4.3.0" - } - }, "System.Collections.Immutable": { "type": "Transitive", "resolved": "7.0.0", "contentHash": "dQPcs0U1IKnBdRDBkrCTi1FoajSTBzLcVTpjO4MBCMC7f4pDOIPzgBoX8JjG7X6uZRJ8EBxsi8+DR1JuwjnzOQ==" }, - "System.Console": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "DHDrIxiqk1h03m6khKWV2X8p/uvN79rgSqpilL6uzpmSfxfU5ng8VcPtW4qsDsQDHiTv6IPV9TmD5M/vElPNLg==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "Microsoft.NETCore.Targets": "1.1.0", - "System.IO": "4.3.0", - "System.Runtime": "4.3.0", - "System.Text.Encoding": "4.3.0" - } - }, "System.Diagnostics.Contracts": { "type": "Transitive", "resolved": "4.3.0", @@ -741,26 +544,6 @@ "resolved": "6.0.0", "contentHash": "lcyUiXTsETK2ALsZrX+nWuHSIQeazhqPphLfaRxzdGaG93+0kELqpgEHtwWOlQe7+jSFnKwaCAgL4kjeZCQJnw==" }, - "System.Diagnostics.Tools": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "UUvkJfSYJMM6x527dJg2VyWPSRqIVB0Z7dbjHst1zmwTXz5CcXSYJFWRpuigfbO1Lf7yfZiIaEUesfnl/g5EyA==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "Microsoft.NETCore.Targets": "1.1.0", - "System.Runtime": "4.3.0" - } - }, - "System.Diagnostics.Tracing": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "rswfv0f/Cqkh78rA5S8eN8Neocz234+emGCtTF3lxPY96F+mmmUen6tbn0glN6PMvlKQb9bPAY5e9u7fgPTkKw==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "Microsoft.NETCore.Targets": "1.1.0", - "System.Runtime": "4.3.0" - } - }, "System.Globalization": { "type": "Transitive", "resolved": "4.3.0", @@ -771,30 +554,6 @@ "System.Runtime": "4.3.0" } }, - "System.Globalization.Calendars": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "GUlBtdOWT4LTV3I+9/PJW+56AnnChTaOqqTLFtdmype/L500M2LIyXgmtd9X2P2VOkmJd5c67H5SaC2QcL1bFA==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "Microsoft.NETCore.Targets": "1.1.0", - "System.Globalization": "4.3.0", - "System.Runtime": "4.3.0" - } - }, - "System.Globalization.Extensions": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "FhKmdR6MPG+pxow6wGtNAWdZh7noIOpdD5TwQ3CprzgIE1bBBoim0vbR1+AWsWjQmU7zXHgQo4TWSP6lCeiWcQ==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "System.Globalization": "4.3.0", - "System.Resources.ResourceManager": "4.3.0", - "System.Runtime": "4.3.0", - "System.Runtime.Extensions": "4.3.0", - "System.Runtime.InteropServices": "4.3.0" - } - }, "System.IO": { "type": "Transitive", "resolved": "4.3.0", @@ -807,67 +566,6 @@ "System.Threading.Tasks": "4.3.0" } }, - "System.IO.Compression": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "YHndyoiV90iu4iKG115ibkhrG+S3jBm8Ap9OwoUAzO5oPDAWcr0SFwQFm0HjM8WkEZWo0zvLTyLmbvTkW1bXgg==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "System.Buffers": "4.3.0", - "System.Collections": "4.3.0", - "System.Diagnostics.Debug": "4.3.0", - "System.IO": "4.3.0", - "System.Resources.ResourceManager": "4.3.0", - "System.Runtime": "4.3.0", - "System.Runtime.Extensions": "4.3.0", - "System.Runtime.Handles": "4.3.0", - "System.Runtime.InteropServices": "4.3.0", - "System.Text.Encoding": "4.3.0", - "System.Threading": "4.3.0", - "System.Threading.Tasks": "4.3.0", - "runtime.native.System": "4.3.0", - "runtime.native.System.IO.Compression": "4.3.0" - } - }, - "System.IO.Compression.ZipFile": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "G4HwjEsgIwy3JFBduZ9quBkAu+eUwjIdJleuNSgmUojbH6O3mlvEIme+GHx/cLlTAPcrnnL7GqvB9pTlWRfhOg==", - "dependencies": { - "System.Buffers": "4.3.0", - "System.IO": "4.3.0", - "System.IO.Compression": "4.3.0", - "System.IO.FileSystem": "4.3.0", - "System.IO.FileSystem.Primitives": "4.3.0", - "System.Resources.ResourceManager": "4.3.0", - "System.Runtime": "4.3.0", - "System.Runtime.Extensions": "4.3.0", - "System.Text.Encoding": "4.3.0" - } - }, - "System.IO.FileSystem": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "3wEMARTnuio+ulnvi+hkRNROYwa1kylvYahhcLk4HSoVdl+xxTFVeVlYOfLwrDPImGls0mDqbMhrza8qnWPTdA==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "Microsoft.NETCore.Targets": "1.1.0", - "System.IO": "4.3.0", - "System.IO.FileSystem.Primitives": "4.3.0", - "System.Runtime": "4.3.0", - "System.Runtime.Handles": "4.3.0", - "System.Text.Encoding": "4.3.0", - "System.Threading.Tasks": "4.3.0" - } - }, - "System.IO.FileSystem.Primitives": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "6QOb2XFLch7bEc4lIcJH49nJN2HV+OC3fHDgsLVsBVBk3Y4hFAnOBGzJ2lUu7CyDDFo9IBWkSsnbkT6IBwwiMw==", - "dependencies": { - "System.Runtime": "4.3.0" - } - }, "System.Linq": { "type": "Transitive", "resolved": "4.3.0", @@ -924,63 +622,6 @@ "resolved": "4.5.5", "contentHash": "XIWiDvKPXaTveaB7HVganDlOCRoj03l+jrwNvcge/t8vhGYKvqV+dMv6G4SAX2NoNmN0wZfVPTAlFwZcZvVOUw==" }, - "System.Net.Http": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "sYg+FtILtRQuYWSIAuNOELwVuVsxVyJGWQyOnlAzhV4xvhyFnON1bAzYYC+jjRW8JREM45R0R5Dgi8MTC5sEwA==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "System.Collections": "4.3.0", - "System.Diagnostics.Debug": "4.3.0", - "System.Diagnostics.DiagnosticSource": "4.3.0", - "System.Diagnostics.Tracing": "4.3.0", - "System.Globalization": "4.3.0", - "System.Globalization.Extensions": "4.3.0", - "System.IO": "4.3.0", - "System.IO.FileSystem": "4.3.0", - "System.Net.Primitives": "4.3.0", - "System.Resources.ResourceManager": "4.3.0", - "System.Runtime": "4.3.0", - "System.Runtime.Extensions": "4.3.0", - "System.Runtime.Handles": "4.3.0", - "System.Runtime.InteropServices": "4.3.0", - "System.Security.Cryptography.Algorithms": "4.3.0", - "System.Security.Cryptography.Encoding": "4.3.0", - "System.Security.Cryptography.OpenSsl": "4.3.0", - "System.Security.Cryptography.Primitives": "4.3.0", - "System.Security.Cryptography.X509Certificates": "4.3.0", - "System.Text.Encoding": "4.3.0", - "System.Threading": "4.3.0", - "System.Threading.Tasks": "4.3.0", - "runtime.native.System": "4.3.0", - "runtime.native.System.Net.Http": "4.3.0", - "runtime.native.System.Security.Cryptography.OpenSsl": "4.3.0" - } - }, - "System.Net.Primitives": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "qOu+hDwFwoZPbzPvwut2qATe3ygjeQBDQj91xlsaqGFQUI5i4ZnZb8yyQuLGpDGivEPIt8EJkd1BVzVoP31FXA==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "Microsoft.NETCore.Targets": "1.1.0", - "System.Runtime": "4.3.0", - "System.Runtime.Handles": "4.3.0" - } - }, - "System.Net.Sockets": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "m6icV6TqQOAdgt5N/9I5KNpjom/5NFtkmGseEH+AK/hny8XrytLH3+b5M8zL/Ycg3fhIocFpUMyl/wpFnVRvdw==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "Microsoft.NETCore.Targets": "1.1.0", - "System.IO": "4.3.0", - "System.Net.Primitives": "4.3.0", - "System.Runtime": "4.3.0", - "System.Threading.Tasks": "4.3.0" - } - }, "System.ObjectModel": { "type": "Transitive", "resolved": "4.3.0", @@ -1109,198 +750,6 @@ "System.Runtime": "4.3.0" } }, - "System.Runtime.Handles": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "OKiSUN7DmTWeYb3l51A7EYaeNMnvxwE249YtZz7yooT4gOZhmTjIn48KgSsw2k2lYdLgTKNJw/ZIfSElwDRVgg==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "Microsoft.NETCore.Targets": "1.1.0", - "System.Runtime": "4.3.0" - } - }, - "System.Runtime.InteropServices": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "uv1ynXqiMK8mp1GM3jDqPCFN66eJ5w5XNomaK2XD+TuCroNTLFGeZ+WCmBMcBDyTFKou3P6cR6J/QsaqDp7fGQ==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "Microsoft.NETCore.Targets": "1.1.0", - "System.Reflection": "4.3.0", - "System.Reflection.Primitives": "4.3.0", - "System.Runtime": "4.3.0", - "System.Runtime.Handles": "4.3.0" - } - }, - "System.Runtime.InteropServices.RuntimeInformation": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "cbz4YJMqRDR7oLeMRbdYv7mYzc++17lNhScCX0goO2XpGWdvAt60CGN+FHdePUEHCe/Jy9jUlvNAiNdM+7jsOw==", - "dependencies": { - "System.Reflection": "4.3.0", - "System.Reflection.Extensions": "4.3.0", - "System.Resources.ResourceManager": "4.3.0", - "System.Runtime": "4.3.0", - "System.Runtime.InteropServices": "4.3.0", - "System.Threading": "4.3.0", - "runtime.native.System": "4.3.0" - } - }, - "System.Runtime.Numerics": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "yMH+MfdzHjy17l2KESnPiF2dwq7T+xLnSJar7slyimAkUh/gTrS9/UQOtv7xarskJ2/XDSNvfLGOBQPjL7PaHQ==", - "dependencies": { - "System.Globalization": "4.3.0", - "System.Resources.ResourceManager": "4.3.0", - "System.Runtime": "4.3.0", - "System.Runtime.Extensions": "4.3.0" - } - }, - "System.Security.Cryptography.Algorithms": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "W1kd2Y8mYSCgc3ULTAZ0hOP2dSdG5YauTb1089T0/kRcN2MpSAW1izOFROrJgxSlMn3ArsgHXagigyi+ibhevg==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "System.Collections": "4.3.0", - "System.IO": "4.3.0", - "System.Resources.ResourceManager": "4.3.0", - "System.Runtime": "4.3.0", - "System.Runtime.Extensions": "4.3.0", - "System.Runtime.Handles": "4.3.0", - "System.Runtime.InteropServices": "4.3.0", - "System.Runtime.Numerics": "4.3.0", - "System.Security.Cryptography.Encoding": "4.3.0", - "System.Security.Cryptography.Primitives": "4.3.0", - "System.Text.Encoding": "4.3.0", - "runtime.native.System.Security.Cryptography.Apple": "4.3.0", - "runtime.native.System.Security.Cryptography.OpenSsl": "4.3.0" - } - }, - "System.Security.Cryptography.Cng": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "03idZOqFlsKRL4W+LuCpJ6dBYDUWReug6lZjBa3uJWnk5sPCUXckocevTaUA8iT/MFSrY/2HXkOt753xQ/cf8g==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "System.IO": "4.3.0", - "System.Resources.ResourceManager": "4.3.0", - "System.Runtime": "4.3.0", - "System.Runtime.Extensions": "4.3.0", - "System.Runtime.Handles": "4.3.0", - "System.Runtime.InteropServices": "4.3.0", - "System.Security.Cryptography.Algorithms": "4.3.0", - "System.Security.Cryptography.Encoding": "4.3.0", - "System.Security.Cryptography.Primitives": "4.3.0", - "System.Text.Encoding": "4.3.0" - } - }, - "System.Security.Cryptography.Csp": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "X4s/FCkEUnRGnwR3aSfVIkldBmtURMhmexALNTwpjklzxWU7yjMk7GHLKOZTNkgnWnE0q7+BCf9N2LVRWxewaA==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "System.IO": "4.3.0", - "System.Reflection": "4.3.0", - "System.Resources.ResourceManager": "4.3.0", - "System.Runtime": "4.3.0", - "System.Runtime.Extensions": "4.3.0", - "System.Runtime.Handles": "4.3.0", - "System.Runtime.InteropServices": "4.3.0", - "System.Security.Cryptography.Algorithms": "4.3.0", - "System.Security.Cryptography.Encoding": "4.3.0", - "System.Security.Cryptography.Primitives": "4.3.0", - "System.Text.Encoding": "4.3.0", - "System.Threading": "4.3.0" - } - }, - "System.Security.Cryptography.Encoding": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "1DEWjZZly9ae9C79vFwqaO5kaOlI5q+3/55ohmq/7dpDyDfc8lYe7YVxJUZ5MF/NtbkRjwFRo14yM4OEo9EmDw==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "System.Collections": "4.3.0", - "System.Collections.Concurrent": "4.3.0", - "System.Linq": "4.3.0", - "System.Resources.ResourceManager": "4.3.0", - "System.Runtime": "4.3.0", - "System.Runtime.Extensions": "4.3.0", - "System.Runtime.Handles": "4.3.0", - "System.Runtime.InteropServices": "4.3.0", - "System.Security.Cryptography.Primitives": "4.3.0", - "System.Text.Encoding": "4.3.0", - "runtime.native.System.Security.Cryptography.OpenSsl": "4.3.0" - } - }, - "System.Security.Cryptography.OpenSsl": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "h4CEgOgv5PKVF/HwaHzJRiVboL2THYCou97zpmhjghx5frc7fIvlkY1jL+lnIQyChrJDMNEXS6r7byGif8Cy4w==", - "dependencies": { - "System.Collections": "4.3.0", - "System.IO": "4.3.0", - "System.Resources.ResourceManager": "4.3.0", - "System.Runtime": "4.3.0", - "System.Runtime.Extensions": "4.3.0", - "System.Runtime.Handles": "4.3.0", - "System.Runtime.InteropServices": "4.3.0", - "System.Runtime.Numerics": "4.3.0", - "System.Security.Cryptography.Algorithms": "4.3.0", - "System.Security.Cryptography.Encoding": "4.3.0", - "System.Security.Cryptography.Primitives": "4.3.0", - "System.Text.Encoding": "4.3.0", - "runtime.native.System.Security.Cryptography.OpenSsl": "4.3.0" - } - }, - "System.Security.Cryptography.Primitives": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "7bDIyVFNL/xKeFHjhobUAQqSpJq9YTOpbEs6mR233Et01STBMXNAc/V+BM6dwYGc95gVh/Zf+iVXWzj3mE8DWg==", - "dependencies": { - "System.Diagnostics.Debug": "4.3.0", - "System.Globalization": "4.3.0", - "System.IO": "4.3.0", - "System.Resources.ResourceManager": "4.3.0", - "System.Runtime": "4.3.0", - "System.Threading": "4.3.0", - "System.Threading.Tasks": "4.3.0" - } - }, - "System.Security.Cryptography.X509Certificates": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "t2Tmu6Y2NtJ2um0RtcuhP7ZdNNxXEgUm2JeoA/0NvlMjAhKCnM1NX07TDl3244mVp3QU6LPEhT3HTtH1uF7IYw==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "System.Collections": "4.3.0", - "System.Diagnostics.Debug": "4.3.0", - "System.Globalization": "4.3.0", - "System.Globalization.Calendars": "4.3.0", - "System.IO": "4.3.0", - "System.IO.FileSystem": "4.3.0", - "System.IO.FileSystem.Primitives": "4.3.0", - "System.Resources.ResourceManager": "4.3.0", - "System.Runtime": "4.3.0", - "System.Runtime.Extensions": "4.3.0", - "System.Runtime.Handles": "4.3.0", - "System.Runtime.InteropServices": "4.3.0", - "System.Runtime.Numerics": "4.3.0", - "System.Security.Cryptography.Algorithms": "4.3.0", - "System.Security.Cryptography.Cng": "4.3.0", - "System.Security.Cryptography.Csp": "4.3.0", - "System.Security.Cryptography.Encoding": "4.3.0", - "System.Security.Cryptography.OpenSsl": "4.3.0", - "System.Security.Cryptography.Primitives": "4.3.0", - "System.Text.Encoding": "4.3.0", - "System.Threading": "4.3.0", - "runtime.native.System": "4.3.0", - "runtime.native.System.Net.Http": "4.3.0", - "runtime.native.System.Security.Cryptography.OpenSsl": "4.3.0" - } - }, "System.Text.Encoding": { "type": "Transitive", "resolved": "4.3.0", @@ -1311,17 +760,6 @@ "System.Runtime": "4.3.0" } }, - "System.Text.Encoding.Extensions": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "YVMK0Bt/A43RmwizJoZ22ei2nmrhobgeiYwFzC4YAN+nue8RF6djXDMog0UCn+brerQoYVyaS+ghy9P/MUVcmw==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "Microsoft.NETCore.Targets": "1.1.0", - "System.Runtime": "4.3.0", - "System.Text.Encoding": "4.3.0" - } - }, "System.Text.Encodings.Web": { "type": "Transitive", "resolved": "6.0.0", @@ -1339,14 +777,6 @@ "System.Text.Encodings.Web": "6.0.0" } }, - "System.Text.RegularExpressions": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "RpT2DA+L660cBt1FssIE9CAGpLFdFPuheB7pLpKpn6ZXNby7jDERe8Ua/Ne2xGiwLVG2JOqziiaVCGDon5sKFA==", - "dependencies": { - "System.Runtime": "4.3.0" - } - }, "System.Threading": { "type": "Transitive", "resolved": "4.3.0", @@ -1371,62 +801,11 @@ "resolved": "4.5.4", "contentHash": "zteT+G8xuGu6mS+mzDzYXbzS7rd3K6Fjb9RiZlYlJPam2/hU7JCBZBVEcywNuR+oZ1ncTvc/cq0faRr3P01OVg==" }, - "System.Threading.Timer": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "Z6YfyYTCg7lOZjJzBjONJTFKGN9/NIYKSxhU5GRd+DTwHSZyvWp1xuI5aR+dLg+ayyC5Xv57KiY4oJ0tMO89fQ==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "Microsoft.NETCore.Targets": "1.1.0", - "System.Runtime": "4.3.0" - } - }, "System.ValueTuple": { "type": "Transitive", "resolved": "4.5.0", "contentHash": "okurQJO6NRE/apDIP23ajJ0hpiNmJ+f0BwOlB/cSqTLQlw5upkf+5+96+iG2Jw40G1fCVCyPz/FhIABUjMR+RQ==" }, - "System.Xml.ReaderWriter": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "GrprA+Z0RUXaR4N7/eW71j1rgMnEnEVlgii49GZyAjTH7uliMnrOU3HNFBr6fEDBCJCIdlVNq9hHbaDR621XBA==", - "dependencies": { - "System.Collections": "4.3.0", - "System.Diagnostics.Debug": "4.3.0", - "System.Globalization": "4.3.0", - "System.IO": "4.3.0", - "System.IO.FileSystem": "4.3.0", - "System.IO.FileSystem.Primitives": "4.3.0", - "System.Resources.ResourceManager": "4.3.0", - "System.Runtime": "4.3.0", - "System.Runtime.Extensions": "4.3.0", - "System.Runtime.InteropServices": "4.3.0", - "System.Text.Encoding": "4.3.0", - "System.Text.Encoding.Extensions": "4.3.0", - "System.Text.RegularExpressions": "4.3.0", - "System.Threading.Tasks": "4.3.0", - "System.Threading.Tasks.Extensions": "4.3.0" - } - }, - "System.Xml.XDocument": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "5zJ0XDxAIg8iy+t4aMnQAu0MqVbqyvfoUVl1yDV61xdo3Vth45oA2FoY4pPkxYAH5f8ixpmTqXeEIya95x0aCQ==", - "dependencies": { - "System.Collections": "4.3.0", - "System.Diagnostics.Debug": "4.3.0", - "System.Diagnostics.Tools": "4.3.0", - "System.Globalization": "4.3.0", - "System.IO": "4.3.0", - "System.Reflection": "4.3.0", - "System.Resources.ResourceManager": "4.3.0", - "System.Runtime": "4.3.0", - "System.Runtime.Extensions": "4.3.0", - "System.Text.Encoding": "4.3.0", - "System.Threading": "4.3.0", - "System.Xml.ReaderWriter": "4.3.0" - } - }, "Tomlyn": { "type": "Transitive", "resolved": "0.14.3", @@ -1574,7 +953,9 @@ "type": "Project", "dependencies": { "MethodBoundaryAspect.Fody": "[2.0.148, )", + "NETStandard.Library": "[2.0.3, )", "Nncase.CodeGen": "[1.0.0, )", + "Nncase.Compiler": "[1.0.0, )", "Nncase.Core": "[1.0.0, )", "Nncase.Modules.StackVM": "[1.0.0, )", "Nncase.Passes": "[1.0.0, )", diff --git a/tests/importer/ncnn_/__init__.py b/tests/importer/ncnn_/__init__.py new file mode 100644 index 0000000000..e69de29bb2 diff --git a/tests/importer/ncnn_/basic/__init__.py b/tests/importer/ncnn_/basic/__init__.py new file mode 100644 index 0000000000..e69de29bb2 diff --git a/tests/importer/ncnn_/basic/test_conv2d.py b/tests/importer/ncnn_/basic/test_conv2d.py new file mode 100644 index 0000000000..b892594cad --- /dev/null +++ b/tests/importer/ncnn_/basic/test_conv2d.py @@ -0,0 +1,87 @@ +# Copyright 2019-2021 Canaan Inc. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# pylint: disable=invalid-name, unused-argument, import-outside-toplevel + +import pytest +import numpy as np +from ncnn_test_runner import Net, NcnnTestRunner + + +def _make_module(i_channels, i_size, k_size, o_channels, strides, padding, dilations): + w = np.random.rand(*k_size, i_channels, o_channels).astype(np.float32) - 0.5 + + net = Net() + input = net.Input("input", i_size[1], i_size[0], i_channels) + net.Convolution("conv1", input, o_channels, k_size[1], k_size[0], dilations[1], dilations[0], + strides[1], strides[0], padding[0], padding[1], padding[2], padding[3], 0.0, w) + + return net + + +i_channels = [ + 3, + 16 +] + +i_sizes = [ + [12, 24], + [38, 65] +] + +k_sizes = [ + [1, 1], + [3, 3], +] + +o_channels = [ + 1, + 8 +] + +strides = [ + (1, 1), + (5, 5) +] + +paddings = [ + (1, 1, 1, 1) +] + +padding_modes = [ + 'zeros' +] + +dilations = [ + [1, 1], + [2, 2] +] + + +@pytest.mark.parametrize('i_channels', i_channels) +@pytest.mark.parametrize('i_size', i_sizes) +@pytest.mark.parametrize('k_size', k_sizes) +@pytest.mark.parametrize('o_channels', o_channels) +@pytest.mark.parametrize('strides', strides) +@pytest.mark.parametrize('padding', paddings) +@pytest.mark.parametrize('dilations', dilations) +def test_conv2d(i_channels, i_size, k_size, o_channels, strides, padding, dilations, request): + module = _make_module(i_channels, i_size, k_size, o_channels, + strides, padding, dilations) + runner = NcnnTestRunner(request.node.name) + model_param, model_bin = runner.from_ncnn(module) + runner.run(model_param, model_bin) + + +if __name__ == "__main__": + pytest.main(['-vv', 'test_conv2d.py']) diff --git a/tests/ncnn_test_runner.py b/tests/ncnn_test_runner.py new file mode 100644 index 0000000000..37e3b9ab43 --- /dev/null +++ b/tests/ncnn_test_runner.py @@ -0,0 +1,209 @@ +from posixpath import join +from typing import Sequence +import ncnn +import shutil +import os +import numpy as np +from numpy.core.defchararray import array +from numpy.lib.function_base import select +from test_runner import * +import io + + +class Layer: + def __init__(self, type: str, name: str, inputs: Sequence[str] = [], outputs: Sequence[str] = [], params: dict = {}) -> None: + self.type = type + self.name = name + self.inputs = inputs + self.outputs = outputs + self.params = params + + def __str__(self) -> str: + s = f"{self.type} {self.name} {len(self.inputs)} {len(self.outputs)}" + s += ''.join([' ' + v for v in self.inputs]) + s += ''.join([' ' + v for v in self.outputs]) + s += ''.join([f" {k}={v}" for k, v in self.params.items()]) + return s + + def __repr__(self) -> str: + return str(self) + + +class Net: + def __init__(self) -> None: + self.layers = [] + self.bin = io.BytesIO() + self.blobs = 0 + + def Input(self, name: str, w: int, h: int, c: int) -> str: + self._add_layer("Input", name, outputs=[name], params={'0': w, '1': h, '2': c}) + return name + + def Convolution(self, name: str, input: str, outch: int, kernel_w: int, kernel_h: int, + dilation_w: int, dilation_h: int, stride_w: int, stride_h: int, + pad_left: int, pad_right: int, pad_top: int, pad_bottom: int, + pad_value: float, weights: np.ndarray, bias: np.ndarray = None) -> str: + self._add_layer("Convolution", name, inputs=[input], outputs=[name], params={ + '0': outch, + '1': kernel_w, + '11': kernel_h, + '2': dilation_w, + '12': dilation_h, + '3': stride_w, + '13': stride_h, + '4': pad_left, + '15': pad_right, + '14': pad_top, + '16': pad_bottom, + '18': pad_value, + '5': 0 if bias is None else 1, + '6': weights.size + }) + self._add_bin(0, weights) + if bias is not None: + self._add_bin(1, bias) + return name + + def Pooling(self, name: str, input: str, pooling_type: int, kernel_w: int, kernel_h: int, + stride_w: int, stride_h: int, + pad_left: int, pad_right: int, pad_top: int, pad_bottom: int, + global_pooling: bool, weights: np.ndarray, bias: np.ndarray = None) -> str: + self._add_layer("Pooling", name, inputs=[input], outputs=[name], params={ + '0': pooling_type, + '1': kernel_w, + '11': kernel_h, + '2': stride_w, + '12': stride_h, + '3': pad_left, + '13': pad_right, + '4': pad_top, + '15': pad_bottom, + '4': 1 if global_pooling else 0, + '5': 0 if bias is None else 1, + '6': weights.size + }) + self._add_bin(0, weights) + if bias is not None: + self._add_bin(1, bias) + return name + + def _add_layer(self, type: str, name: str, inputs: Sequence[str] = [], outputs: Sequence[str] = [], params: dict = []): + self.layers.append(Layer(type, name, inputs, outputs, params)) + self.blobs += len(outputs) + + def _add_bin(self, tag: int, arr: np.ndarray): + self.bin.write(tag.to_bytes(4, byteorder='little')) + self.bin.write(arr.tobytes()) + + +class NcnnTestRunner(TestRunner): + def __init__(self, case_name, overwrite_configs: str = None): + super().__init__(case_name, overwrite_configs) + self.model_type = "ncnn" + + def from_ncnn(self, net: Net): + param_file = os.path.join(self.case_dir, 'test.param') + with open(param_file, 'w') as fp: + print("7767517", file=fp) + print(f"{len(net.layers)} {net.blobs}", file=fp) + for l in net.layers: + print(str(l), file=fp) + + bin_file = os.path.join(self.case_dir, 'test.bin') + with open(bin_file, 'wb') as fb: + fb.write(net.bin.getbuffer()) + + return param_file, bin_file + + def run(self, param_file, bin_file): + if self.case_dir != os.path.dirname(param_file): + new_file = os.path.join(self.case_dir, 'test.param') + shutil.copy(param_file, new_file) + param_file = new_file + if self.case_dir != os.path.dirname(bin_file): + new_file = os.path.join(self.case_dir, 'test.bin') + shutil.copy(bin_file, new_file) + bin_file = new_file + + if not self.inputs: + self.parse_model(param_file) + + super().run([param_file, bin_file]) + + def parse_model(self, param_file: str): + all_inputs = [] + all_outputs = [] + with open(param_file, 'r') as fp: + for line in fp: + tokens = line.split(' ', 4) + if len(tokens) < 4: + continue + op_type = tokens[0] + name = tokens[1] + in_num = int(tokens[2]) + out_num = int(tokens[3]) + tokens = tokens[-1].split(' ', in_num) + inputs = tokens[:in_num] + tokens = tokens[-1].split(' ', out_num) + outputs = tokens[:out_num] + all_inputs += inputs + all_outputs += outputs + + if op_type != 'Input': + continue + param_kvs = [] + for kv in tokens[-1].split(' '): + kv_tokens = kv.split('=') + param_kvs.append((int(kv_tokens[0]), int(kv_tokens[1]))) + params = dict(param_kvs) + input_dict = {} + input_dict['name'] = outputs[0] + input_dict['dtype'] = np.float32 + shape = [params[2], params[1], params[0]] + input_dict['shape'] = shape + input_dict['model_shape'] = shape + self.inputs.append(input_dict) + self.calibs.append(copy.deepcopy(input_dict)) + + used_inputs = set(inputs) + seen_outputs = set() + for n in all_outputs: + if not n in used_inputs and not n in seen_outputs: + seen_outputs.add(n) + input_dict = {} + input_dict['name'] = n + self.outputs.append(input_dict) + + def cpu_infer(self, model_file: List[str]): + outputs = [] + with ncnn.Net() as net: + ret = net.load_param(model_file[0]) + assert ret == 0 + ret = net.load_model(model_file[1]) + assert ret == 0 + + with net.create_extractor() as ex: + for input in self.inputs: + new_value = self.transform_input( + self.data_pre_process(input['data']), "float32", "CPU")[0] + in_mat = ncnn.Mat(new_value) + ex.input(input['name'], in_mat) + if self.cfg['compile_opt']['preprocess'] and not test_utils.in_ci(): + dump_bin_file(os.path.join(self.case_dir, f'frame_input_{i}.bin'), new_value) + dump_txt_file(os.path.join(self.case_dir, f'frame_input_{i}.txt'), new_value) + + i = 0 + for output in self.outputs: + out_mat = ncnn.Mat() + ex.extract(output['name'], out_mat) + out_arr = np.array(out_mat) + out_mat.release() + outputs.append(out_arr) + if not test_utils.in_ci(): + dump_bin_file(os.path.join(self.case_dir, f'cpu_result_{i}.bin'), out_arr) + dump_txt_file(os.path.join(self.case_dir, f'cpu_result_{i}.txt'), out_arr) + i += 1 + return outputs + + def import_model(self, compiler, model_content, import_options): + compiler.import_ncnn(model_content[0], model_content[1], import_options) diff --git a/third_party/onnx/packages.lock.json b/third_party/onnx/packages.lock.json index 207b93b556..0bdbf312bd 100644 --- a/third_party/onnx/packages.lock.json +++ b/third_party/onnx/packages.lock.json @@ -16,17 +16,17 @@ }, "StyleCop.Analyzers": { "type": "Direct", - "requested": "[1.2.0-beta.435, )", - "resolved": "1.2.0-beta.435", - "contentHash": "TADk7vdGXtfTnYCV7GyleaaRTQjfoSfZXprQrVMm7cSJtJbFc1QIbWPyLvrgrfGdfHbGmUPvaN4ODKNxg2jgPQ==", + "requested": "[1.2.0-beta.507, )", + "resolved": "1.2.0-beta.507", + "contentHash": "/FtugDT66cKJJ+GGH7rNpG6UDrT4iIWz45M6lrXXHobDUFDHw+q5VgkbiR+6ffTO564ge7w6fQh/eoQhVdJO8Q==", "dependencies": { - "StyleCop.Analyzers.Unstable": "1.2.0.435" + "StyleCop.Analyzers.Unstable": "1.2.0.507" } }, "StyleCop.Analyzers.Unstable": { "type": "Transitive", - "resolved": "1.2.0.435", - "contentHash": "ouwPWZxbOV3SmCZxIRqHvljkSzkCyi1tDoMzQtDb/bRP8ctASV/iRJr+A2Gdj0QLaLmWnqTWDrH82/iP+X80Lg==" + "resolved": "1.2.0.507", + "contentHash": "gTY3IQdRqDJ4hbhSA3e/R48oE8b/OiKfvwkt1QdNVfrJK2gMHBV8ldaHJ885jxWZfllK66soa/sdcjh9bX49Tw==" } } } diff --git a/third_party/tflite/packages.lock.json b/third_party/tflite/packages.lock.json index 325adfa712..73d7544eab 100644 --- a/third_party/tflite/packages.lock.json +++ b/third_party/tflite/packages.lock.json @@ -10,17 +10,17 @@ }, "StyleCop.Analyzers": { "type": "Direct", - "requested": "[1.2.0-beta.435, )", - "resolved": "1.2.0-beta.435", - "contentHash": "TADk7vdGXtfTnYCV7GyleaaRTQjfoSfZXprQrVMm7cSJtJbFc1QIbWPyLvrgrfGdfHbGmUPvaN4ODKNxg2jgPQ==", + "requested": "[1.2.0-beta.507, )", + "resolved": "1.2.0-beta.507", + "contentHash": "/FtugDT66cKJJ+GGH7rNpG6UDrT4iIWz45M6lrXXHobDUFDHw+q5VgkbiR+6ffTO564ge7w6fQh/eoQhVdJO8Q==", "dependencies": { - "StyleCop.Analyzers.Unstable": "1.2.0.435" + "StyleCop.Analyzers.Unstable": "1.2.0.507" } }, "StyleCop.Analyzers.Unstable": { "type": "Transitive", - "resolved": "1.2.0.435", - "contentHash": "ouwPWZxbOV3SmCZxIRqHvljkSzkCyi1tDoMzQtDb/bRP8ctASV/iRJr+A2Gdj0QLaLmWnqTWDrH82/iP+X80Lg==" + "resolved": "1.2.0.507", + "contentHash": "gTY3IQdRqDJ4hbhSA3e/R48oE8b/OiKfvwkt1QdNVfrJK2gMHBV8ldaHJ885jxWZfllK66soa/sdcjh9bX49Tw==" } } } diff --git a/tools/Nncase.SourceGenerator/packages.lock.json b/tools/Nncase.SourceGenerator/packages.lock.json index 0430a3e081..50bdccb9fa 100644 --- a/tools/Nncase.SourceGenerator/packages.lock.json +++ b/tools/Nncase.SourceGenerator/packages.lock.json @@ -34,11 +34,11 @@ }, "StyleCop.Analyzers": { "type": "Direct", - "requested": "[1.2.0-beta.435, )", - "resolved": "1.2.0-beta.435", - "contentHash": "TADk7vdGXtfTnYCV7GyleaaRTQjfoSfZXprQrVMm7cSJtJbFc1QIbWPyLvrgrfGdfHbGmUPvaN4ODKNxg2jgPQ==", + "requested": "[1.2.0-beta.507, )", + "resolved": "1.2.0-beta.507", + "contentHash": "/FtugDT66cKJJ+GGH7rNpG6UDrT4iIWz45M6lrXXHobDUFDHw+q5VgkbiR+6ffTO564ge7w6fQh/eoQhVdJO8Q==", "dependencies": { - "StyleCop.Analyzers.Unstable": "1.2.0.435" + "StyleCop.Analyzers.Unstable": "1.2.0.507" } }, "Microsoft.CodeAnalysis.Common": { @@ -62,8 +62,8 @@ }, "StyleCop.Analyzers.Unstable": { "type": "Transitive", - "resolved": "1.2.0.435", - "contentHash": "ouwPWZxbOV3SmCZxIRqHvljkSzkCyi1tDoMzQtDb/bRP8ctASV/iRJr+A2Gdj0QLaLmWnqTWDrH82/iP+X80Lg==" + "resolved": "1.2.0.507", + "contentHash": "gTY3IQdRqDJ4hbhSA3e/R48oE8b/OiKfvwkt1QdNVfrJK2gMHBV8ldaHJ885jxWZfllK66soa/sdcjh9bX49Tw==" }, "System.Buffers": { "type": "Transitive", diff --git a/tools/StyleCopAnalyzers.ruleset b/tools/StyleCopAnalyzers.ruleset index 387a2e1ac9..d93b2053f8 100644 --- a/tools/StyleCopAnalyzers.ruleset +++ b/tools/StyleCopAnalyzers.ruleset @@ -1,5 +1,5 @@  - + @@ -86,7 +86,7 @@ - + @@ -177,6 +177,7 @@ + diff --git a/tools/stackvm_gen/IsaGen/packages.lock.json b/tools/stackvm_gen/IsaGen/packages.lock.json index bbcfe63a45..6440c55973 100644 --- a/tools/stackvm_gen/IsaGen/packages.lock.json +++ b/tools/stackvm_gen/IsaGen/packages.lock.json @@ -27,11 +27,11 @@ }, "StyleCop.Analyzers": { "type": "Direct", - "requested": "[1.2.0-beta.435, )", - "resolved": "1.2.0-beta.435", - "contentHash": "TADk7vdGXtfTnYCV7GyleaaRTQjfoSfZXprQrVMm7cSJtJbFc1QIbWPyLvrgrfGdfHbGmUPvaN4ODKNxg2jgPQ==", + "requested": "[1.2.0-beta.507, )", + "resolved": "1.2.0-beta.507", + "contentHash": "/FtugDT66cKJJ+GGH7rNpG6UDrT4iIWz45M6lrXXHobDUFDHw+q5VgkbiR+6ffTO564ge7w6fQh/eoQhVdJO8Q==", "dependencies": { - "StyleCop.Analyzers.Unstable": "1.2.0.435" + "StyleCop.Analyzers.Unstable": "1.2.0.507" } }, "Microsoft.AspNetCore.Mvc.Razor.Extensions": { @@ -169,8 +169,8 @@ }, "StyleCop.Analyzers.Unstable": { "type": "Transitive", - "resolved": "1.2.0.435", - "contentHash": "ouwPWZxbOV3SmCZxIRqHvljkSzkCyi1tDoMzQtDb/bRP8ctASV/iRJr+A2Gdj0QLaLmWnqTWDrH82/iP+X80Lg==" + "resolved": "1.2.0.507", + "contentHash": "gTY3IQdRqDJ4hbhSA3e/R48oE8b/OiKfvwkt1QdNVfrJK2gMHBV8ldaHJ885jxWZfllK66soa/sdcjh9bX49Tw==" }, "System.Buffers": { "type": "Transitive", From 2fe80ac0d0f5648235aed2968063b3d319203001 Mon Sep 17 00:00:00 2001 From: zhangyang2057 Date: Wed, 20 Sep 2023 10:38:01 +0800 Subject: [PATCH 20/25] Fix benchmark test flow with dynamic shape. (#1095) * Fix benchmark test with dynamic shape. - Extract actual fps only for dynamic model - Fix tflite test runner to run dynamic model * Apply code-format changes * trigger CI again --------- Co-authored-by: zhangyang2057 --- python/nncase/__init__.py | 2 +- tests/compare_util.py | 2 +- tests/inference.py | 64 ++++++++++++++++++------------------- tests/ncnn_test_runner.py | 12 ++++--- tests/test_runner.py | 2 +- tests/tflite_test_runner.py | 35 +++++++++++--------- 6 files changed, 62 insertions(+), 55 deletions(-) diff --git a/python/nncase/__init__.py b/python/nncase/__init__.py index 4d0c57042c..0663332e10 100644 --- a/python/nncase/__init__.py +++ b/python/nncase/__init__.py @@ -192,7 +192,7 @@ def import_tflite(self, model_content: bytes, options: ImportOptions) -> None: self._compile_options.input_format = "tflite" self._import_tflite_module(model_content) - def import_ncnn(self, model_param: bytes, model_bin : bytes, options: ImportOptions) -> None: + def import_ncnn(self, model_param: bytes, model_bin: bytes, options: ImportOptions) -> None: self._compile_options.input_format = "ncnn" self._import_ncnn_module(model_param, model_bin) diff --git a/tests/compare_util.py b/tests/compare_util.py index 93f19d8827..73282e3d0a 100644 --- a/tests/compare_util.py +++ b/tests/compare_util.py @@ -90,7 +90,7 @@ def compare_ndarray(expected: np.ndarray, if expected.size == actual.size: similarity = similarity_func[similarity_name](expected.flatten(), actual.flatten()) else: - raise ValueError("The number of elements in gt and result not match\n") + return False, f"The numbers of elements in gt({expected.size}) and result({actual.size}) are not match.\n" if dump_hist: y, x = np.histogram(expected - actual, 100) diff --git a/tests/inference.py b/tests/inference.py index f0a4912ecb..e511ead3a8 100644 --- a/tests/inference.py +++ b/tests/inference.py @@ -197,28 +197,28 @@ def run_evb(self, target, kmodel, compile_opt, infer_dir): if header_dict['type'].find('finish') != -1: if self.cfg['infer_report_opt']['enabled']: - - # update trace info - model_name = self.cfg['infer_report_opt']['model_name'] - infer_result = f'0:{model_name} :\n' + detail - trace_file = search_file(infer_dir, 'trace_info.py') - assert(trace_file != '') - update_trace_info(infer_result, trace_file) - - # roofline fps/mac usage - estimate_file = search_file(infer_dir, 'estimate_fps.py') - assert(estimate_file != '') - - mac_file = search_file(infer_dir, 'mac.csv') - assert(mac_file != '') - - cmd_status, cmd_result = subprocess.getstatusoutput( - f'python3 {estimate_file} {mac_file}') - assert(cmd_status == 0) - data = cmd_result.split(',') - assert(len(data) >= 3) - self.infer_report_dict['roofline_fps'] = data[1].split(':')[-1].strip() - self.infer_report_dict['roofline_mac_usage'] = data[2].split(':')[-1].strip() + if not self.dynamic: + # update trace info + model_name = self.cfg['infer_report_opt']['model_name'] + infer_result = f'0:{model_name} :\n' + detail + trace_file = search_file(infer_dir, 'trace_info.py') + assert(trace_file != '') + update_trace_info(infer_result, trace_file) + + # roofline fps/mac usage + estimate_file = search_file(infer_dir, 'estimate_fps.py') + assert(estimate_file != '') + + mac_file = search_file(infer_dir, 'mac.csv') + assert(mac_file != '') + + cmd_status, cmd_result = subprocess.getstatusoutput( + f'python3 {estimate_file} {mac_file}') + assert(cmd_status == 0) + data = cmd_result.split(',') + assert(len(data) >= 3) + self.infer_report_dict['roofline_fps'] = data[1].split(':')[-1].strip() + self.infer_report_dict['roofline_mac_usage'] = data[2].split(':')[-1].strip() # actual fps fps_pattern = re.compile( @@ -234,15 +234,16 @@ def run_evb(self, target, kmodel, compile_opt, infer_dir): round(1000 / float(match.group(2)), 3)) break - # actual mac usage - draw_trace_file = search_file(infer_dir, 'draw_trace.py') - assert(draw_trace_file != '') - cmd_status, cmd_result = subprocess.getstatusoutput( - f'python3 {draw_trace_file} {mac_file}') - assert(cmd_status == 0) - data = cmd_result.split(',') - assert(len(data) >= 1) - self.infer_report_dict['actual_mac_usage'] = data[0].split(':')[-1].strip() + if not self.dynamic: + # actual mac usage + draw_trace_file = search_file(infer_dir, 'draw_trace.py') + assert(draw_trace_file != '') + cmd_status, cmd_result = subprocess.getstatusoutput( + f'python3 {draw_trace_file} {mac_file}') + assert(cmd_status == 0) + data = cmd_result.split(',') + assert(len(data) >= 1) + self.infer_report_dict['actual_mac_usage'] = data[0].split(':')[-1].strip() client_socket.sendall(f"pls send outputs".encode()) @@ -273,7 +274,6 @@ def run_evb(self, target, kmodel, compile_opt, infer_dir): if self.cfg['infer_report_opt']['enabled']: self.infer_report_dict['result'] = 'Fail' self.infer_report_dict['remark'] = detail.replace('\n', '
') - # self.infer_report_dict['remark'] = detail prefix, suffix = os.path.splitext(self.infer_report_file) json_file = f'{prefix}_{os.path.basename(self.case_dir)}{suffix}' dump_dict_to_json(self.infer_report_dict, json_file) diff --git a/tests/ncnn_test_runner.py b/tests/ncnn_test_runner.py index 37e3b9ab43..71635f4473 100644 --- a/tests/ncnn_test_runner.py +++ b/tests/ncnn_test_runner.py @@ -65,9 +65,9 @@ def Convolution(self, name: str, input: str, outch: int, kernel_w: int, kernel_h return name def Pooling(self, name: str, input: str, pooling_type: int, kernel_w: int, kernel_h: int, - stride_w: int, stride_h: int, - pad_left: int, pad_right: int, pad_top: int, pad_bottom: int, - global_pooling: bool, weights: np.ndarray, bias: np.ndarray = None) -> str: + stride_w: int, stride_h: int, + pad_left: int, pad_right: int, pad_top: int, pad_bottom: int, + global_pooling: bool, weights: np.ndarray, bias: np.ndarray = None) -> str: self._add_layer("Pooling", name, inputs=[input], outputs=[name], params={ '0': pooling_type, '1': kernel_w, @@ -189,8 +189,10 @@ def cpu_infer(self, model_file: List[str]): in_mat = ncnn.Mat(new_value) ex.input(input['name'], in_mat) if self.cfg['compile_opt']['preprocess'] and not test_utils.in_ci(): - dump_bin_file(os.path.join(self.case_dir, f'frame_input_{i}.bin'), new_value) - dump_txt_file(os.path.join(self.case_dir, f'frame_input_{i}.txt'), new_value) + dump_bin_file(os.path.join( + self.case_dir, f'frame_input_{i}.bin'), new_value) + dump_txt_file(os.path.join( + self.case_dir, f'frame_input_{i}.txt'), new_value) i = 0 for output in self.outputs: diff --git a/tests/test_runner.py b/tests/test_runner.py index 2207ffefda..d2ff3c4783 100644 --- a/tests/test_runner.py +++ b/tests/test_runner.py @@ -52,7 +52,7 @@ def __init__(self, case_name, override_cfg: str = None) -> None: # [n, c, h, w].zip default_shape => [(n, 1), (c, 1), (h, 48), (w, 48)] self.default_shape = [1, 1, 48, 48, 24, 24] self.shape_vars = {} - # used for tag dynamic model for onnx simplify + # used for tag dynamic model self.dynamic = False if self.cfg['infer_report_opt']['enabled']: diff --git a/tests/tflite_test_runner.py b/tests/tflite_test_runner.py index f68236d287..dffa694b72 100644 --- a/tests/tflite_test_runner.py +++ b/tests/tflite_test_runner.py @@ -9,6 +9,7 @@ class TfliteTestRunner(TestRunner): def __init__(self, case_name, overwrite_configs: str = None): super().__init__(case_name, overwrite_configs) self.model_type = "tflite" + self.interp = None def from_tensorflow(self, module): # export model @@ -42,33 +43,38 @@ def run(self, model_file): super().run(model_file) def parse_model(self, model_path: str): - interp = tf.lite.Interpreter(model_path=model_path) + self.interp = tf.lite.Interpreter(model_path=model_path) - def translate_shape(shape, default_shape): - return [(i if i > 0 else d) for i, d in zip(shape, default_shape)] + def translate_shape(shape): + return [i if i > 0 else self.shape_vars["-1"] for i in shape] - for item in interp.get_input_details(): + for item in self.interp.get_input_details(): input_dict = {} input_dict['index'] = item['index'] input_dict['name'] = item['name'] input_dict['dtype'] = item['dtype'] - if item['shape_signature'].size == 0: + + if len(self.shape_vars) == 0: + # fixed shape shape = item['shape'] else: + # dynamic shape shape = item['shape_signature'] - # todo: tflite not support set shape var for model with dynamic shape - # don't have model with shape var to debug this feature + if len(shape) <= 4: - input_dict['model_shape'] = translate_shape(shape, self.default_shape) + input_dict['model_shape'] = translate_shape(shape) else: if -1 in shape: raise "tflite test_runner not supported dynamic shape which rank > 4" input_dict['model_shape'] = shape + + if -1 in shape: + self.dynamic = True + self.interp.resize_tensor_input(item['index'], input_dict['model_shape']) self.inputs.append(input_dict) self.calibs.append(copy.deepcopy(input_dict)) - # self.dump_range_data.append(copy.deepcopy(input_dict)) - for item in interp.get_output_details(): + for item in self.interp.get_output_details(): output_dict = {} output_dict['index'] = item['index'] output_dict['name'] = item['name'] @@ -77,22 +83,21 @@ def translate_shape(shape, default_shape): self.outputs.append(output_dict) def cpu_infer(self, model_file: bytes): - interp = tf.lite.Interpreter(model_path=model_file) - interp.allocate_tensors() + self.interp.allocate_tensors() for idx, value in enumerate(self.inputs): new_value = self.transform_input( self.data_pre_process(value['data']), "float32", "CPU")[0] - interp.set_tensor(value["index"], new_value) + self.interp.set_tensor(value["index"], new_value) if self.cfg['compile_opt']['preprocess'] and not test_utils.in_ci(): dump_bin_file(os.path.join(self.case_dir, f'frame_input_{idx}.bin'), new_value) dump_txt_file(os.path.join(self.case_dir, f'frame_input_{idx}.txt'), new_value) - interp.invoke() + self.interp.invoke() i = 0 results = [] for output in self.outputs: - data = interp.get_tensor(output['index']) + data = self.interp.get_tensor(output['index']) results.append(data) if not test_utils.in_ci(): dump_bin_file(os.path.join(self.case_dir, f'cpu_result_{i}.bin'), data) From b0d4962bd481ecc05642633aa5efb01a8fa6a317 Mon Sep 17 00:00:00 2001 From: zhangyang2057 Date: Thu, 21 Sep 2023 13:52:19 +0800 Subject: [PATCH 21/25] Escape some special characters for benchmark remark. (#1096) * Escape some special characters for benchmark remark. * Do not show exception detail as there are some non ascii characters which html table does not support. --- tests/inference.py | 3 ++- tests/nuc_proxy.py | 2 +- tests/test_runner.py | 4 +++- tests/update_trace_info.py | 5 ----- 4 files changed, 6 insertions(+), 8 deletions(-) diff --git a/tests/inference.py b/tests/inference.py index e511ead3a8..fdf42925e3 100644 --- a/tests/inference.py +++ b/tests/inference.py @@ -10,6 +10,7 @@ import time import subprocess from update_trace_info import * +from html import escape def data_shape_list_string(data): @@ -273,7 +274,7 @@ def run_evb(self, target, kmodel, compile_opt, infer_dir): if self.cfg['infer_report_opt']['enabled']: self.infer_report_dict['result'] = 'Fail' - self.infer_report_dict['remark'] = detail.replace('\n', '
') + self.infer_report_dict['remark'] = escape(detail) prefix, suffix = os.path.splitext(self.infer_report_file) json_file = f'{prefix}_{os.path.basename(self.case_dir)}{suffix}' dump_dict_to_json(self.infer_report_dict, json_file) diff --git a/tests/nuc_proxy.py b/tests/nuc_proxy.py index 66253657dc..0aadb5b324 100644 --- a/tests/nuc_proxy.py +++ b/tests/nuc_proxy.py @@ -160,7 +160,7 @@ def infer_worker(target): if ret.find('terminate') != -1 or ret.find('Exception') != -1: err = 'infer exception' target.logger.error(err) - msg = f'{err}: {ret}'.encode() + msg = f'{err}'.encode() dict['type'] = 'exception' dict['len'] = len(msg) conn.sendall(json.dumps(dict).encode()) diff --git a/tests/test_runner.py b/tests/test_runner.py index d2ff3c4783..9c2ba46135 100644 --- a/tests/test_runner.py +++ b/tests/test_runner.py @@ -21,6 +21,7 @@ from evaluator import * from compare_util import * from test_utils import * +from html import escape class TestRunner(Evaluator, Inference, metaclass=ABCMeta): @@ -271,7 +272,8 @@ def run(self, model_file: Union[List[str], str]): if stage == 'infer' and self.cfg['infer_report_opt']['enabled']: self.infer_report_dict['result'] = 'Pass' if judge else 'Fail' - self.infer_report_dict['remark'] = result.replace('\n', '
') + self.infer_report_dict['remark'] = escape( + result).replace('\n', '
') prefix, suffix = os.path.splitext(self.infer_report_file) json_file = f'{prefix}_{os.path.basename(self.case_dir)}{suffix}' dump_dict_to_json(self.infer_report_dict, json_file) diff --git a/tests/update_trace_info.py b/tests/update_trace_info.py index 71cb6f85a9..7cf107f01f 100644 --- a/tests/update_trace_info.py +++ b/tests/update_trace_info.py @@ -70,15 +70,12 @@ def update_trace_info(infer_result: str, info_file: str): line = buf.readline() if not line: break - print('line = {0}'.format(line)) if status == Status.find_titile: title = find_titile(line) - print('title = {0}'.format(title)) if title: status = Status.find_time item_num = find_items(info_file) - print('item_num = {0}'.format(item_num)) if item_num == -1 or item_num == 0: item_num = -1 status = Status.find_titile @@ -86,12 +83,10 @@ def update_trace_info(infer_result: str, info_file: str): if status is Status.find_time: time = find_time(line) - print('time = {0}'.format(time)) if time: times.append(time) if (len(times) == item_num): update_items(info_file, times) - print('time updated!') times.clear() status = Status.find_titile continue From 4c2850c3bba7b837441c583bd5c519ade8b5d798 Mon Sep 17 00:00:00 2001 From: FusionBolt <59008347+FusionBolt@users.noreply.github.com> Date: Fri, 22 Sep 2023 10:03:29 +0800 Subject: [PATCH 22/25] Fix Enable Nop (#1097) * replace ENABLE_NOP with SKIP_NOP * Apply code-format changes --------- Co-authored-by: FusionBolt --- src/Native/src/kernels/stackvm/tensor_ops.cpp | 16 +++++++--------- 1 file changed, 7 insertions(+), 9 deletions(-) diff --git a/src/Native/src/kernels/stackvm/tensor_ops.cpp b/src/Native/src/kernels/stackvm/tensor_ops.cpp index 5357771fb5..0a4d6d1125 100644 --- a/src/Native/src/kernels/stackvm/tensor_ops.cpp +++ b/src/Native/src/kernels/stackvm/tensor_ops.cpp @@ -27,8 +27,6 @@ using namespace nncase::kernels::stackvm; using namespace nncase::runtime; using namespace nncase::runtime::stackvm; -// #define ENABLE_NOP - result nncase::kernels::stackvm::batch_normalization( value_t input, value_t scale, value_t bias, value_t input_mean, value_t input_var, value_t epsilon, [[maybe_unused]] value_t momentum, @@ -573,11 +571,11 @@ result nncase::kernels::stackvm::one_hot(one_hot_mode_t one_hot_mode, } inline bool is_nop_pad([[maybe_unused]] const paddings_t &paddings) { -#ifdef ENABLE_NOP +#ifdef SKIP_NOP + return false; +#else return std::all_of(paddings.begin(), paddings.end(), [](const padding &p) { return p.sum() == 0; }); -#else - return false; #endif } @@ -735,11 +733,11 @@ result nncase::kernels::stackvm::require( } inline bool is_nop_pad([[maybe_unused]] const std::vector &paddings) { -#ifdef ENABLE_NOP +#ifdef SKIP_NOP + return false; +#else return std::all_of(paddings.begin(), paddings.end(), [](auto &p) { return p == 0; }); -#else - return false; #endif } @@ -921,7 +919,7 @@ inline bool is_nop_slice([[maybe_unused]] const axes_t &begin, [[maybe_unused]] const axes_t &axes, [[maybe_unused]] const axes_t &strides, [[maybe_unused]] const dims_t &in_shape) { -#ifndef ENABLE_NOP +#ifdef SKIP_NOP return false; #else if (begin.size() != in_shape.size()) { From 4df2cd9e94fb3cca845bb4f855d8d28aa30e3fe7 Mon Sep 17 00:00:00 2001 From: huochenghai Date: Fri, 22 Sep 2023 11:20:00 +0800 Subject: [PATCH 23/25] fix euclidean calc (#1094) * fix euclidean calc * Apply code-format changes --------- Co-authored-by: xhuohai Co-authored-by: FusionBolt <59008347+FusionBolt@users.noreply.github.com> --- tests/compare_util.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/tests/compare_util.py b/tests/compare_util.py index 73282e3d0a..598c46488c 100644 --- a/tests/compare_util.py +++ b/tests/compare_util.py @@ -15,7 +15,7 @@ def cosine(gt: np.ndarray, pred: np.ndarray, *args): def euclidean(gt: np.ndarray, pred: np.ndarray, *args): - return np.linalg.norm(gt - pred, 2)**2 + return np.linalg.norm(gt.reshape(-1) - pred.reshape(-1)) def allclose(gt: np.ndarray, pred: np.ndarray, thresh: float): @@ -71,7 +71,7 @@ def compare_binfile(result_path: Tuple[str, str], np.savetxt(str(p.parent / (p.stem + '_hist.csv')), np.stack((x[:-1], y)).T, fmt='%f', delimiter=',') similarity_info = f"\n{similarity_name} similarity = {similarity}, threshold = {threshold}\n" - if similarity_name in ['cosine', 'euclidean', 'segment']: + if similarity_name in ['cosine', 'segment']: compare_op = lt else: compare_op = gt @@ -97,7 +97,7 @@ def compare_ndarray(expected: np.ndarray, np.savetxt(dump_file, np.stack((x[:-1], y)).T, fmt='%f', delimiter=',') similarity_info = f"{similarity_name} similarity = {similarity}, threshold = {threshold}\n" - if similarity_name in ['cosine', 'euclidean', 'segment']: + if similarity_name in ['cosine', 'segment']: compare_op = lt else: compare_op = gt From a6c39af94787b74969d2ec153089daa39f480391 Mon Sep 17 00:00:00 2001 From: FusionBolt <59008347+FusionBolt@users.noreply.github.com> Date: Fri, 22 Sep 2023 12:30:31 +0800 Subject: [PATCH 24/25] Fix BucketPad (#1098) * fix bucket pad * Apply code-format changes --------- Co-authored-by: FusionBolt Co-authored-by: zhangyang2057 --- src/Native/src/kernels/stackvm/tensor_ops.cpp | 29 +++++++++++++++---- 1 file changed, 23 insertions(+), 6 deletions(-) diff --git a/src/Native/src/kernels/stackvm/tensor_ops.cpp b/src/Native/src/kernels/stackvm/tensor_ops.cpp index 0a4d6d1125..4fa7bc4882 100644 --- a/src/Native/src/kernels/stackvm/tensor_ops.cpp +++ b/src/Native/src/kernels/stackvm/tensor_ops.cpp @@ -761,13 +761,30 @@ result nncase::kernels::stackvm::bucket_pad( compute_size(pads_shape) * sizeof(int)); try_var(pads, hrt::create(dt_int32, pads_shape, span, false, host_runtime_tensor::pool_cpu_only)); - auto pad_value = 0; - auto data = gsl::span(reinterpret_cast(&pad_value), - in_tensor->dtype()->size_bytes()); - try_var(pad_v, hrt::create(in_tensor->dtype()->typecode(), dims_t{}, data, - false, host_runtime_tensor::pool_cpu_only)); - return nncase::kernels::stackvm::pad(pad_mode_t::constant, input, +#define RUN_PAD \ + auto data = gsl::span(reinterpret_cast(&pad_value), \ + in_tensor->dtype()->size_bytes()); \ + try_var(pad_v, hrt::create(in_tensor->dtype()->typecode(), dims_t{}, data, \ + false, host_runtime_tensor::pool_cpu_only)); \ + return nncase::kernels::stackvm::pad(pad_mode_t::constant, input, \ pads.impl(), pad_v.impl(), output); + + if (runtime::get_bytes(in_tensor->dtype()) == 1) { + auto pad_value = (int8_t)0; + RUN_PAD; + } else if (runtime::get_bytes(in_tensor->dtype()) == 2) { + auto pad_value = (int16_t)0; + RUN_PAD; + } + if (runtime::get_bytes(in_tensor->dtype()) == 4) { + auto pad_value = (int32_t)0; + RUN_PAD; + } + if (runtime::get_bytes(in_tensor->dtype()) == 8) { + auto pad_value = (int64_t)0; + RUN_PAD; + } + return err(std::errc::not_supported); } result From e76b4781ab96c9868ed17e4413997fd8d7bb501d Mon Sep 17 00:00:00 2001 From: zhangyang2057 Date: Fri, 22 Sep 2023 15:43:00 +0800 Subject: [PATCH 25/25] fix nncase version suffix. (#1099) --- CMakeLists.txt | 17 ++++++++++++++--- 1 file changed, 14 insertions(+), 3 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 05ab14e495..937f2bec33 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -12,12 +12,23 @@ endif() if(NOT DEFINED NNCASE_VERSION_SUFFIX) find_package (Git) + execute_process( - COMMAND ${GIT_EXECUTABLE} describe --always --dirty + COMMAND ${GIT_EXECUTABLE} describe --always --dirty --tag WORKING_DIRECTORY ${CMAKE_SOURCE_DIR} - OUTPUT_VARIABLE GIT_DESC + OUTPUT_VARIABLE GIT_TAG OUTPUT_STRIP_TRAILING_WHITESPACE) - set(NNCASE_VERSION_SUFFIX "-${GIT_DESC}") + + if ("v${NNCASE_VERSION}" STREQUAL ${GIT_TAG}) + set(NNCASE_VERSION_SUFFIX "") + else() + execute_process( + COMMAND ${GIT_EXECUTABLE} describe --always --dirty + WORKING_DIRECTORY ${CMAKE_SOURCE_DIR} + OUTPUT_VARIABLE GIT_DESC + OUTPUT_STRIP_TRAILING_WHITESPACE) + set(NNCASE_VERSION_SUFFIX "-${GIT_DESC}") + endif() endif() if (NOT PACKAGE_VERSION)