diff --git a/tools/onnx-subgraph/CMakeLists.txt b/tools/onnx-subgraph/CMakeLists.txt new file mode 100644 index 00000000000..730f2485d2e --- /dev/null +++ b/tools/onnx-subgraph/CMakeLists.txt @@ -0,0 +1,30 @@ +# cmake version dependency +cmake_minimum_required(VERSION 3.10) + +set(ONNX_SUGRAPH_FILES + extract_onnx.py + test_model_download.sh + subgraphs_ios.txt + ) + + foreach(ONNX_SUGRAPH IN ITEMS ${ONNX_SUGRAPH_FILES}) + set(ONNX_SUGRAPH_FILE ${ONNX_SUGRAPH}) + set(ONNX_SUGRAPH_SRC "${CMAKE_CURRENT_SOURCE_DIR}/${ONNX_SUGRAPH_FILE}") + set(ONNX_SUGRAPH_BIN "${CMAKE_CURRENT_BINARY_DIR}/scripts/${ONNX_SUGRAPH_FILE}") + set(ONNX_SUGRAPH_TARGET "${ONNX_SUGRAPH}_target") + + add_custom_command(OUTPUT ${ONNX_SUGRAPH_BIN} + COMMAND ${CMAKE_COMMAND} -E copy "${ONNX_SUGRAPH_SRC}" "${ONNX_SUGRAPH_BIN}" + DEPENDS ${ONNX_SUGRAPH_SRC} + COMMENT "Generate ${ONNX_SUGRAPH_BIN}" + ) + + add_custom_target(${ONNX_SUGRAPH_TARGET} ALL DEPENDS ${ONNX_SUGRAPH_BIN}) + + install(FILES ${ONNX_SUGRAPH_BIN} + PERMISSIONS OWNER_WRITE OWNER_READ OWNER_EXECUTE + GROUP_READ GROUP_EXECUTE + WORLD_READ WORLD_EXECUTE + DESTINATION bin) + + endforeach(ONNX_SUGRAPH) diff --git a/tools/onnx-subgraph/Readme.md b/tools/onnx-subgraph/Readme.md new file mode 100644 index 00000000000..44a054d3c11 --- /dev/null +++ b/tools/onnx-subgraph/Readme.md @@ -0,0 +1,56 @@ +# onnx_autosubgraph +onnx-subgraph tool provides model auto partitionioning of onnx model to several sub models by +operator, performance and model size limitations,with the order and input / output names of +sub models + +# How to build the onnx-subgraph +## OS environment dependence + 1. ubuntu >=20.04 + 2. GCC >= 9.4.0 + 3. cmake >= 3.10 + 4. python >= 3.8 + 5. apt-get install libprotobuf-dev protobuf-compiler libjsoncpp-dev + +## Python packages dependence + onnx 1.16.0 + onnxruntime 1.18.1 + onnxsim 0.4.36 + torch 2.3.1 + scikit-image + scikit-learn + pandas + tqdm + +## building the onnx-subgraph + 1. cd onnx-subgraph + 2. mkdir build & cd build + 3. cmake .. & make + 4. we can get following output at ./build + └── scripts + ├── extract_onnx.py + └── test_model_download.sh + └── subgraphs_ios.txt + +# How to use the onnx-subgraph +## Pre-steps +### Download the test AI models + 1. bash scripts/test_model_download.sh, then "resnet-test.onnx" will be got in ./build + 2. you can change to any other onnx files as your needs, or edit the download link in + "scripts/test_model_download.sh" + +## Parse the onnx model + note: subgraphs_ios.txt will be generated in future code, suppose we already have it as + the example file now + +## Split the onnx model to subgraphs + 1. edit the config path and model file path at ./scripts/extract_onnx.py + e.g.: extract_onnx_lib.split_onnx_ios('./scripts/subgraphs_ios.txt','./resnet-test.onnx') + 2. python scripts/extract_onnx.py, after extraction done, the subgraphs will be saved + at './subgraphs' + subgraphs + ├── CPU + │   ├── CPUsubgraph0.onnx + │   └── CPUsubgraph1.onnx + └── NPU + ├── NPUsubgraph0.onnx + └── NPUsubgraph1.onnx diff --git a/tools/onnx-subgraph/extract_onnx.py b/tools/onnx-subgraph/extract_onnx.py new file mode 100644 index 00000000000..4208fdde84d --- /dev/null +++ b/tools/onnx-subgraph/extract_onnx.py @@ -0,0 +1,66 @@ +# Copyright (c) 2025 Samsung Electronics Co., Ltd. All Rights Reserved +# +# 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. + +import onnx +import re +import os + + +def splitsubgraph_ios(iofile): + iolist = re.split('--input-name |;--output-name ', iofile) + in_ = iolist[1].split(';') + out_ = iolist[2].split(';') + del out_[-1] + type = iolist[0].split('subgraph')[0] + return in_, out_, type + + +def split_onnx_ios(instrfile, input_path='./resnet-test.onnx', out_folder='subgraphs/'): + if not os.path.exists(input_path): + print(input_path + " not exist") + return + + model = onnx.load(input_path) + onnx.checker.check_model(input_path) + for output in model.graph.output: + model.graph.value_info.append(output) + onnx.save(model, input_path) + f1 = open(instrfile, "r") + lines = f1.readlines() + cpu_count = 0 + npu_count = 0 + count = 0 + if not os.path.exists(out_folder): + os.makedirs(out_folder) + for line in lines: + input_names, output_names, type = splitsubgraph_ios(line) + if (type == 'CPU'): + count = cpu_count + cpu_count = cpu_count + 1 + else: + count = npu_count + npu_count = npu_count + 1 + output_path_folder = out_folder + if not os.path.exists(output_path_folder): + os.makedirs(output_path_folder) + output_path = output_path_folder + type + 'subgraph' + str(count) + '.onnx' + if ((input_names != ['']) and (output_names != [''])): + onnx.utils.extract_model(input_path, output_path, input_names, output_names) + print("succeed", count) + count = count + 1 + f1.close() + + +if __name__ == "__main__": + split_onnx_ios('./scripts/subgraphs_ios.txt', './resnet-test.onnx') diff --git a/tools/onnx-subgraph/subgraphs_ios.txt b/tools/onnx-subgraph/subgraphs_ios.txt new file mode 100644 index 00000000000..9dfdc95e32e --- /dev/null +++ b/tools/onnx-subgraph/subgraphs_ios.txt @@ -0,0 +1,4 @@ +NPUsubgraph0: order0--input-name x;--output-name /stem/conv3/bn/act/Mul_output_0; +NPUsubgraph1: order2--input-name /stem/pool/MaxPool_output_0;--output-name /stages/stages.3/stages.3.1/act/Mul_output_0; +CPUsubgraph0: order1--input-name /stem/conv3/bn/act/Mul_output_0;--output-name /stem/pool/MaxPool_output_0; +CPUsubgraph1: order3--input-name /stages/stages.3/stages.3.1/act/Mul_output_0;--output-name 316; diff --git a/tools/onnx-subgraph/test_model_download.sh b/tools/onnx-subgraph/test_model_download.sh new file mode 100644 index 00000000000..d6597d2dd79 --- /dev/null +++ b/tools/onnx-subgraph/test_model_download.sh @@ -0,0 +1,16 @@ +pip install onnx onnxsim + +if [ ! -d "./models/" ];then + mkdir ./models/ + else + echo "./models path existing" +fi + +cd ./models +wget https://media.githubusercontent.com/media/onnx/models/refs/heads/main/Computer_Vision/resnext26ts_Opset16_timm/resnext26ts_Opset16.onnx --no-check-certificate +#wget https://media.githubusercontent.com/media/onnx/models/refs/heads/main/Natural_Language_Processing/xmod_Opset16_transformers/xmod_Opset16.onnx --no-check-certificate + +onnxsim resnext26ts_Opset16.onnx ../resnet-test.onnx +#onnxsim xmod_Opset16.onnx ../xmod-transformer-test.onnx + +cd ..