From d35ea904798313cec54ca8baf3aa1d11358d19f8 Mon Sep 17 00:00:00 2001 From: xiaowuhu Date: Fri, 5 May 2023 16:01:57 +0800 Subject: [PATCH 1/4] upgrade protobuf to 3.20.2 (#257) * upgrade protobuf Signed-off-by: xiaowuhu * downgrade to 3.20.2 Signed-off-by: xiaowuhu * Update linux-conda-CI.yml Signed-off-by: xiaowuhu --------- Signed-off-by: xiaowuhu --- .azure-pipelines/linux-conda-CI.yml | 4 ++-- .azure-pipelines/win32-conda-CI.yml | 3 ++- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/.azure-pipelines/linux-conda-CI.yml b/.azure-pipelines/linux-conda-CI.yml index a782662..6675d37 100644 --- a/.azure-pipelines/linux-conda-CI.yml +++ b/.azure-pipelines/linux-conda-CI.yml @@ -10,7 +10,7 @@ jobs: - job: 'Test' pool: - vmImage: 'Ubuntu-18.04' + vmImage: 'Ubuntu-latest' strategy: matrix: Python381: @@ -53,8 +53,8 @@ jobs: - script: | python -m pip install --upgrade pip conda config --set always_yes yes --set changeps1 no - conda install -c conda-forge protobuf conda install -c conda-forge numpy + pip install protobuf==3.20.2 pip install pytest displayName: 'Install dependencies' diff --git a/.azure-pipelines/win32-conda-CI.yml b/.azure-pipelines/win32-conda-CI.yml index 92034a1..d0ddffb 100644 --- a/.azure-pipelines/win32-conda-CI.yml +++ b/.azure-pipelines/win32-conda-CI.yml @@ -36,7 +36,7 @@ jobs: - powershell: Write-Host "##vso[task.prependpath]$env:CONDA\Scripts" displayName: Add conda to PATH - - script: conda create --yes --quiet --name py$(python.version) -c conda-forge python=$(python.version) protobuf numpy + - script: conda create --yes --quiet --name py$(python.version) -c conda-forge python=$(python.version) numpy displayName: Create Anaconda environment - script: | @@ -44,6 +44,7 @@ jobs: pip install onnxruntime pip install onnxmltools pip install %ONNX_PATH% + pip install protobuf==3.20.2 pip install pytest pip install -e . displayName: 'Install dependencies' From 8c81a0e7ea2381d0fc98f13a247d17f3eaa9ec25 Mon Sep 17 00:00:00 2001 From: xiaowuhu Date: Thu, 11 May 2023 13:28:07 +0800 Subject: [PATCH 2/4] Update nightly-CI.yml (#258) Signed-off-by: xiaowuhu --- .azure-pipelines/nightly-CI.yml | 32 +++++++++++--------------------- 1 file changed, 11 insertions(+), 21 deletions(-) diff --git a/.azure-pipelines/nightly-CI.yml b/.azure-pipelines/nightly-CI.yml index e479713..8794db2 100644 --- a/.azure-pipelines/nightly-CI.yml +++ b/.azure-pipelines/nightly-CI.yml @@ -7,21 +7,9 @@ jobs: - job: 'Linux' pool: - vmImage: 'Ubuntu-18.04' + vmImage: 'Ubuntu-latest' strategy: matrix: - Python36: - python.version: '3.6' - ONNX_PATH: onnx==1.5.0 - - Python37: - python.version: '3.7' - ONNX_PATH: onnx==1.6.0 - - Python381: - python.version: '3.8' - ONNX_PATH: onnx==1.7.0 - Python382: python.version: '3.8' ONNX_PATH: onnx==1.8.0 @@ -34,6 +22,10 @@ jobs: python.version: '3.9' ONNX_PATH: onnx==1.10.2 + Python310: + python.version: '3.10' + ONNX_PATH: onnx==1.14.0 + maxParallel: 4 steps: @@ -58,6 +50,7 @@ jobs: pip uninstall -y onnxruntime pip install --index-url https://test.pypi.org/simple/ ort-nightly pip install $(ONNX_PATH) + pip install protobuf==3.20.2 pip install pytest pip install -e . displayName: 'Install dependencies' @@ -83,14 +76,6 @@ jobs: vmImage: 'windows-latest' strategy: matrix: - Python37: - python.version: '3.7' - ONNX_PATH: onnx==1.6.0 - - Python381: - python.version: '3.8' - ONNX_PATH: onnx==1.7.0 - Python382: python.version: '3.8' ONNX_PATH: onnx==1.8.0 @@ -103,6 +88,10 @@ jobs: python.version: '3.9' ONNX_PATH: onnx==1.10.2 + Python310: + python.version: '3.10' + ONNX_PATH: onnx==1.14.0 + maxParallel: 4 steps: @@ -128,6 +117,7 @@ jobs: pip uninstall -y onnxruntime pip install --index-url https://test.pypi.org/simple/ ort-nightly pip install %ONNX_PATH% + pip install protobuf==3.20.2 pip install pytest pip install -e . displayName: 'Install dependencies' From 3873b291c32b1ee930b63111496639f364d4c928 Mon Sep 17 00:00:00 2001 From: xiaowuhu Date: Mon, 21 Aug 2023 13:27:32 +0800 Subject: [PATCH 3/4] fix subgraph bug (#260) * add functions to resort Signed-off-by: xiaowuhu * change code and add test case Signed-off-by: xiaowuhu * Update float16.py Signed-off-by: xiaowuhu * Delete float16_old.py Signed-off-by: xiaowuhu * Update float16.py Signed-off-by: xiaowuhu * fix flake 8 Signed-off-by: xiaowuhu * Update perfstats.py Signed-off-by: xiaowuhu * Update test_float16.py Signed-off-by: xiaowuhu * Update __init__.py Signed-off-by: xiaowuhu * Create pyproject.toml * add more info * update Signed-off-by: xiaowuhu * Delete setup.py * Update float16.py Signed-off-by: xiaowuhu * disable python Signed-off-by: xiaowuhu * Revert "Delete setup.py" This reverts commit 2da07274239b963431118cd19b1657365944d0ba. --------- Signed-off-by: xiaowuhu --- .../OneBranchPipeline-Official.yml | 4 +- .../OneBranchPipeline-PullRequest.yml | 4 +- MANIFEST.in | 1 + onnxconverter_common/__init__.py | 2 +- onnxconverter_common/data_types.py | 4 +- onnxconverter_common/float16.py | 64 ++++++++++++++++-- onnxconverter_common/perfstats.py | 2 +- pyproject.toml | 30 ++++++++ tests/data/test_subgraph.onnx | Bin 0 -> 655 bytes tests/test_float16.py | 16 +++++ 10 files changed, 115 insertions(+), 12 deletions(-) create mode 100644 pyproject.toml create mode 100644 tests/data/test_subgraph.onnx diff --git a/.azure-pipelines/OneBranchPipeline-Official.yml b/.azure-pipelines/OneBranchPipeline-Official.yml index b05a291..6e9cabf 100644 --- a/.azure-pipelines/OneBranchPipeline-Official.yml +++ b/.azure-pipelines/OneBranchPipeline-Official.yml @@ -33,7 +33,7 @@ extends: break: true # always break the build on policheck issues. You can disable it by setting to 'false' codeql: python: - enabled: true + enabled: false stages: - stage: firststage @@ -57,7 +57,7 @@ extends: pip install -r requirements.txt pip install onnxruntime pip install onnxmltools - pip install onnx==1.12.0 + pip install onnx pip install pytest pip install -e . displayName: 'Install dependencies' diff --git a/.azure-pipelines/OneBranchPipeline-PullRequest.yml b/.azure-pipelines/OneBranchPipeline-PullRequest.yml index 0a84e99..6eaf586 100644 --- a/.azure-pipelines/OneBranchPipeline-PullRequest.yml +++ b/.azure-pipelines/OneBranchPipeline-PullRequest.yml @@ -34,7 +34,7 @@ extends: break: true # always break the build on policheck issues. codeql: python: - enabled: true + enabled: false stages: - stage: firststage @@ -55,7 +55,7 @@ extends: pip install -r requirements.txt pip install onnxruntime pip install onnxmltools - pip install onnx==1.12.0 + pip install onnx pip install pytest pip install -e . displayName: 'Install dependencies' diff --git a/MANIFEST.in b/MANIFEST.in index 1aba38f..096dd50 100644 --- a/MANIFEST.in +++ b/MANIFEST.in @@ -1 +1,2 @@ include LICENSE +include requirements.txt diff --git a/onnxconverter_common/__init__.py b/onnxconverter_common/__init__.py index 4581691..146bf5d 100644 --- a/onnxconverter_common/__init__.py +++ b/onnxconverter_common/__init__.py @@ -8,7 +8,7 @@ This framework performs optimization for ONNX models and includes common utilities for ONNX converters. """ -__version__ = "1.13.0" +__version__ = "1.14.0" __author__ = "Microsoft" __producer__ = "OnnxMLTools" __producer_version__ = __version__ diff --git a/onnxconverter_common/data_types.py b/onnxconverter_common/data_types.py index bc5debe..8b1ca1c 100644 --- a/onnxconverter_common/data_types.py +++ b/onnxconverter_common/data_types.py @@ -248,9 +248,9 @@ def find_type_conversion(source_type, target_type): """ Find the operator name for converting source_type into target_type """ - if type(source_type) == type(target_type): + if isinstance(source_type, target_type): return 'identity' - if type(target_type) == FloatTensorType: + if isinstance(target_type, FloatTensorType): return 'imageToFloatTensor' raise ValueError('Unsupported type conversion from %s to %s' % ( source_type, target_type)) diff --git a/onnxconverter_common/float16.py b/onnxconverter_common/float16.py index 02af8d0..a63572f 100644 --- a/onnxconverter_common/float16.py +++ b/onnxconverter_common/float16.py @@ -157,6 +157,8 @@ def convert_float_to_float16(model, min_positive_val=1e-7, max_finite_val=1e4, queue = [] value_info_list = [] node_list = [] + # key = node, value = graph, used to distinguish global with sub-graph + node_dict = {} # type inference on input model if func_infer_shape is not None: model = func_infer_shape(model) @@ -222,6 +224,7 @@ def convert_float_to_float16(model, min_positive_val=1e-7, max_finite_val=1e4, # so it will not be converted to float16 if n.op_type in op_block_list or n.name in node_block_list: node_list.append(n) + node_dict[n.name] = q else: if n.op_type == 'Cast': for attr in n.attribute: @@ -264,7 +267,8 @@ def convert_float_to_float16(model, min_positive_val=1e-7, max_finite_val=1e4, for value_info in value_info_list: if input == value_info.name: # create new value_info for current node's new input name - new_value_info = model.graph.value_info.add() + graph = node_dict[node.name] # get the correct graph instead of the global graph + new_value_info = graph.value_info.add() new_value_info.CopyFrom(value_info) output_name = node.name + '_input_cast_' + str(i) new_value_info.name = output_name @@ -272,7 +276,7 @@ def convert_float_to_float16(model, min_positive_val=1e-7, max_finite_val=1e4, # add Cast node (from tensor(float16) to tensor(float) before current node node_name = node.name + '_input_cast' + str(i) new_node = [helper.make_node('Cast', [input], [output_name], to=1, name=node_name)] - model.graph.node.extend(new_node) + graph.node.extend(new_node) # change current node's input name node.input[i] = output_name break @@ -283,7 +287,8 @@ def convert_float_to_float16(model, min_positive_val=1e-7, max_finite_val=1e4, for value_info in value_info_list: if output == value_info.name: # create new value_info for current node's new output - new_value_info = model.graph.value_info.add() + graph = node_dict[node.name] # get the correct graph instead of the global graph + new_value_info = graph.value_info.add() new_value_info.CopyFrom(value_info) input_name = node.name + '_output_cast_' + str(i) new_value_info.name = input_name @@ -291,11 +296,12 @@ def convert_float_to_float16(model, min_positive_val=1e-7, max_finite_val=1e4, # add Cast node (from tensor(float) to tensor(float16) after current node node_name = node.name + '_output_cast' + str(i) new_node = [helper.make_node('Cast', [input_name], [output], to=10, name=node_name)] - model.graph.node.extend(new_node) + graph.node.extend(new_node) # change current node's input name node.output[i] = input_name break + sort_topology(model.graph) return model @@ -332,3 +338,53 @@ def convert_float_to_float16_model_path(model_path, min_positive_val=1e-7, max_f if not disable_shape_infer: model = onnx.load(model_path) return convert_float_to_float16(model, min_positive_val, max_finite_val, keep_io_types, disable_shape_infer) + + +def sort_graph_node(graph_proto): + # find the "first" node in Nodes that its input is not any node's output + def find_first_node(output2node_dict): + for node in org_nodes: + is_not_first_node = any(item in output2node_dict for item in node.input) + if not is_not_first_node: + return node + return None + + # remove the node from output2node_dict using output as key + def remove_first_node_from_dict2(first_node): + for output in first_node.output: + if output in output2node_dict: + del output2node_dict[output] + + org_nodes = graph_proto.node + # create a dict to store output as key and node as value + output2node_dict = {} + for node in org_nodes: + for output in node.output: + output2node_dict[output] = node + + # save the final node after sorted + sorted_node = [] + # traverse the Nodes to find the first node + while (len(output2node_dict) > 0): + first_node = find_first_node(output2node_dict) + sorted_node.append(first_node) + remove_first_node_from_dict2(first_node) + # del node from original nodes list to avoid duplicate traverse + org_nodes.remove(first_node) + + for new_node in sorted_node: + graph_proto.node.extend([new_node]) + + +# The input graph should be mode.graph +# Recursevly sort the topology for each sub-graph +def sort_topology(graph_proto): + assert (isinstance(graph_proto, onnx_proto.GraphProto)) + sort_graph_node(graph_proto) # sort global graph + for node in graph_proto.node: + for attr in node.attribute: + if isinstance(attr.g, onnx_proto.GraphProto) and len(attr.g.node) > 0: + sort_topology(attr.g) # sort sub-graph + for g in attr.graphs: + if isinstance(g, onnx_proto.GraphProto): + sort_topology(g) # sort sub-graph diff --git a/onnxconverter_common/perfstats.py b/onnxconverter_common/perfstats.py index 11d405f..62361aa 100644 --- a/onnxconverter_common/perfstats.py +++ b/onnxconverter_common/perfstats.py @@ -114,7 +114,7 @@ def compute_op_type_entries(raw_entries): def read_raw_entries(profile_path): with open(profile_path, "r") as f: data = json.load(f) - if type(data) == dict: + if isinstance(data, dict): data = data['traceEvents'] entries = [] for item in data: diff --git a/pyproject.toml b/pyproject.toml new file mode 100644 index 0000000..bc22188 --- /dev/null +++ b/pyproject.toml @@ -0,0 +1,30 @@ +[build-system] +requires = ["setuptools>=61.0.0"] +build-backend = "setuptools.build_meta" + +[project] +name = "onnxconverter-common" +dynamic = ["version"] +description="ONNX Converter and Optimization Tools" +authors = [{ name = "Microsoft Corporation", email = "onnx@microsoft.com" }] +urls = { "Repository" = "https://github.com/microsoft/onnxconverter-common" } +readme = "README.md" +requires-python = ">=3.8" +license = { file = "LICENSE" } +classifiers = [ + "Development Status :: 5 - Production/Stable", + "Environment :: Console", + "Intended Audience :: Developers", + "Operating System :: MacOS :: MacOS X", + "Operating System :: Microsoft :: Windows", + "Programming Language :: Python", + "Programming Language :: Python :: 3.8", + "Programming Language :: Python :: 3.9", + "Programming Language :: Python :: 3.10", + "Programming Language :: Python :: 3.11", + "License :: OSI Approved :: MIT License", +] +dependencies = ["numpy", "onnx", "packaging", "protobuf==3.20.2"] + +[tool.setuptools.dynamic] +version = {attr = "onnxconverter_common.__version__"} diff --git a/tests/data/test_subgraph.onnx b/tests/data/test_subgraph.onnx new file mode 100644 index 0000000000000000000000000000000000000000..66076acadc80941f275bac55872c5bf2b48c676a GIT binary patch literal 655 zcmZ{i%}&BV6oosbK)Ddai3>w?VHaw;F#MX>owy(*xG{0#rkS>5Ai#j_)PQRrgm*B$ zgOBBH%RnHy>%H^MnR8BRn$Bk)PJk?dtSDi1T{NuReGoVrbZK!c*QhLA=0o)Pdtcy z{>Ya05ttLs7r}TIooZ{MqwXCoDSw9{&s4}-7IFt>F>heE0pii>R_O1j7YM-tM2Vj! z&7r-0H_bHPuJV7~G&46>K>VGdCM{$=p-R^(J&Wiq=KKR2r)gLHkS#`T#{<}K6#K~A zLn!lU#8s0HoF_%9%3Eol<{;ogj^!%RN@%53fi0M-;dy>G5BT(@jDHs`fMF7 Date: Tue, 22 Aug 2023 12:06:15 +0800 Subject: [PATCH 4/4] Update manually-publish.yml for Azure Pipelines (#263) * Update manually-publish.yml for Azure Pipelines * Update manually-publish.yml for Azure Pipelines * Update manually-publish.yml for Azure Pipelines * add tar.gz into package * add trigger : none --- manually-publish.yml | 32 ++++++++++++++++++++++++++++++++ 1 file changed, 32 insertions(+) create mode 100644 manually-publish.yml diff --git a/manually-publish.yml b/manually-publish.yml new file mode 100644 index 0000000..2201ae9 --- /dev/null +++ b/manually-publish.yml @@ -0,0 +1,32 @@ +trigger: none + +steps: + - task: UsePythonVersion@0 + inputs: + versionSpec: '3.11' + displayName: 'Set Up Python' + - script: python -m pip install --upgrade pip build wheel + displayName: 'Install Python build dependencies' + - script: python -m build + displayName: 'Build wheel' + - task: CopyFiles@2 + displayName: 'Copy Python Wheel to: $(Build.ArtifactStagingDirectory)' + inputs: + SourceFolder: 'dist' + Contents: '*.*' + TargetFolder: '$(Build.ArtifactStagingDirectory)' + - task: PublishBuildArtifacts@1 + displayName: 'Publish converter-common' + inputs: + ArtifactName: onnxconverter_common + - task: EsrpRelease@3 + inputs: + ConnectedServiceName: 'esrprelease' + Intent: 'PackageDistribution' + ContentType: 'PyPi' + PackageLocation: '$(Build.ArtifactStagingDirectory)' + Owners: 'xiaowuhu@microsoft.com' + Approvers: 'xiaowuhu@microsoft.com' + ServiceEndpointUrl: 'https://api.esrp.microsoft.com' + MainPublisher: 'AIFrameworks' + DomainTenantId: '72f988bf-86f1-41af-91ab-2d7cd011db47'