modelconv 0.5.3__tar.gz → 0.5.4__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {modelconv-0.5.3 → modelconv-0.5.4}/PKG-INFO +2 -1
- {modelconv-0.5.3 → modelconv-0.5.4}/modelconv.egg-info/PKG-INFO +2 -1
- {modelconv-0.5.3 → modelconv-0.5.4}/modelconv.egg-info/SOURCES.txt +2 -2
- {modelconv-0.5.3 → modelconv-0.5.4}/modelconv.egg-info/requires.txt +1 -0
- {modelconv-0.5.3 → modelconv-0.5.4}/modelconverter/__init__.py +1 -1
- {modelconv-0.5.3 → modelconv-0.5.4}/modelconverter/packages/base_exporter.py +19 -1
- {modelconv-0.5.3 → modelconv-0.5.4}/modelconverter/packages/rvc3/exporter.py +1 -0
- {modelconv-0.5.3 → modelconv-0.5.4}/modelconverter/packages/rvc4/analyze.py +21 -17
- {modelconv-0.5.3 → modelconv-0.5.4}/modelconverter/packages/rvc4/benchmark.py +113 -157
- {modelconv-0.5.3 → modelconv-0.5.4}/modelconverter/packages/rvc4/exporter.py +1 -0
- {modelconv-0.5.3 → modelconv-0.5.4}/modelconverter/utils/__init__.py +12 -4
- modelconv-0.5.4/modelconverter/utils/device_handlers.py +357 -0
- modelconv-0.5.3/modelconverter/utils/adb_monitor.py → modelconv-0.5.4/modelconverter/utils/device_monitors.py +23 -17
- {modelconv-0.5.3 → modelconv-0.5.4}/requirements-analysis.txt +1 -0
- modelconv-0.5.4/tests/test_benchmark/conftest.py +93 -0
- modelconv-0.5.4/tests/test_benchmark/test_benchmark_regression.py +279 -0
- modelconv-0.5.3/modelconverter/utils/adb_handler.py +0 -83
- modelconv-0.5.3/tests/test_benchmark/conftest.py +0 -36
- modelconv-0.5.3/tests/test_benchmark/test_benchmark_regression.py +0 -74
- {modelconv-0.5.3 → modelconv-0.5.4}/LICENSE +0 -0
- {modelconv-0.5.3 → modelconv-0.5.4}/README.md +0 -0
- {modelconv-0.5.3 → modelconv-0.5.4}/modelconv.egg-info/dependency_links.txt +0 -0
- {modelconv-0.5.3 → modelconv-0.5.4}/modelconv.egg-info/entry_points.txt +0 -0
- {modelconv-0.5.3 → modelconv-0.5.4}/modelconv.egg-info/top_level.txt +0 -0
- {modelconv-0.5.3 → modelconv-0.5.4}/modelconverter/__main__.py +0 -0
- {modelconv-0.5.3 → modelconv-0.5.4}/modelconverter/cli/__init__.py +0 -0
- {modelconv-0.5.3 → modelconv-0.5.4}/modelconverter/cli/utils.py +0 -0
- {modelconv-0.5.3 → modelconv-0.5.4}/modelconverter/packages/__init__.py +0 -0
- {modelconv-0.5.3 → modelconv-0.5.4}/modelconverter/packages/base_analyze.py +0 -0
- {modelconv-0.5.3 → modelconv-0.5.4}/modelconverter/packages/base_benchmark.py +0 -0
- {modelconv-0.5.3 → modelconv-0.5.4}/modelconverter/packages/base_inferer.py +0 -0
- {modelconv-0.5.3 → modelconv-0.5.4}/modelconverter/packages/base_visualize.py +0 -0
- {modelconv-0.5.3 → modelconv-0.5.4}/modelconverter/packages/getters.py +0 -0
- {modelconv-0.5.3 → modelconv-0.5.4}/modelconverter/packages/hailo/__init__.py +0 -0
- {modelconv-0.5.3 → modelconv-0.5.4}/modelconverter/packages/hailo/exporter.py +0 -0
- {modelconv-0.5.3 → modelconv-0.5.4}/modelconverter/packages/hailo/inferer.py +0 -0
- {modelconv-0.5.3 → modelconv-0.5.4}/modelconverter/packages/hailo/requirements.txt +0 -0
- {modelconv-0.5.3 → modelconv-0.5.4}/modelconverter/packages/multistage_exporter.py +0 -0
- {modelconv-0.5.3 → modelconv-0.5.4}/modelconverter/packages/rvc2/__init__.py +0 -0
- {modelconv-0.5.3 → modelconv-0.5.4}/modelconverter/packages/rvc2/benchmark.py +0 -0
- {modelconv-0.5.3 → modelconv-0.5.4}/modelconverter/packages/rvc2/exporter.py +0 -0
- {modelconv-0.5.3 → modelconv-0.5.4}/modelconverter/packages/rvc2/inferer.py +0 -0
- {modelconv-0.5.3 → modelconv-0.5.4}/modelconverter/packages/rvc2/requirements.txt +0 -0
- {modelconv-0.5.3 → modelconv-0.5.4}/modelconverter/packages/rvc3/__init__.py +0 -0
- {modelconv-0.5.3 → modelconv-0.5.4}/modelconverter/packages/rvc3/benchmark.py +0 -0
- {modelconv-0.5.3 → modelconv-0.5.4}/modelconverter/packages/rvc3/inferer.py +0 -0
- {modelconv-0.5.3 → modelconv-0.5.4}/modelconverter/packages/rvc3/requirements.txt +0 -0
- {modelconv-0.5.3 → modelconv-0.5.4}/modelconverter/packages/rvc4/__init__.py +0 -0
- {modelconv-0.5.3 → modelconv-0.5.4}/modelconverter/packages/rvc4/inferer.py +0 -0
- {modelconv-0.5.3 → modelconv-0.5.4}/modelconverter/packages/rvc4/requirements.txt +0 -0
- {modelconv-0.5.3 → modelconv-0.5.4}/modelconverter/packages/rvc4/visualize.py +0 -0
- {modelconv-0.5.3 → modelconv-0.5.4}/modelconverter/utils/calibration_data.py +0 -0
- {modelconv-0.5.3 → modelconv-0.5.4}/modelconverter/utils/config.py +0 -0
- {modelconv-0.5.3 → modelconv-0.5.4}/modelconverter/utils/constants.py +0 -0
- {modelconv-0.5.3 → modelconv-0.5.4}/modelconverter/utils/docker_utils.py +0 -0
- {modelconv-0.5.3 → modelconv-0.5.4}/modelconverter/utils/environ.py +0 -0
- {modelconv-0.5.3 → modelconv-0.5.4}/modelconverter/utils/exceptions.py +0 -0
- {modelconv-0.5.3 → modelconv-0.5.4}/modelconverter/utils/filesystem_utils.py +0 -0
- {modelconv-0.5.3 → modelconv-0.5.4}/modelconverter/utils/general.py +0 -0
- {modelconv-0.5.3 → modelconv-0.5.4}/modelconverter/utils/hub_requests.py +0 -0
- {modelconv-0.5.3 → modelconv-0.5.4}/modelconverter/utils/hubai_utils.py +0 -0
- {modelconv-0.5.3 → modelconv-0.5.4}/modelconverter/utils/image.py +0 -0
- {modelconv-0.5.3 → modelconv-0.5.4}/modelconverter/utils/layout.py +0 -0
- {modelconv-0.5.3 → modelconv-0.5.4}/modelconverter/utils/metadata.py +0 -0
- {modelconv-0.5.3 → modelconv-0.5.4}/modelconverter/utils/nn_archive.py +0 -0
- {modelconv-0.5.3 → modelconv-0.5.4}/modelconverter/utils/onnx_compatibility.py +0 -0
- {modelconv-0.5.3 → modelconv-0.5.4}/modelconverter/utils/onnx_tools.py +0 -0
- {modelconv-0.5.3 → modelconv-0.5.4}/modelconverter/utils/progress_handler.py +0 -0
- {modelconv-0.5.3 → modelconv-0.5.4}/modelconverter/utils/subprocess.py +0 -0
- {modelconv-0.5.3 → modelconv-0.5.4}/modelconverter/utils/types.py +0 -0
- {modelconv-0.5.3 → modelconv-0.5.4}/pyproject.toml +0 -0
- {modelconv-0.5.3 → modelconv-0.5.4}/requirements-bench.txt +0 -0
- {modelconv-0.5.3 → modelconv-0.5.4}/requirements-dev.txt +0 -0
- {modelconv-0.5.3 → modelconv-0.5.4}/requirements.txt +0 -0
- {modelconv-0.5.3 → modelconv-0.5.4}/setup.cfg +0 -0
- {modelconv-0.5.3 → modelconv-0.5.4}/tests/__init__.py +0 -0
- {modelconv-0.5.3 → modelconv-0.5.4}/tests/conftest.py +0 -0
- {modelconv-0.5.3 → modelconv-0.5.4}/tests/test_benchmark/__init__.py +0 -0
- {modelconv-0.5.3 → modelconv-0.5.4}/tests/test_packages/__init__.py +0 -0
- {modelconv-0.5.3 → modelconv-0.5.4}/tests/test_packages/common.py +0 -0
- {modelconv-0.5.3 → modelconv-0.5.4}/tests/test_packages/metrics/__init__.py +0 -0
- {modelconv-0.5.3 → modelconv-0.5.4}/tests/test_packages/metrics/base_metric.py +0 -0
- {modelconv-0.5.3 → modelconv-0.5.4}/tests/test_packages/metrics/mnist_metric.py +0 -0
- {modelconv-0.5.3 → modelconv-0.5.4}/tests/test_packages/metrics/resnet_metric.py +0 -0
- {modelconv-0.5.3 → modelconv-0.5.4}/tests/test_packages/metrics/yolov6_metric.py +0 -0
- {modelconv-0.5.3 → modelconv-0.5.4}/tests/test_packages/onnx_inferer.py +0 -0
- {modelconv-0.5.3 → modelconv-0.5.4}/tests/test_packages/test_cross_format_export.py +0 -0
- {modelconv-0.5.3 → modelconv-0.5.4}/tests/test_packages/test_hailo.py +0 -0
- {modelconv-0.5.3 → modelconv-0.5.4}/tests/test_packages/test_rvc2.py +0 -0
- {modelconv-0.5.3 → modelconv-0.5.4}/tests/test_packages/test_rvc3.py +0 -0
- {modelconv-0.5.3 → modelconv-0.5.4}/tests/test_packages/test_rvc4.py +0 -0
- {modelconv-0.5.3 → modelconv-0.5.4}/tests/test_utils/__init__.py +0 -0
- {modelconv-0.5.3 → modelconv-0.5.4}/tests/test_utils/conftest.py +0 -0
- {modelconv-0.5.3 → modelconv-0.5.4}/tests/test_utils/test_config.py +0 -0
- {modelconv-0.5.3 → modelconv-0.5.4}/tests/test_utils/test_filesystem.py +0 -0
- {modelconv-0.5.3 → modelconv-0.5.4}/tests/test_utils/test_image.py +0 -0
- {modelconv-0.5.3 → modelconv-0.5.4}/tests/test_utils/test_layout.py +0 -0
- {modelconv-0.5.3 → modelconv-0.5.4}/tests/test_utils/test_modifier.py +0 -0
- {modelconv-0.5.3 → modelconv-0.5.4}/tests/test_utils/test_onnx_compatibility.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: modelconv
|
|
3
|
-
Version: 0.5.
|
|
3
|
+
Version: 0.5.4
|
|
4
4
|
Summary: Converter for neural models into various formats.
|
|
5
5
|
Author-email: Luxonis <support@luxonis.com>
|
|
6
6
|
Maintainer-email: Luxonis <support@luxonis.com>
|
|
@@ -33,6 +33,7 @@ Requires-Dist: depthai~=3.0; extra == "bench"
|
|
|
33
33
|
Provides-Extra: analysis
|
|
34
34
|
Requires-Dist: polars; extra == "analysis"
|
|
35
35
|
Requires-Dist: plotly; extra == "analysis"
|
|
36
|
+
Requires-Dist: depthai~=3.0; extra == "analysis"
|
|
36
37
|
Provides-Extra: dev
|
|
37
38
|
Requires-Dist: pre-commit==3.2.1; extra == "dev"
|
|
38
39
|
Requires-Dist: pytest-cov>=4.1.0; extra == "dev"
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: modelconv
|
|
3
|
-
Version: 0.5.
|
|
3
|
+
Version: 0.5.4
|
|
4
4
|
Summary: Converter for neural models into various formats.
|
|
5
5
|
Author-email: Luxonis <support@luxonis.com>
|
|
6
6
|
Maintainer-email: Luxonis <support@luxonis.com>
|
|
@@ -33,6 +33,7 @@ Requires-Dist: depthai~=3.0; extra == "bench"
|
|
|
33
33
|
Provides-Extra: analysis
|
|
34
34
|
Requires-Dist: polars; extra == "analysis"
|
|
35
35
|
Requires-Dist: plotly; extra == "analysis"
|
|
36
|
+
Requires-Dist: depthai~=3.0; extra == "analysis"
|
|
36
37
|
Provides-Extra: dev
|
|
37
38
|
Requires-Dist: pre-commit==3.2.1; extra == "dev"
|
|
38
39
|
Requires-Dist: pytest-cov>=4.1.0; extra == "dev"
|
|
@@ -45,11 +45,11 @@ modelconverter/packages/rvc4/inferer.py
|
|
|
45
45
|
modelconverter/packages/rvc4/requirements.txt
|
|
46
46
|
modelconverter/packages/rvc4/visualize.py
|
|
47
47
|
modelconverter/utils/__init__.py
|
|
48
|
-
modelconverter/utils/adb_handler.py
|
|
49
|
-
modelconverter/utils/adb_monitor.py
|
|
50
48
|
modelconverter/utils/calibration_data.py
|
|
51
49
|
modelconverter/utils/config.py
|
|
52
50
|
modelconverter/utils/constants.py
|
|
51
|
+
modelconverter/utils/device_handlers.py
|
|
52
|
+
modelconverter/utils/device_monitors.py
|
|
53
53
|
modelconverter/utils/docker_utils.py
|
|
54
54
|
modelconverter/utils/environ.py
|
|
55
55
|
modelconverter/utils/exceptions.py
|
|
@@ -4,7 +4,7 @@ from typing import Final
|
|
|
4
4
|
from luxonis_ml.utils import PUT_FILE_REGISTRY
|
|
5
5
|
from pydantic_extra_types.semantic_version import SemanticVersion
|
|
6
6
|
|
|
7
|
-
__version__: Final[str] = "0.5.
|
|
7
|
+
__version__: Final[str] = "0.5.4"
|
|
8
8
|
__semver__: Final[SemanticVersion] = SemanticVersion.parse(__version__)
|
|
9
9
|
|
|
10
10
|
|
|
@@ -5,6 +5,7 @@ from importlib.metadata import version
|
|
|
5
5
|
from pathlib import Path
|
|
6
6
|
from typing import Any
|
|
7
7
|
|
|
8
|
+
import cv2
|
|
8
9
|
import numpy as np
|
|
9
10
|
from loguru import logger
|
|
10
11
|
|
|
@@ -225,7 +226,24 @@ class Exporter(ABC):
|
|
|
225
226
|
arr = np.clip(arr, calib.min_value, calib.max_value)
|
|
226
227
|
|
|
227
228
|
arr = arr.astype(calib.data_type.as_numpy_dtype())
|
|
228
|
-
|
|
229
|
+
if len(arr.shape) in {2, 3} or (
|
|
230
|
+
len(arr.shape) in {3, 4} and arr.shape[0] == 1
|
|
231
|
+
):
|
|
232
|
+
layout = inp.layout
|
|
233
|
+
if arr.shape[0] == 1 and len(arr.shape) > 2:
|
|
234
|
+
arr = arr.squeeze(0)
|
|
235
|
+
if layout is not None:
|
|
236
|
+
layout = layout[1:]
|
|
237
|
+
|
|
238
|
+
if layout is not None and "C" in layout:
|
|
239
|
+
channel_dim = layout.index("C")
|
|
240
|
+
if channel_dim == 0 and len(arr.shape) == 3:
|
|
241
|
+
arr = arr.transpose(1, 2, 0)
|
|
242
|
+
elif arr.shape[0] in {1, 3}: # type: ignore
|
|
243
|
+
arr = arr.transpose(1, 2, 0)
|
|
244
|
+
cv2.imwrite(str(dest / f"{i}.png"), arr)
|
|
245
|
+
else:
|
|
246
|
+
np.save(dest / f"{i}.npy", arr)
|
|
229
247
|
|
|
230
248
|
self.inputs[name].calibration = ImageCalibrationConfig(path=dest)
|
|
231
249
|
|
|
@@ -31,6 +31,7 @@ class RVC3Exporter(RVC2Exporter):
|
|
|
31
31
|
self.mo_args = config.rvc3.mo_args
|
|
32
32
|
self.compile_tool_args = config.rvc3.compile_tool_args
|
|
33
33
|
self.device = "VPUX.3400"
|
|
34
|
+
self.reverse_input_channels = False
|
|
34
35
|
self._device_specific_buildinfo = {}
|
|
35
36
|
|
|
36
37
|
def export(self) -> Path:
|
|
@@ -14,7 +14,7 @@ from PIL import Image
|
|
|
14
14
|
|
|
15
15
|
from modelconverter.packages.base_analyze import Analyzer
|
|
16
16
|
from modelconverter.packages.rvc4.benchmark import get_device_info
|
|
17
|
-
from modelconverter.utils import
|
|
17
|
+
from modelconverter.utils import constants, create_handler, subprocess_run
|
|
18
18
|
|
|
19
19
|
|
|
20
20
|
class RVC4Analyzer(Analyzer):
|
|
@@ -27,7 +27,7 @@ class RVC4Analyzer(Analyzer):
|
|
|
27
27
|
):
|
|
28
28
|
super().__init__(dlc_model_path, image_dirs)
|
|
29
29
|
_, device_adb_id = get_device_info(device_ip, device_id)
|
|
30
|
-
self.
|
|
30
|
+
self.handler = create_handler(device_ip, device_adb_id)
|
|
31
31
|
|
|
32
32
|
def analyze_layer_outputs(self, onnx_model_path: Path) -> None:
|
|
33
33
|
input_matcher = self._prepare_input_matcher()
|
|
@@ -76,8 +76,8 @@ class RVC4Analyzer(Analyzer):
|
|
|
76
76
|
self, input_matcher: dict[str, dict[str, str]], type: type = np.uint8
|
|
77
77
|
) -> dict[str, str]:
|
|
78
78
|
logger.info("Preparing raw inputs for RVC4 analysis.")
|
|
79
|
-
self.
|
|
80
|
-
self.
|
|
79
|
+
self.handler.shell(f"rm -rf /data/modelconverter/{self.model_name}")
|
|
80
|
+
self.handler.shell(
|
|
81
81
|
f"mkdir -p /data/modelconverter/{self.model_name}/inputs"
|
|
82
82
|
)
|
|
83
83
|
|
|
@@ -109,7 +109,7 @@ class RVC4Analyzer(Analyzer):
|
|
|
109
109
|
|
|
110
110
|
with tempfile.NamedTemporaryFile() as f:
|
|
111
111
|
raw_image.tofile(f)
|
|
112
|
-
self.
|
|
112
|
+
self.handler.push(
|
|
113
113
|
f.name,
|
|
114
114
|
f"/data/modelconverter/{self.model_name}/inputs/{input_name}_{img_name}.raw",
|
|
115
115
|
)
|
|
@@ -122,7 +122,7 @@ class RVC4Analyzer(Analyzer):
|
|
|
122
122
|
with tempfile.NamedTemporaryFile() as f:
|
|
123
123
|
f.write(input_list.encode())
|
|
124
124
|
f.flush()
|
|
125
|
-
self.
|
|
125
|
+
self.handler.push(
|
|
126
126
|
f.name,
|
|
127
127
|
f"/data/modelconverter/{self.model_name}/input_list.txt",
|
|
128
128
|
)
|
|
@@ -133,8 +133,12 @@ class RVC4Analyzer(Analyzer):
|
|
|
133
133
|
return dlc_matcher
|
|
134
134
|
|
|
135
135
|
def _add_outputs_to_all_layers(self, onnx_file_path: str) -> Path:
|
|
136
|
-
|
|
137
|
-
|
|
136
|
+
onnx_path = Path(onnx_file_path)
|
|
137
|
+
all_output_path = onnx_path.with_name(
|
|
138
|
+
f"{onnx_path.stem}-all-layers{onnx_path.suffix}"
|
|
139
|
+
)
|
|
140
|
+
if all_output_path.exists():
|
|
141
|
+
all_output_path.unlink()
|
|
138
142
|
|
|
139
143
|
model = onnx.load(onnx_file_path)
|
|
140
144
|
onnx.checker.check_model(model)
|
|
@@ -152,10 +156,10 @@ class RVC4Analyzer(Analyzer):
|
|
|
152
156
|
|
|
153
157
|
for output in orig_graph_output:
|
|
154
158
|
graph.output.append(output)
|
|
155
|
-
|
|
156
|
-
onnx.save(model,
|
|
159
|
+
all_output_path.parent.mkdir(parents=True, exist_ok=True)
|
|
160
|
+
onnx.save(model, all_output_path)
|
|
157
161
|
|
|
158
|
-
return
|
|
162
|
+
return all_output_path
|
|
159
163
|
|
|
160
164
|
def transpose_to_match(
|
|
161
165
|
self, src: np.ndarray, target_shape: tuple[int, ...]
|
|
@@ -321,14 +325,14 @@ class RVC4Analyzer(Analyzer):
|
|
|
321
325
|
def _run_dlc(self, command: str) -> str:
|
|
322
326
|
logger.info("Inferencing DLC model on device.")
|
|
323
327
|
try:
|
|
324
|
-
self.
|
|
328
|
+
self.handler.push(
|
|
325
329
|
str(self.dlc_model_path),
|
|
326
330
|
f"/data/modelconverter/{self.model_name}/{self.model_name}.dlc",
|
|
327
331
|
)
|
|
328
|
-
self.
|
|
332
|
+
self.handler.shell(
|
|
329
333
|
f"rm -rf /data/modelconverter/{self.model_name}/output"
|
|
330
334
|
)
|
|
331
|
-
self.
|
|
335
|
+
self.handler.shell(
|
|
332
336
|
f"cd /data/modelconverter/{self.model_name} && {command}"
|
|
333
337
|
)
|
|
334
338
|
|
|
@@ -337,7 +341,7 @@ class RVC4Analyzer(Analyzer):
|
|
|
337
341
|
shutil.rmtree(target_dir / "output")
|
|
338
342
|
|
|
339
343
|
target_dir.mkdir(parents=True, exist_ok=True)
|
|
340
|
-
self.
|
|
344
|
+
self.handler.pull(
|
|
341
345
|
f"/data/modelconverter/{self.model_name}/output",
|
|
342
346
|
f"{target_dir}/output",
|
|
343
347
|
)
|
|
@@ -397,7 +401,7 @@ class RVC4Analyzer(Analyzer):
|
|
|
397
401
|
|
|
398
402
|
logger.info("Running DLC model to analyze layer cycles.")
|
|
399
403
|
output_dir = self._run_dlc(
|
|
400
|
-
f"snpe-net-run --container {self.model_name}.dlc --input_list input_list.txt --use_dsp --use_native_input_files --use_native_output_files --perf_profile balanced --
|
|
404
|
+
f"snpe-net-run --container {self.model_name}.dlc --input_list input_list.txt --use_dsp --use_native_input_files --use_native_output_files --perf_profile balanced --userbuffer_auto"
|
|
401
405
|
)
|
|
402
406
|
|
|
403
407
|
csv_path = Path(output_dir + "/layer_stats.csv")
|
|
@@ -456,7 +460,7 @@ class RVC4Analyzer(Analyzer):
|
|
|
456
460
|
|
|
457
461
|
# cleanup
|
|
458
462
|
def _cleanup_dlc_outputs(self) -> None:
|
|
459
|
-
self.
|
|
463
|
+
self.handler.shell(f"rm -rf /data/modelconverter/{self.model_name}")
|
|
460
464
|
|
|
461
465
|
output_dir = Path(
|
|
462
466
|
f"{constants.OUTPUTS_DIR!s}/analysis/{self.model_name}/output"
|
|
@@ -4,9 +4,9 @@ import re
|
|
|
4
4
|
import shutil
|
|
5
5
|
import tempfile
|
|
6
6
|
from collections.abc import Iterable
|
|
7
|
-
from
|
|
7
|
+
from dataclasses import dataclass
|
|
8
8
|
from pathlib import Path
|
|
9
|
-
from typing import Final
|
|
9
|
+
from typing import Final
|
|
10
10
|
|
|
11
11
|
import depthai as dai
|
|
12
12
|
import numpy as np
|
|
@@ -19,9 +19,9 @@ from modelconverter.packages.base_benchmark import (
|
|
|
19
19
|
Configuration,
|
|
20
20
|
)
|
|
21
21
|
from modelconverter.utils import (
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
22
|
+
MonitorDSP,
|
|
23
|
+
MonitorPower,
|
|
24
|
+
create_handler,
|
|
25
25
|
create_progress_handler,
|
|
26
26
|
environ,
|
|
27
27
|
subprocess_run,
|
|
@@ -45,6 +45,26 @@ RUNTIMES: dict[str, str] = {
|
|
|
45
45
|
"cpu": "use_cpu",
|
|
46
46
|
}
|
|
47
47
|
|
|
48
|
+
DLC_TO_DAI_DATA_TYPE: Final[dict[str, dai.TensorInfo.DataType]] = {
|
|
49
|
+
"Float_32": dai.TensorInfo.DataType.FP32,
|
|
50
|
+
"Float_16": dai.TensorInfo.DataType.FP16,
|
|
51
|
+
"Float_64": dai.TensorInfo.DataType.FP64,
|
|
52
|
+
"Int_8": dai.TensorInfo.DataType.I8,
|
|
53
|
+
"Int_32": dai.TensorInfo.DataType.INT,
|
|
54
|
+
# DAI does not currently expose a 16-bit fixed-point/int tensor type.
|
|
55
|
+
# Until it does, keep uFxp_16 on the closest supported 16-bit path.
|
|
56
|
+
"uFxp_16": dai.TensorInfo.DataType.FP16,
|
|
57
|
+
"uFxp_8": dai.TensorInfo.DataType.U8F,
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
|
|
61
|
+
@dataclass(frozen=True)
|
|
62
|
+
class InputSpec:
|
|
63
|
+
name: str
|
|
64
|
+
shape: list[int]
|
|
65
|
+
dlc_dtype: str
|
|
66
|
+
dai_dtype: dai.TensorInfo.DataType
|
|
67
|
+
|
|
48
68
|
|
|
49
69
|
class RVC4Benchmark(Benchmark):
|
|
50
70
|
@property
|
|
@@ -80,15 +100,29 @@ class RVC4Benchmark(Benchmark):
|
|
|
80
100
|
for threads in [1, 2]
|
|
81
101
|
]
|
|
82
102
|
|
|
83
|
-
def
|
|
103
|
+
def _get_dlc_input_specs(
|
|
84
104
|
self, model_path: str | Path | None = None
|
|
85
|
-
) ->
|
|
105
|
+
) -> list[InputSpec]:
|
|
106
|
+
"""Retrieve normalized input specs from a DLC or NNArchive."""
|
|
107
|
+
model_path = self.model_path if model_path is None else model_path
|
|
108
|
+
|
|
109
|
+
if str(model_path).endswith(".tar.xz"):
|
|
110
|
+
with tempfile.TemporaryDirectory() as tmp_dir:
|
|
111
|
+
shutil.unpack_archive(model_path, tmp_dir)
|
|
112
|
+
dlc_files = list(Path(tmp_dir).rglob("*.dlc"))
|
|
113
|
+
if not dlc_files:
|
|
114
|
+
raise ValueError("No .dlc file found in the archive.")
|
|
115
|
+
return self._get_dlc_input_specs(dlc_files[0])
|
|
116
|
+
|
|
117
|
+
if not str(model_path).endswith(".dlc"):
|
|
118
|
+
raise ValueError("Expected .dlc, or .tar.xz model format.")
|
|
119
|
+
|
|
86
120
|
csv_path = Path("info.csv")
|
|
87
121
|
subprocess_run(
|
|
88
122
|
[
|
|
89
123
|
"snpe-dlc-info",
|
|
90
124
|
"-i",
|
|
91
|
-
|
|
125
|
+
model_path,
|
|
92
126
|
"-s",
|
|
93
127
|
csv_path,
|
|
94
128
|
],
|
|
@@ -110,146 +144,70 @@ class RVC4Benchmark(Benchmark):
|
|
|
110
144
|
)
|
|
111
145
|
|
|
112
146
|
rows = df.rows(named=True)
|
|
113
|
-
|
|
114
|
-
|
|
147
|
+
data_types = [str(row["Type"]) for row in rows]
|
|
148
|
+
unsupported_types = sorted(set(data_types) - set(DLC_TO_DAI_DATA_TYPE))
|
|
149
|
+
if unsupported_types:
|
|
150
|
+
raise ValueError(
|
|
151
|
+
f"Unsupported data types {unsupported_types}. Expected one of: {sorted(DLC_TO_DAI_DATA_TYPE)}."
|
|
152
|
+
)
|
|
115
153
|
|
|
116
|
-
return
|
|
154
|
+
return [
|
|
155
|
+
InputSpec(
|
|
156
|
+
name=str(row["Input Name"]),
|
|
157
|
+
shape=list(row["Dimensions"]),
|
|
158
|
+
dlc_dtype=str(row["Type"]),
|
|
159
|
+
dai_dtype=DLC_TO_DAI_DATA_TYPE[str(row["Type"])],
|
|
160
|
+
)
|
|
161
|
+
for row in rows
|
|
162
|
+
]
|
|
117
163
|
|
|
118
|
-
def _prepare_raw_inputs(
|
|
119
|
-
|
|
164
|
+
def _prepare_raw_inputs(
|
|
165
|
+
self, input_specs: list[InputSpec], num_images: int
|
|
166
|
+
) -> None:
|
|
120
167
|
input_list = ""
|
|
121
|
-
self.
|
|
168
|
+
self.handler.shell(
|
|
122
169
|
f"mkdir -p /data/modelconverter/{self.model_name}/inputs"
|
|
123
170
|
)
|
|
124
171
|
for i in range(num_images):
|
|
125
|
-
for
|
|
126
|
-
|
|
127
|
-
numpy_type = np.float32
|
|
128
|
-
elif data_types[name] in ["uFxp_16", "Float_16"]:
|
|
129
|
-
numpy_type = np.float16
|
|
130
|
-
elif data_types[name] == "uFxp_8":
|
|
131
|
-
numpy_type = np.uint8
|
|
132
|
-
else:
|
|
133
|
-
raise ValueError(
|
|
134
|
-
f"Unsupported data type {data_types[name]} for input {name}."
|
|
135
|
-
)
|
|
136
|
-
img = cast(np.ndarray, np.random.rand(*size)).astype(
|
|
137
|
-
numpy_type
|
|
138
|
-
)
|
|
172
|
+
for spec in input_specs:
|
|
173
|
+
input_data = self._create_random_input(spec)
|
|
139
174
|
with tempfile.NamedTemporaryFile() as f:
|
|
140
|
-
|
|
141
|
-
self.
|
|
175
|
+
input_data.tofile(f)
|
|
176
|
+
self.handler.push(
|
|
142
177
|
f.name,
|
|
143
|
-
f"/data/modelconverter/{self.model_name}/inputs/{name}_{i}.raw",
|
|
178
|
+
f"/data/modelconverter/{self.model_name}/inputs/{spec.name}_{i}.raw",
|
|
144
179
|
)
|
|
145
180
|
|
|
146
|
-
input_list += f"{name}:=/data/modelconverter/{self.model_name}/inputs/{name}_{i}.raw "
|
|
181
|
+
input_list += f"{spec.name}:=/data/modelconverter/{self.model_name}/inputs/{spec.name}_{i}.raw "
|
|
147
182
|
input_list += "\n"
|
|
148
183
|
|
|
149
184
|
with tempfile.NamedTemporaryFile() as f:
|
|
150
185
|
f.write(input_list.encode())
|
|
151
|
-
self.
|
|
186
|
+
self.handler.push(
|
|
152
187
|
f.name,
|
|
153
188
|
f"/data/modelconverter/{self.model_name}/input_list.txt",
|
|
154
189
|
)
|
|
155
190
|
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
raise ValueError("Expected .dlc, or .tar.xz model format.")
|
|
177
|
-
|
|
178
|
-
model_input = next(iter(data_types.values()))
|
|
179
|
-
if model_input == "Float_32":
|
|
180
|
-
return dai.TensorInfo.DataType.FP32
|
|
181
|
-
if model_input in ["uFxp_16", "Float_16"]:
|
|
182
|
-
return dai.TensorInfo.DataType.FP16
|
|
183
|
-
if model_input == "uFxp_8":
|
|
184
|
-
return dai.TensorInfo.DataType.U8F
|
|
185
|
-
raise ValueError(
|
|
186
|
-
f"Unsupported data type {model_input}. Expected Float_32, Float_16, or uFxp_8."
|
|
187
|
-
)
|
|
188
|
-
|
|
189
|
-
def _get_data_type(self) -> dai.TensorInfo.DataType:
|
|
190
|
-
"""Retrieve the data type of the model inputs. If the model is
|
|
191
|
-
not a HubAI model, it defaults to dai.TensorInfo.DataType.U8F
|
|
192
|
-
(INT8).
|
|
193
|
-
|
|
194
|
-
@return: The data type of the model inputs.
|
|
195
|
-
@rtype: dai.TensorInfo.DataType
|
|
196
|
-
"""
|
|
197
|
-
from modelconverter.cli import Request, slug_to_id
|
|
198
|
-
|
|
199
|
-
if not isinstance(
|
|
200
|
-
self.model_path, str
|
|
201
|
-
) or not self.HUB_MODEL_PATTERN.match(self.model_path):
|
|
202
|
-
return self._get_data_type_from_dlc()
|
|
203
|
-
|
|
204
|
-
model_id = slug_to_id(self.model_name, "models")
|
|
205
|
-
model_variant = self.model_path.split(":")[1]
|
|
206
|
-
|
|
207
|
-
model_variants = []
|
|
208
|
-
for is_public in [True, False]:
|
|
209
|
-
with suppress(Exception):
|
|
210
|
-
model_variants += Request.get(
|
|
211
|
-
"modelVersions/",
|
|
212
|
-
params={"model_id": model_id, "is_public": is_public},
|
|
213
|
-
)
|
|
214
|
-
|
|
215
|
-
model_version_id = None
|
|
216
|
-
for version in model_variants:
|
|
217
|
-
if version["variant_slug"] == model_variant:
|
|
218
|
-
model_version_id = version["id"]
|
|
219
|
-
break
|
|
220
|
-
|
|
221
|
-
if not model_version_id:
|
|
222
|
-
return dai.TensorInfo.DataType.U8F
|
|
223
|
-
|
|
224
|
-
model_instances = []
|
|
225
|
-
for is_public in [True, False]:
|
|
226
|
-
with suppress(Exception):
|
|
227
|
-
model_instances += Request.get(
|
|
228
|
-
"modelInstances/",
|
|
229
|
-
params={
|
|
230
|
-
"model_id": model_id,
|
|
231
|
-
"model_version_id": model_version_id,
|
|
232
|
-
"is_public": is_public,
|
|
233
|
-
},
|
|
234
|
-
)
|
|
235
|
-
|
|
236
|
-
model_precision_type = "INT8"
|
|
237
|
-
for instance in model_instances:
|
|
238
|
-
if instance["platforms"] == ["RVC4"] and (
|
|
239
|
-
self.model_instance is None
|
|
240
|
-
or instance["hash_short"] == self.model_instance
|
|
241
|
-
):
|
|
242
|
-
model_precision_type = instance.get(
|
|
243
|
-
"model_precision_type", "INT8"
|
|
244
|
-
)
|
|
245
|
-
break
|
|
246
|
-
|
|
247
|
-
if model_precision_type == "FP16":
|
|
248
|
-
return dai.TensorInfo.DataType.FP16
|
|
249
|
-
if model_precision_type == "FP32":
|
|
250
|
-
return dai.TensorInfo.DataType.FP32
|
|
251
|
-
|
|
252
|
-
return dai.TensorInfo.DataType.U8F
|
|
191
|
+
@staticmethod
|
|
192
|
+
def _create_random_input(
|
|
193
|
+
spec: InputSpec,
|
|
194
|
+
) -> np.ndarray:
|
|
195
|
+
if spec.dai_dtype == dai.TensorInfo.DataType.FP32:
|
|
196
|
+
return np.random.rand(*spec.shape).astype(np.float32)
|
|
197
|
+
if spec.dai_dtype == dai.TensorInfo.DataType.FP16:
|
|
198
|
+
return np.random.rand(*spec.shape).astype(np.float16)
|
|
199
|
+
if spec.dai_dtype == dai.TensorInfo.DataType.FP64:
|
|
200
|
+
return np.random.rand(*spec.shape).astype(np.float64)
|
|
201
|
+
if spec.dai_dtype == dai.TensorInfo.DataType.I8:
|
|
202
|
+
return np.random.randint(-128, 128, size=spec.shape, dtype=np.int8)
|
|
203
|
+
if spec.dai_dtype == dai.TensorInfo.DataType.INT:
|
|
204
|
+
# INT inputs are often token/index tensors; zero keeps synthetic
|
|
205
|
+
# benchmark inputs in a safe range.
|
|
206
|
+
return np.zeros(spec.shape, dtype=np.int32)
|
|
207
|
+
if spec.dai_dtype == dai.TensorInfo.DataType.U8F:
|
|
208
|
+
return np.random.randint(0, 256, size=spec.shape, dtype=np.uint8)
|
|
209
|
+
|
|
210
|
+
raise ValueError(f"Unsupported DAI data type {spec.dai_dtype}.")
|
|
253
211
|
|
|
254
212
|
def benchmark(self, configuration: Configuration) -> BenchmarkResult:
|
|
255
213
|
dai_benchmark = configuration.get("dai_benchmark")
|
|
@@ -260,18 +218,18 @@ class RVC4Benchmark(Benchmark):
|
|
|
260
218
|
configuration.get("device_ip"), configuration.get("device_id")
|
|
261
219
|
)
|
|
262
220
|
if power_benchmark or dsp_benchmark or not dai_benchmark:
|
|
263
|
-
self.
|
|
221
|
+
self.handler = create_handler(device_ip, device_adb_id)
|
|
264
222
|
|
|
265
223
|
configuration["device_ip"] = device_ip
|
|
266
224
|
|
|
267
225
|
self.power_monitor = None
|
|
268
226
|
if power_benchmark:
|
|
269
|
-
self.power_monitor =
|
|
227
|
+
self.power_monitor = MonitorPower(self.handler)
|
|
270
228
|
self.power_monitor.start()
|
|
271
229
|
|
|
272
230
|
self.dsp_monitor = None
|
|
273
231
|
if dsp_benchmark:
|
|
274
|
-
self.dsp_monitor =
|
|
232
|
+
self.dsp_monitor = MonitorDSP(self.handler)
|
|
275
233
|
self.dsp_monitor.start()
|
|
276
234
|
|
|
277
235
|
try:
|
|
@@ -315,7 +273,7 @@ class RVC4Benchmark(Benchmark):
|
|
|
315
273
|
# so we don't delete the wrong directory
|
|
316
274
|
assert self.model_name
|
|
317
275
|
|
|
318
|
-
self.
|
|
276
|
+
self.handler.shell(
|
|
319
277
|
f"rm -rf /data/modelconverter/{self.model_name}"
|
|
320
278
|
)
|
|
321
279
|
|
|
@@ -345,7 +303,6 @@ class RVC4Benchmark(Benchmark):
|
|
|
345
303
|
dlc_path = next(tmp_dir.rglob(dlc_model_name), None)
|
|
346
304
|
if not dlc_path:
|
|
347
305
|
raise ValueError("Could not find model.dlc in the archive.")
|
|
348
|
-
self.model_path = dlc_path
|
|
349
306
|
elif str(model_path).endswith(".dlc"):
|
|
350
307
|
dlc_path = model_path
|
|
351
308
|
else:
|
|
@@ -353,13 +310,14 @@ class RVC4Benchmark(Benchmark):
|
|
|
353
310
|
"Unsupported model format. Supported formats: .dlc, or HubAI model slug."
|
|
354
311
|
)
|
|
355
312
|
|
|
356
|
-
|
|
357
|
-
self.
|
|
313
|
+
input_specs = self._get_dlc_input_specs(dlc_path)
|
|
314
|
+
self.handler.shell(f"mkdir -p /data/modelconverter/{self.model_name}")
|
|
315
|
+
self.handler.push(
|
|
358
316
|
str(dlc_path), f"/data/modelconverter/{self.model_name}/model.dlc"
|
|
359
317
|
)
|
|
360
|
-
self._prepare_raw_inputs(num_images)
|
|
318
|
+
self._prepare_raw_inputs(input_specs, num_images)
|
|
361
319
|
|
|
362
|
-
_, stdout, _ = self.
|
|
320
|
+
_, stdout, _ = self.handler.shell(
|
|
363
321
|
# "source /data/modelconverter/source_me.sh && "
|
|
364
322
|
"snpe-parallel-run "
|
|
365
323
|
f"--container /data/modelconverter/{self.model_name}/model.dlc "
|
|
@@ -408,15 +366,17 @@ class RVC4Benchmark(Benchmark):
|
|
|
408
366
|
)
|
|
409
367
|
|
|
410
368
|
if isinstance(model_path, str):
|
|
411
|
-
modelPath =
|
|
412
|
-
dai.
|
|
413
|
-
|
|
414
|
-
|
|
415
|
-
|
|
416
|
-
|
|
369
|
+
modelPath = Path(
|
|
370
|
+
dai.getModelFromZoo(
|
|
371
|
+
dai.NNModelDescription(
|
|
372
|
+
model_path,
|
|
373
|
+
platform=device.getPlatformAsString(),
|
|
374
|
+
),
|
|
375
|
+
apiKey=environ.HUBAI_API_KEY or "",
|
|
376
|
+
)
|
|
417
377
|
)
|
|
418
378
|
elif str(model_path).endswith(".tar.xz"):
|
|
419
|
-
modelPath =
|
|
379
|
+
modelPath = Path(model_path)
|
|
420
380
|
elif str(model_path).endswith(".dlc"):
|
|
421
381
|
raise ValueError(
|
|
422
382
|
"DLC model format is not currently supported for dai-benchmark. Please use SNPE for DLC models."
|
|
@@ -426,19 +386,15 @@ class RVC4Benchmark(Benchmark):
|
|
|
426
386
|
"Unsupported model format. Supported formats: .tar.xz, or HubAI model slug."
|
|
427
387
|
)
|
|
428
388
|
|
|
429
|
-
|
|
430
|
-
inputNames = []
|
|
389
|
+
input_specs: list[InputSpec] = []
|
|
431
390
|
if isinstance(model_path, str) or str(model_path).endswith(".tar.xz"):
|
|
432
|
-
|
|
433
|
-
|
|
434
|
-
inputSizes.append(input.shape)
|
|
435
|
-
inputNames.append(input.name)
|
|
391
|
+
model_archive = dai.NNArchive(modelPath) # type: ignore[arg-type]
|
|
392
|
+
input_specs = self._get_dlc_input_specs(modelPath)
|
|
436
393
|
|
|
437
|
-
data_type = self._get_data_type()
|
|
438
394
|
inputData = dai.NNData()
|
|
439
|
-
for
|
|
440
|
-
|
|
441
|
-
inputData.addTensor(name,
|
|
395
|
+
for spec in input_specs:
|
|
396
|
+
input_data = self._create_random_input(spec)
|
|
397
|
+
inputData.addTensor(spec.name, input_data, dataType=spec.dai_dtype)
|
|
442
398
|
|
|
443
399
|
with dai.Pipeline(device) as pipeline:
|
|
444
400
|
benchmarkOut = pipeline.create(dai.node.BenchmarkOut)
|
|
@@ -449,7 +405,7 @@ class RVC4Benchmark(Benchmark):
|
|
|
449
405
|
if isinstance(model_path, str) or str(model_path).endswith(
|
|
450
406
|
".tar.xz"
|
|
451
407
|
):
|
|
452
|
-
neuralNetwork.setNNArchive(
|
|
408
|
+
neuralNetwork.setNNArchive(model_archive)
|
|
453
409
|
|
|
454
410
|
neuralNetwork.setBackendProperties(
|
|
455
411
|
{
|
|
@@ -187,6 +187,7 @@ class RVC4Exporter(Exporter):
|
|
|
187
187
|
args.append("--override_params")
|
|
188
188
|
elif self.quantization_mode == QuantizationMode.INT8_16_MIX:
|
|
189
189
|
self._add_args(args, ["--act_bitwidth", "16"])
|
|
190
|
+
args.append("--override_params")
|
|
190
191
|
elif self.encodings is not None:
|
|
191
192
|
args.append("--override_params")
|
|
192
193
|
|
|
@@ -1,6 +1,11 @@
|
|
|
1
|
-
from .adb_handler import AdbHandler
|
|
2
|
-
from .adb_monitor import AdbMonitorDSP, AdbMonitorPower
|
|
3
1
|
from .calibration_data import download_calibration_data
|
|
2
|
+
from .device_handlers import (
|
|
3
|
+
AdbHandler,
|
|
4
|
+
DeviceHandler,
|
|
5
|
+
SSHHandler,
|
|
6
|
+
create_handler,
|
|
7
|
+
)
|
|
8
|
+
from .device_monitors import MonitorDSP, MonitorPower
|
|
4
9
|
from .docker_utils import (
|
|
5
10
|
check_docker,
|
|
6
11
|
docker_build,
|
|
@@ -46,16 +51,19 @@ from .subprocess import SubprocessHandle, subprocess_run
|
|
|
46
51
|
|
|
47
52
|
__all__ = [
|
|
48
53
|
"AdbHandler",
|
|
49
|
-
"
|
|
50
|
-
"AdbMonitorPower",
|
|
54
|
+
"DeviceHandler",
|
|
51
55
|
"Metadata",
|
|
52
56
|
"ModelconverterException",
|
|
57
|
+
"MonitorDSP",
|
|
58
|
+
"MonitorPower",
|
|
53
59
|
"ONNXModifier",
|
|
54
60
|
"S3Exception",
|
|
61
|
+
"SSHHandler",
|
|
55
62
|
"SubprocessException",
|
|
56
63
|
"SubprocessHandle",
|
|
57
64
|
"archive_from_model",
|
|
58
65
|
"check_docker",
|
|
66
|
+
"create_handler",
|
|
59
67
|
"create_progress_handler",
|
|
60
68
|
"docker_build",
|
|
61
69
|
"docker_exec",
|