Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add Python interface for compilation and one single interface for compilation and running process #1690

Merged
merged 44 commits into from
Oct 24, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
44 commits
Select commit Hold shift + click to select a range
c2cf87c
Add compiler interface to python
Jiaqing-ASU Aug 6, 2022
e26c7dd
Fix bugs and update README with more details
Jiaqing-ASU Aug 19, 2022
5847e05
Update README and environment set up instructions
Jiaqing-ASU Aug 19, 2022
f0d5b6d
Merge branch 'onnx:main' into python-interface
Jiaqing-ASU Sep 12, 2022
6803e50
Merge branch 'main' into python-interface
AlexandreEichenberger Sep 12, 2022
db3c0be
Resolve conflicts
Jiaqing-ASU Sep 13, 2022
d2f42e6
Merge branch 'python-interface' of https://github.com/Jiaqing-ASU/onn…
Jiaqing-ASU Sep 13, 2022
15068e4
Minor fix
Jiaqing-ASU Sep 13, 2022
a21b369
Merge branch 'main' into python-interface
Jiaqing-ASU Sep 13, 2022
e6332fe
Adjust the PyOnnxMlirCompiler with new interface
Jiaqing-ASU Sep 13, 2022
492ee8f
Merge branch 'main' into python-interface
AlexandreEichenberger Sep 14, 2022
52aa227
first version submit after redesigning the python interface
Jiaqing-ASU Sep 18, 2022
f7f481a
Merge branch 'main' into python-interface
AlexandreEichenberger Sep 19, 2022
be18794
Modify the new class PyCompileExecutionSession
Jiaqing-ASU Sep 20, 2022
e116da5
Merge branch 'main' into python-interface
Jiaqing-ASU Sep 20, 2022
af84aa9
Merge branch 'main' into python-interface
AlexandreEichenberger Sep 20, 2022
70620ca
Merge branch 'main' into python-interface
Jiaqing-ASU Sep 28, 2022
a6306ce
Fix undefined symbol issue in PyCompileExecutionSession
Jiaqing-ASU Sep 28, 2022
4f065c3
Merge branch 'python-interface' of https://github.com/Jiaqing-ASU/onn…
Jiaqing-ASU Sep 28, 2022
3363c27
Merge branch 'main' into python-interface
Jiaqing-ASU Sep 28, 2022
8bdecd2
Merge branch 'main' into python-interface
AlexandreEichenberger Sep 30, 2022
9b57c29
Fix interfaces
Jiaqing-ASU Sep 30, 2022
68c8663
Merge branch 'python-interface' of https://github.com/Jiaqing-ASU/onn…
Jiaqing-ASU Sep 30, 2022
ffbb827
Merge branch 'main' into python-interface
Jiaqing-ASU Sep 30, 2022
afc4f36
Update README
Jiaqing-ASU Sep 30, 2022
ae1fcfe
Merge branch 'python-interface' of https://github.com/Jiaqing-ASU/onn…
Jiaqing-ASU Sep 30, 2022
3aa31e0
Merge branch 'main' into python-interface
Jiaqing-ASU Sep 30, 2022
9d18a91
Merge branch 'main' into python-interface
AlexandreEichenberger Oct 3, 2022
3a841fc
Merge branch 'main' into python-interface
Jiaqing-ASU Oct 4, 2022
cf8a376
Merge branch 'main' into python-interface
AlexandreEichenberger Oct 12, 2022
25a9f33
Add SuppressWarnings
Jiaqing-ASU Oct 12, 2022
1a70b83
Merge branch 'python-interface' of https://github.com/Jiaqing-ASU/onn…
Jiaqing-ASU Oct 12, 2022
b454e67
Merge branch 'main' into python-interface
AlexandreEichenberger Oct 13, 2022
75fcbc2
Add EHsc to enable RTTI and exceptions
Jiaqing-ASU Oct 17, 2022
d252912
Merge branch 'main' into python-interface
Jiaqing-ASU Oct 17, 2022
2b2e121
Merge branch 'main' into python-interface
AlexandreEichenberger Oct 18, 2022
7ed3f84
Fix comments and refactor PyOMCompileExecutionSession
Jiaqing-ASU Oct 20, 2022
51673d2
Merge branch 'python-interface' of https://github.com/Jiaqing-ASU/onn…
Jiaqing-ASU Oct 20, 2022
78ee9f2
Merge branch 'main' into python-interface
Jiaqing-ASU Oct 20, 2022
30d6c85
Fix comments
Jiaqing-ASU Oct 20, 2022
be8db77
Merge branch 'main' into python-interface
AlexandreEichenberger Oct 20, 2022
005c68c
Fix comments and revert to previous version
Jiaqing-ASU Oct 21, 2022
0e68f91
Merge branch 'main' into python-interface
Jiaqing-ASU Oct 21, 2022
cbda68c
Merge branch 'main' into python-interface
AlexandreEichenberger Oct 24, 2022
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
222 changes: 208 additions & 14 deletions docs/UsingPyRuntime.md
Original file line number Diff line number Diff line change
@@ -1,31 +1,44 @@
<!--- SPDX-License-Identifier: Apache-2.0 -->

