From 80e94f4ec2820fe92d51270a672ef029d9072d28 Mon Sep 17 00:00:00 2001 From: Jang Jiseob Date: Mon, 6 Jan 2025 19:18:50 +0900 Subject: [PATCH] [onert/python] Introduce BaseSession (#14527) This commit introduces the class BaseSession. - Inroduce the class BaseSession to group common functionalities - Modify setup.py to make Python files easier to find. ONE-DCO-1.0-Signed-off-by: ragmani --- infra/nnfw/python/setup.py | 25 +++++-- runtime/onert/api/python/package/__init__.py | 8 +- .../api/python/package/common/__init__.py | 3 + .../api/python/package/common/basesession.py | 75 +++++++++++++++++++ runtime/onert/api/python/package/infer.py | 58 -------------- .../api/python/package/infer/__init__.py | 3 + .../onert/api/python/package/infer/session.py | 27 +++++++ 7 files changed, 133 insertions(+), 66 deletions(-) create mode 100644 runtime/onert/api/python/package/common/__init__.py create mode 100644 runtime/onert/api/python/package/common/basesession.py delete mode 100644 runtime/onert/api/python/package/infer.py create mode 100644 runtime/onert/api/python/package/infer/__init__.py create mode 100644 runtime/onert/api/python/package/infer/session.py diff --git a/infra/nnfw/python/setup.py b/infra/nnfw/python/setup.py index d140e17e2cb..1df1832582c 100644 --- a/infra/nnfw/python/setup.py +++ b/infra/nnfw/python/setup.py @@ -52,12 +52,23 @@ # copy *py files to package_directory PY_DIR = os.path.join(THIS_FILE_DIR, '../../../runtime/onert/api/python/package') - for py_file in os.listdir(PY_DIR): - if py_file.endswith(".py"): - src_path = os.path.join(PY_DIR, py_file) - dest_path = os.path.join(THIS_FILE_DIR, package_directory) - shutil.copy(src_path, dest_path) - print(f"Copied '{src_path}' to '{dest_path}'") + for root, dirs, files in os.walk(PY_DIR): + # Calculate the relative path from the source directory + rel_path = os.path.relpath(root, PY_DIR) + dest_dir = os.path.join(THIS_FILE_DIR, package_directory) + dest_sub_dir = os.path.join(dest_dir, rel_path) + print(f"dest_sub_dir '{dest_sub_dir}'") + + # Ensure the corresponding destination subdirectory exists + os.makedirs(dest_sub_dir, exist_ok=True) + + # Copy only .py files + for py_file in files: + if py_file.endswith(".py"): + src_path = os.path.join(root, py_file) + # dest_path = os.path.join(THIS_FILE_DIR, package_directory) + shutil.copy(src_path, dest_sub_dir) + print(f"Copied '{src_path}' to '{dest_sub_dir}'") # remove architecture directory if os.path.exists(package_directory): @@ -142,6 +153,6 @@ def get_directories(): url='https://github.com/Samsung/ONE', license='Apache-2.0, MIT, BSD-2-Clause, BSD-3-Clause, Mozilla Public License 2.0', has_ext_modules=lambda: True, - packages=[package_directory], + packages=find_packages(), package_data={package_directory: so_list}, install_requires=['numpy >= 1.19']) diff --git a/runtime/onert/api/python/package/__init__.py b/runtime/onert/api/python/package/__init__.py index 05e235a3112..9970ced45f6 100644 --- a/runtime/onert/api/python/package/__init__.py +++ b/runtime/onert/api/python/package/__init__.py @@ -1,2 +1,8 @@ -__all__ = ['infer'] +# Define the public API of the onert package +__all__ = ["infer", "tensorinfo"] + +# Import and expose the infer module's functionalities from . import infer + +# Import and expose tensorinfo +from .common import tensorinfo as tensorinfo diff --git a/runtime/onert/api/python/package/common/__init__.py b/runtime/onert/api/python/package/common/__init__.py new file mode 100644 index 00000000000..fb46ba379bd --- /dev/null +++ b/runtime/onert/api/python/package/common/__init__.py @@ -0,0 +1,3 @@ +from .basesession import BaseSession, tensorinfo + +__all__ = ["BaseSession", "tensorinfo"] diff --git a/runtime/onert/api/python/package/common/basesession.py b/runtime/onert/api/python/package/common/basesession.py new file mode 100644 index 00000000000..d9f62770474 --- /dev/null +++ b/runtime/onert/api/python/package/common/basesession.py @@ -0,0 +1,75 @@ +import numpy as np + +from ..native import libnnfw_api_pybind + + +def num_elems(tensor_info): + """Get the total number of elements in nnfw_tensorinfo.dims.""" + n = 1 + for x in range(tensor_info.rank): + n *= tensor_info.dims[x] + return n + + +class BaseSession: + """ + Base class providing common functionality for inference and training sessions. + """ + def __init__(self, backend_session): + """ + Initialize the BaseSession with a backend session. + Args: + backend_session: A backend-specific session object (e.g., nnfw_session). + """ + self.session = backend_session + self.inputs = [] + self.outputs = [] + + def __getattr__(self, name): + """ + Delegate attribute access to the bound NNFW_SESSION instance. + Args: + name (str): The name of the attribute or method to access. + Returns: + The attribute or method from the bound NNFW_SESSION instance. + """ + return getattr(self.session, name) + + def set_inputs(self, size, inputs_array=[]): + """ + Set the input tensors for the session. + Args: + size (int): Number of input tensors. + inputs_array (list): List of numpy arrays for the input data. + """ + for i in range(size): + input_tensorinfo = self.session.input_tensorinfo(i) + + if len(inputs_array) > i: + input_array = np.array(inputs_array[i], dtype=input_tensorinfo.dtype) + else: + print( + f"Model's input size is {size}, but given inputs_array size is {len(inputs_array)}.\n{i}-th index input is replaced by an array filled with 0." + ) + input_array = np.zeros((num_elems(input_tensorinfo)), + dtype=input_tensorinfo.dtype) + + self.session.set_input(i, input_array) + self.inputs.append(input_array) + + def set_outputs(self, size): + """ + Set the output tensors for the session. + Args: + size (int): Number of output tensors. + """ + for i in range(size): + output_tensorinfo = self.session.output_tensorinfo(i) + output_array = np.zeros((num_elems(output_tensorinfo)), + dtype=output_tensorinfo.dtype) + self.session.set_output(i, output_array) + self.outputs.append(output_array) + + +def tensorinfo(): + return libnnfw_api_pybind.infer.nnfw_tensorinfo() diff --git a/runtime/onert/api/python/package/infer.py b/runtime/onert/api/python/package/infer.py deleted file mode 100644 index f3f95c63c52..00000000000 --- a/runtime/onert/api/python/package/infer.py +++ /dev/null @@ -1,58 +0,0 @@ -import numpy as np -import os -import shutil - -from .native import libnnfw_api_pybind - - -def num_elems(tensor_info): - """Get the total number of elements in nnfw_tensorinfo.dims.""" - n = 1 - for x in range(tensor_info.rank): - n *= tensor_info.dims[x] - return n - - -class session(libnnfw_api_pybind.nnfw_session): - """Class inherited nnfw_session for easily processing input/output""" - def __init__(self, nnpackage_path, backends="cpu"): - super().__init__(nnpackage_path, backends) - self.inputs = [] - self.outputs = [] - self.set_outputs(self.output_size()) - - def set_inputs(self, size, inputs_array=[]): - """Set inputs for each index""" - for i in range(size): - input_tensorinfo = self.input_tensorinfo(i) - - if len(inputs_array) > i: - input_array = np.array(inputs_array[i], dtype=input_tensorinfo.dtype) - else: - print( - f"model's input size is {size} but given inputs_array size is {len(inputs_array)}.\n{i}-th index input is replaced by an array filled with 0." - ) - input_array = np.zeros((num_elems(input_tensorinfo)), - dtype=input_tensorinfo.dtype) - - self.set_input(i, input_array) - self.inputs.append(input_array) - - def set_outputs(self, size): - """Set outputs for each index""" - for i in range(size): - output_tensorinfo = self.output_tensorinfo(i) - output_array = np.zeros((num_elems(output_tensorinfo)), - dtype=output_tensorinfo.dtype) - self.set_output(i, output_array) - self.outputs.append(output_array) - - def inference(self): - """Inference model and get outputs""" - self.run() - - return self.outputs - - -def tensorinfo(): - return libnnfw_api_pybind.nnfw_tensorinfo() diff --git a/runtime/onert/api/python/package/infer/__init__.py b/runtime/onert/api/python/package/infer/__init__.py new file mode 100644 index 00000000000..0b8b162c905 --- /dev/null +++ b/runtime/onert/api/python/package/infer/__init__.py @@ -0,0 +1,3 @@ +from .session import session + +__all__ = ["session"] diff --git a/runtime/onert/api/python/package/infer/session.py b/runtime/onert/api/python/package/infer/session.py new file mode 100644 index 00000000000..da59c4ae653 --- /dev/null +++ b/runtime/onert/api/python/package/infer/session.py @@ -0,0 +1,27 @@ +from ..native import libnnfw_api_pybind +from ..common.basesession import BaseSession + + +class session(BaseSession): + """ + Class for inference using nnfw_session. + """ + def __init__(self, nnpackage_path, backends="cpu"): + """ + Initialize the inference session. + Args: + nnpackage_path (str): Path to the nnpackage file or directory. + backends (str): Backends to use, default is "cpu". + """ + super().__init__(libnnfw_api_pybind.infer.nnfw_session(nnpackage_path, backends)) + self.session.prepare() + self.set_outputs(self.session.output_size()) + + def inference(self): + """ + Perform model and get outputs + Returns: + list: Outputs from the model. + """ + self.session.run() + return self.outputs