Files
openvino/tests/stress_tests/scripts/get_testdata.py
Vitaliy Urusovskij 25cadb661b [Stress] Enable OMZ info_dumper.py in get_testdata.py (#1485)
* [Stress] Support OMZ model_info.py in get_testdata.py

* [Stress] Copy IRs from OMZ models folder to IRs folder

* [Stress] Support modified configs in C++ tests

* [Stress] Deprecate support of --env_conf due refactoring of configs

* [Stress] Update configs:
1. Removed env configs due deprecation
2. Moved test configs to a new format

* [Stress] Extend MemCheck records with info from test config
2020-07-31 12:13:12 +03:00

242 lines
11 KiB
Python
Executable File

#!/usr/bin/env python3
# Copyright (C) 2020 Intel Corporation
# SPDX-License-Identifier: Apache-2.0
#
""" Script to acquire model IRs for stress tests.
Usage: ./scrips/get_testdata.py
"""
# pylint:disable=line-too-long
import argparse
import logging as log
import multiprocessing
import os
import shutil
import subprocess
import sys
import json
from inspect import getsourcefile
from pathlib import Path
from xml.etree import ElementTree as ET
log.basicConfig(format="{file}: [ %(levelname)s ] %(message)s".format(file=os.path.basename(__file__)),
level=log.INFO, stream=sys.stdout)
# Parameters
OMZ_NUM_ATTEMPTS = 6
DOWNLOADER_JOBS_NUM = 4
def abs_path(relative_path):
"""Return absolute path given path relative to the current file.
"""
return os.path.realpath(
os.path.join(os.path.dirname(getsourcefile(lambda: 0)), relative_path))
class VirtualEnv:
"""Class implemented creation and use of virtual environment."""
is_created = False
def __init__(self, venv_dir):
self.venv_dir = Path(abs_path('..')) / venv_dir
if sys.platform.startswith('linux') or sys.platform == 'darwin':
self.venv_executable = self.venv_dir / "bin" / "python3"
else:
self.venv_executable = self.venv_dir / "Scripts" / "python3.exe"
def get_venv_executable(self):
"""Returns path to executable from virtual environment."""
return str(self.venv_executable)
def get_venv_dir(self):
"""Returns path to virtual environment root directory."""
return str(self.venv_dir)
def create(self):
"""Creates virtual environment."""
cmd = '{executable} -m venv {venv}'.format(executable=sys.executable,
venv=self.get_venv_dir())
run_in_subprocess(cmd)
self.is_created = True
def install_requirements(self, *requirements):
"""Installs provided requirements. Creates virtual environment if it hasn't been created."""
if not self.is_created:
self.create()
cmd = '{executable} -m pip install --upgrade pip'.format(executable=self.get_venv_executable())
for req in requirements:
# Don't install requirements via one `pip install` call to prevent "ERROR: Double requirement given"
cmd += ' && {executable} -m pip install -r {req}'.format(executable=self.get_venv_executable(), req=req)
run_in_subprocess(cmd)
def create_n_install_requirements(self, *requirements):
"""Creates virtual environment and installs provided requirements in it."""
self.create()
self.install_requirements(*requirements)
def run_in_subprocess(cmd, check_call=True):
"""Runs provided command in attached subprocess."""
log.info(cmd)
if check_call:
subprocess.check_call(cmd, shell=True)
else:
subprocess.call(cmd, shell=True)
def main():
"""Main entry point.
"""
parser = argparse.ArgumentParser(
description='Acquire test data',
formatter_class=argparse.ArgumentDefaultsHelpFormatter)
parser.add_argument('--test_conf', required=True, type=Path,
help='Path to a test config .xml file containing models '
'which will be downloaded and converted to IRs via OMZ.')
parser.add_argument('--omz_repo', required=False,
help='Path to Open Model Zoo (OMZ) repository. It will be used to skip cloning step.')
parser.add_argument('--mo_tool', type=Path,
default=Path(abs_path('../../../model-optimizer/mo.py')).resolve(),
help='Path to Model Optimizer (MO) runner. Required for OMZ converter.py only.')
parser.add_argument('--omz_models_out_dir', type=Path,
default=abs_path('../_omz_out/models'),
help='Directory to put test data into. Required for OMZ downloader.py and converter.py')
parser.add_argument('--omz_irs_out_dir', type=Path,
default=abs_path('../_omz_out/irs'),
help='Directory to put test data into. Required for OMZ converter.py only.')
parser.add_argument('--omz_cache_dir', type=Path,
default=abs_path('../_omz_out/cache'),
help='Directory with test data cache. Required for OMZ downloader.py only.')
parser.add_argument('--no_venv', action="store_true",
help='Skip preparation and use of virtual environment to convert models via OMZ converter.py.')
parser.add_argument('--skip_omz_errors', action="store_true",
help='Skip errors caused by OMZ while downloading and converting.')
args = parser.parse_args()
# constants
PRECISION = "FP32"
# parse models from test config
test_conf_obj = ET.parse(str(args.test_conf))
test_conf_root = test_conf_obj.getroot()
models_from_cfg = []
for model_rec in test_conf_root.find("models"):
if "source" in model_rec.attrib and "name" in model_rec.attrib:
if model_rec.attrib["source"] == "omz":
models_from_cfg.append(model_rec.attrib["name"])
else:
log.warning("Record from test config '{}' doesn't contain attributes 'source' or 'name'"
.format(args.test_conf.resolve()))
# prepare Open Model Zoo
if args.omz_repo:
omz_path = Path(args.omz_repo).resolve()
else:
omz_path = Path(abs_path('..')) / "_open_model_zoo"
# clone Open Model Zoo into temporary path
if os.path.exists(str(omz_path)):
shutil.rmtree(str(omz_path))
cmd = 'git clone --single-branch --branch develop' \
' https://github.com/opencv/open_model_zoo {omz_path}'.format(omz_path=omz_path)
run_in_subprocess(cmd)
# prepare models list
downloader_path = omz_path / "tools" / "downloader" / "downloader.py"
models_list_path = args.omz_models_out_dir / "models_list.txt"
cmd = '{downloader_path} --print_all'.format(downloader_path=downloader_path)
models_available = subprocess.check_output(cmd, shell=True, universal_newlines=True).split("\n")
models_to_run = set(models_from_cfg).intersection(models_available)
os.makedirs(str(args.omz_models_out_dir), exist_ok=True)
log.info("List of models from {models_list_path} used for downloader.py and converter.py: "
"{models_to_run}".format(models_list_path=models_list_path, models_to_run=",".join(models_to_run)))
with open(str(models_list_path), "w") as file:
file.writelines([name + "\n" for name in models_to_run])
if set(models_from_cfg) - models_to_run:
log.warning("List of models defined in config but not available in OMZ: {}"
.format(",".join(set(models_from_cfg) - models_to_run)))
# update test config with Open Model Zoo info
info_dumper_path = omz_path / "tools" / "downloader" / "info_dumper.py"
cmd = "{executable} {info_dumper_path} --list {models_list_path}"\
.format(executable=sys.executable, info_dumper_path=info_dumper_path,
models_list_path=models_list_path)
out = subprocess.check_output(cmd, shell=True, universal_newlines=True)
models_info = json.loads(out)
fields_to_add = ["framework", "subdirectory"]
models_root = test_conf_root.find("models")
for model_rec in list(models_root): # convert iterator to list to prevent incorrect removing of records
if model_rec.attrib.get("source") == "omz" and "name" in model_rec.attrib:
if model_rec.attrib["name"] not in models_to_run:
# remove models from test config which aren't available in OMZ
models_root.remove(model_rec)
else:
# Open Model Zoo ensures name uniqueness of every model
models_info_rec = next(iter([rec for rec in models_info if rec["name"] == model_rec.attrib["name"]]))
info_to_add = {key: models_info_rec[key] for key in fields_to_add}
model_rec.attrib.update(info_to_add)
model_rec.attrib["precision"] = PRECISION
model_rec.attrib["path"] = str(
Path(model_rec.attrib["subdirectory"]) / PRECISION / (model_rec.attrib["name"] + ".xml"))
model_rec.attrib["full_path"] = str(
args.omz_irs_out_dir / model_rec.attrib["subdirectory"] / PRECISION / (model_rec.attrib["name"] + ".xml"))
test_conf_obj.write(args.test_conf)
# prepare models
cmd = '{downloader_path} --list {models_list_path}' \
' --num_attempts {num_attempts}' \
' --output_dir {models_dir}' \
' --cache_dir {cache_dir}' \
' --jobs {jobs_num}'.format(downloader_path=downloader_path, models_list_path=models_list_path,
num_attempts=OMZ_NUM_ATTEMPTS,
models_dir=args.omz_models_out_dir,
cache_dir=args.omz_cache_dir,
jobs_num=DOWNLOADER_JOBS_NUM)
run_in_subprocess(cmd, check_call=not args.skip_omz_errors)
# Open Model Zoo doesn't copy downloaded IRs to converter.py output folder where IRs should be stored.
# Do it manually to have only one folder with IRs
for ir_src_path in args.omz_models_out_dir.rglob("*.xml"):
ir_dst_path = args.omz_irs_out_dir / os.path.relpath(ir_src_path, args.omz_models_out_dir)
shutil.copytree(ir_src_path.parent, ir_dst_path.parent)
# prepare virtual environment and install requirements
python_executable = sys.executable
if not args.no_venv:
Venv = VirtualEnv("./.stress_venv")
requirements = [
omz_path / "tools" / "downloader" / "requirements.in",
args.mo_tool.parent / "requirements.txt",
args.mo_tool.parent / "requirements_dev.txt",
omz_path / "tools" / "downloader" / "requirements-caffe2.in",
omz_path / "tools" / "downloader" / "requirements-pytorch.in"
]
Venv.create_n_install_requirements(*requirements)
python_executable = Venv.get_venv_executable()
# convert models to IRs
converter_path = omz_path / "tools" / "downloader" / "converter.py"
# NOTE: remove --precision if both precisions (FP32 & FP16) required
cmd = '{executable} {converter_path} --list {models_list_path}' \
' -p {executable}' \
' --precision={PRECISION}' \
' --output_dir {irs_dir}' \
' --download_dir {models_dir}' \
' --mo {mo_tool} --jobs {workers_num}'.format(executable=python_executable, PRECISION=PRECISION,
converter_path=converter_path,
models_list_path=models_list_path, irs_dir=args.omz_irs_out_dir,
models_dir=args.omz_models_out_dir, mo_tool=args.mo_tool,
workers_num=multiprocessing.cpu_count())
run_in_subprocess(cmd, check_call=not args.skip_omz_errors)
if __name__ == "__main__":
main()