# Using PyRuntime
# Using Python interfaces

onnx-mlir has a runtime utility to run ONNX models compiled as a shared library
by `onnx-mlir --EmitLib`. The runtime is implemented in C++ by the `ExecutionSession` class
(src/Runtime/ExecutionSession.hpp) and has an associated Python binding generated by
[pybind library](https://github.com/pybind/pybind11).
Onnx-mlir has runtime utilities to compile and run ONNX models in Python.
These utilities are implemented by the `OnnxMlirCompiler` compiler interface
(include/OnnxMlirCompiler.h) and the `ExecutionSession` class
(src/Runtime/ExecutionSession.hpp).
Both utilities have an associated Python binding generated by [pybind library](https://github.com/pybind/pybind11).

## PyRuntime Module
## Configuring the Python interfaces

Using pybind, a C/C++ binary can be directly imported by the Python interpreter. For onnx-mlir,
such binary is generated by `PyExecutionSession` (src/Runtime/PyExecutionSession.hpp) and built
as a shared library to `build/Debug/lib/PyRuntime.cpython-<target>.so`.
Using pybind, a C/C++ binary can be directly imported by the Python interpreter.
For onnx-mlir, there are three such libraries, one to compile onnx-mlir models,
one to run the models and the other one is to compile and run the models.

## Configuring and using PyRuntime
1. The library to compile onnx-mlir models is generated
by `PyOMCompileSession` (src/Compiler/PyOMCompileSession.hpp) and build as a shared
library to `build/Debug/lib/PyCompile.cpython-<target>.so`.
2. The library to run onnx-mlir models is generated
by by `PyExecutionSession` (src/Runtime/PyExecutionSession.hpp) and built
as a shared library to `build/Debug/lib/PyRuntime.cpython-<target>.so`.
3. The library to compile and run onnx-mlir models is generated
by by `PyOMCompileExecutionSession` (src/Runtime/PyOMCompileExecutionSession.hpp) and built
as a shared library to `build/Debug/lib/PyCompileAndRuntime.cpython-<target>.so`.
This lobrary takes an .onnx file and the options as inputs, it will load it and then compile and run it.

### Configuration
The module can be imported normally by the Python interpreter as long as it is in your
PYTHONPATH. Another alternative is to create a symbolic link to it in your working directory.

```shell
cd <working directory>
ln -s <path to PyRuntime>
ln -s <path to PyCompile>
ln -s <path to PyCompileAndRuntime>
python3
```

### Running the PyRuntime interface
# Python interface to run models: PyRuntime

## Running the PyRuntime interface

An ONNX model is a computation graph and it is often the case that the graph
has a single entry point to trigger the computation. Below is an example of doing
Expand Down Expand Up @@ -80,8 +93,8 @@ for entry_point in entry_points:
```

## PyRuntime model API
The complete interface to ExecutionSession can be seen in the sources mentioned previously. However,
using the constructor and run method is enough to perform inferences.
The complete interface to ExecutionSession can be seen in the sources mentioned previously.
However, using the constructor and run method is enough to perform inferences.

```python
def __init__(self, shared_lib_path: str, use_default_entry_point: bool):
Expand Down Expand Up @@ -124,3 +137,184 @@ def set_entry_point(self, name: str):
name: an entry point name.
"""
```

# Python interface to compile models: PyCompile

## Running the PyCompile interface

An ONNX model can be compiled directly from the command line. The resulting library can then be executed using Python as shown in the previous sections. At times, it might be convenient to also compile a model directly in Python. This section explores the Python methods to do so.

The PyOMCompileSession object will take a file name while constructing. For the compilation, `compile()` will take a `flags` string as an input which will override any default options set from the env var.

```python
import numpy as np
from PyCompile import PyOMCompileSession

# Load onnx model and create PyOMCompileSession object.
file = './mnist.onnx'
compiler = PyOMCompileSession(file)
# Generate the library file. Success when rc == 0 while set the opt as "-O3"
rc = compiler.compile("-O3")
# Get the output file name
model = compiler.get_compiled_file_name()
if rc:
print("Failed to compile with error code", rc)
exit(1)
print("Compiled onnx file", file, "to", model, "with rc", rc)
```

The `PyCompile` module exports the `PyOMCompileSession` class to drive the
compilation of a ONNX model into an executable model.
Typically, a compiler object is created for a given model by giving it the file name of the ONNX model.
Then, all the compiler options can be set as a whole `std::string` to generate the desired executable.
Finally, the compilation itself is performed by calling the `compile()` command where the user passes the options string as the input of this function.

The `compile()` commands returns a return code reflecting the status of the compilation.
A zero value indicates success, and nonzero values reflect the error code.
Because different Operating Systems may have different suffixes for libraries,
the output file name can be retrieved using the `get_compiled_file_name()` method.

## PyCompile model API

The complete interface to OnnxMlirCompiler can be seen in the sources mentioned previously.
However, using the constructor and the methods below are enough to compile models.

```python
def __init__(self, file_name: str):
"""
Constructor for an ONNX model contained in a file.
Args:
file_name: relative or absolute path to your ONNX model.
"""
def __init__(self, input_buffer: void *, buffer_size: int):
"""
Constructor for an ONNX model contained in an input buffer.
Args:
input_buffer: buffer containing the protobuf representation of the model.
buffer_size: byte size of the input buffer.
"""
def compile(self, flags: str):
"""
Method to compile a model from a file.
Args:
flags: all the options users would like to set.
Returns:
Zero on success, error code on failure.
"""
def compile_from_array(self, output_base_name: str, target: OnnxMlirTarget):
"""
Method to compile a model from an array.
Args:
output_base_name: base name (relative or absolute, without suffix)
where the compiled model should be written into.
target: target for the compiler's output. Typical values are
OnnxMlirTarget.emit_lib or emit_jni.
Returns:
Zero on success, error code on failure.
"""
def get_compiled_file_name(self):
"""
Method to provide the full (absolute or relative) output compiled file name, including
its suffix.
Returns:
String containing the fle name after successful compilation; empty string on failure.
"""
def get_error_message(self):
"""
Method to provide the compilation error message.
Returns:
String containing the error message; empty string on success.
"""
```

# Python interface to compile and run models: PyCompileAndRuntime

## Running the PyCompileAndRuntime interface

```python
import numpy as np
from PyCompileAndRuntime import PyOMCompileExecutionSession

# Load onnx model and create CompileExecutionSession object.
inputFileName = './mnist.onnx'
# Set the full name of compiled model
sharedLibPath = './mnist.so'
# Set the compile option as "-O3"
session = PyOMCompileExecutionSession(inputFileName,sharedLibPath,"-O3")

# Print the models input/output signature, for display.
# Signature functions for info only, commented out if they cause problems.
session.print_input_signature()
session.print_output_signature()

# Do inference using the default entry point.
a = np.full((1, 1, 28, 28), 1, np.dtype(np.float32))
outputs = session.run(input=[a])

for output in outputs:
print(output.shape)
```

## PyCompileAndRuntime model API

The PyCompileAndRuntime is a new class, which combines compile and execution. Its constructor takes the `.onnx` input file and compile the model with the options given by the user and then run the model with an input.

```python
def __init__(self, input_model_path: str, compiled_file_path: str, flags: str, use_default_entry_point: bool):
"""
Constructor for an ONNX model contained in a file.
Args:
input_model_path: relative or absolute path to your ONNX model.
compiled_file_path: relative or absolute path to your compiled file.
flags: all the options users would like to set.
use_default_entry_point: use the default entry point that is `run_main_graph` or not. Set to True by default.
"""
def get_compiled_result(self):
"""
Method to provide the results of the compilation.
Returns:
Int containing the results. 0 represents successful compilation; others on failure.
"""
def get_compiled_file_name(self):
"""
Method to provide the full (absolute or relative) output file name, including
its suffix.
Returns:
String containing the fle name after successful compilation; empty string on failure.
"""
def get_error_message(self):
Jiaqing-ASU marked this conversation as resolved.
Show resolved Hide resolved
"""
Method to provide the compilation error message.
Returns:
String containing the error message; empty string on success.
"""
def entry_points(self) -> List[str]:
"""
Returns:
A list of entry point names.
"""
def set_entry_point(self, name: str):
"""
Args:
name: an entry point name.
"""
def run(self, input: List[ndarray]) -> List[ndarray]:
"""
Args:
input: A list of NumPy arrays, the inputs of your model.

Returns:
A list of NumPy arrays, the outputs of your model.
"""
def input_signature(self) -> str:
"""
Returns:
A string containing a JSON representation of the model's input signature.
"""

def output_signature(self) -> str:
"""
Returns:
A string containing a JSON representation of the model's output signature.
"""
```
Loading