Unverified Commit c4b6469a authored by Umang Yadav's avatar Umang Yadav Committed by GitHub
Browse files

Python Binding for the Manual Graph Buidling (#1143)

Adds following API binding and tests to python :

add_return
add_instruction
add_parameter
create_module.
parent 0295965d
......@@ -12,31 +12,31 @@ shape
.. py:method:: type()
An integer that represents the type
An integer that represents the type.
:rtype: int
.. py:method:: lens()
A list of the lengths of the shape
A list of the lengths of the shape.
:rtype: list[int]
.. py:method:: strides()
A list of the strides of the shape
A list of the strides of the shape.
:rtype: list[int]
.. py:method:: elements()
The number of elements in the shape
The number of elements in the shape.
:rtype: int
.. py:method:: bytes()
The number of bytes the shape uses
The number of bytes the shape uses.
:rtype: int
......@@ -102,20 +102,25 @@ argument
Generate an argument with random data.
:param shape s: Shape of argument to generate.
:param int seed: The seed used for random number generation
:param int seed: The seed used for random number generation.
:rtype: argument
.. py:function:: fill_argument(s, value)
Fill argument of shape s with value.
:param shape s: Shape of argument to fill.
:param int value: Value to fill in the argument.
:rtype argument
target
------
.. py:class:: target()
This represents the compiliation target.
This represents the compilation target.
.. py:function:: get_target(name)
......@@ -126,6 +131,37 @@ target
:rtype: target
module
------
.. py:method:: print()
Prints the contents of the module as list of instructions.
.. py:method:: add_instruction(op, args, mod_args=[])
Adds instruction into the module.
:param operation op: 'migraphx.op' to be added as instruction.
:param list[instruction] args: list of inputs to the op.
:param list[module] mod_args: optional list of module arguments to the operator.
:rtype instruction
.. py:method:: add_parameter(name, shape)
Adds a parameter to the module with provided name and shape.
:param str name: name of the parameter.
:param shape shape: shape of the parameter.
:rtype instruction
.. py:method:: add_return(args)
Adds a return instruction into the module.
:param list[instruction] args: instruction arguments which need to be returned from the module.
:rtype instruction
program
-------
......@@ -135,21 +171,27 @@ program
.. py:method:: clone()
Make a copy of the program
Make a copy of the program.
:rtype: program
.. py:method:: get_parameter_names()
Get all the input arguments' or parameters' names to the program as a list.
:rtype list[str]
.. py:method:: get_parameter_shapes()
Get the shapes of all the input parameters in the program.
:rtype: dict[str, shape]
.. py:method:: get_shape()
.. py:method:: get_output_shapes()
Get the shape of the final output of the program.
Get the shapes of the final outputs of the program.
:rtype: shape
:rtype: list[shape]
.. py:method:: compile(t, offload_copy=True, fast_math=True)
......@@ -159,6 +201,19 @@ program
:param bool offload_copy: For targets with offloaded memory(such as the gpu), this will insert instructions during compilation to copy the input parameters to the offloaded memory and to copy the final result from the offloaded memory back to main memory.
:param bool fast_math: Optimize math functions to use faster approximate versions. There may be slight accuracy degredation when enabled.
.. py:method:: get_main_module()
Get main module of the program.
:rtype module
.. py:method:: create_module(name)
Create and add a module of provided name into the program.
:param str name : name of the new module.
:rtype module
.. py:method:: run(params)
Run the program.
......@@ -167,7 +222,11 @@ program
:type params: dict[str, argument]
:return: The result of the last instruction.
:rtype: argument
:rtype: list[argument]
.. py:method:: sort()
Sort the modules of the program such that instructions appear in topologically sorted order.
.. py:function:: quantize_fp16(prog, ins_names=["all"])
......@@ -190,10 +249,22 @@ program
:type ins_names: list[str]
op
--
.. py::class:: op(name, kwargs)
Construct an operation with name and arguments.
:param str name : name of the operation, must be supported by MIGraphX.
:param dict[str, any] kwargs: arguments to the operation.
:rtype operation
parse_onnx
----------
.. py:function:: parse_onnx(filename, default_dim_value=1, map_input_dims={}, skip_unknown_operators=false, print_program_on_error=false)
.. py:function:: parse_onnx(filename, default_dim_value=1, map_input_dims={}, skip_unknown_operators=false, print_program_on_error=false, max_loop_iterations=10)
Load and parse an onnx file.
......@@ -202,20 +273,21 @@ parse_onnx
:param str map_input_dims: Explicitly specify the dims of an input.
:param str skip_unknown_operators: Continue parsing onnx file if an unknown operator is found.
:param str print_program_on_error: Print program if an error occurs.
:param int max_loop_iterations: Maximum iteration number for the loop operator.
:rtype: program
parse_tf
--------
.. py:function:: parse_tf(filename, is_nhwc=True, batch_size=1)
.. py:function:: parse_tf(filename, is_nhwc=True, batch_size=1, map_input_dims=dict(), output_names=[])
Load and parse an tensorflow protobuf file file.
:param str filename: Path to file.
:param bool is_nhwc: Use nhwc as default format.
:param str batch_size: default batch size to use (if not specified in protobuf).
:param dict[str, list[int]] map_input_dims: Optional arg to explictly specify dimensions of the inputs.
:param list[str] output_names: Optional argument specify names of the output nodes.
:rtype: program
load
......@@ -223,7 +295,7 @@ load
.. py:function:: load(filename, format='msgpack')
Load a MIGraphX program
Load a MIGraphX program.
:param str filename: Path to file.
:param str format: Format of file. Valid options are msgpack or json.
......@@ -235,7 +307,7 @@ save
.. py:function:: save(p, filename, format='msgpack')
Save a MIGraphX program
Save a MIGraphX program.
:param program p: Program to save.
:param str filename: Path to file.
......
......@@ -3,6 +3,8 @@
#include <pybind11/stl.h>
#include <pybind11/numpy.h>
#include <migraphx/program.hpp>
#include <migraphx/instruction_ref.hpp>
#include <migraphx/operation.hpp>
#include <migraphx/quantization.hpp>
#include <migraphx/generate.hpp>
#include <migraphx/ref/target.hpp>
......@@ -95,7 +97,6 @@ migraphx::value to_value(py::kwargs kwargs)
auto&& val = arg.second;
visit_py(val, [&](auto py_val) { v[key] = py_val; });
}
return v;
}
} // namespace migraphx
......@@ -256,13 +257,38 @@ MIGRAPHX_PYBIND11_MODULE(migraphx, m)
py::class_<migraphx::target>(m, "target");
py::class_<migraphx::module>(m, "module")
py::class_<migraphx::instruction_ref>(m, "instruction_ref");
py::class_<migraphx::module, std::unique_ptr<migraphx::module, py::nodelete>>(m, "module")
.def("print", [](const migraphx::module& mm) { std::cout << mm << std::endl; })
.def("__eq__", std::equal_to<migraphx::module>{})
.def("__ne__", std::not_equal_to<migraphx::module>{})
.def(
"add_instruction",
[](migraphx::module& mm,
const migraphx::operation& op,
std::vector<migraphx::instruction_ref>& args,
std::vector<migraphx::module*>& mod_args) {
return mm.add_instruction(op, args, mod_args);
},
py::arg("op"),
py::arg("args"),
py::arg("mod_args") = std::vector<migraphx::module*>{})
.def(
"add_parameter",
[](migraphx::module& mm, const std::string& name, const migraphx::shape shape) {
return mm.add_parameter(name, shape);
},
py::arg("name"),
py::arg("shape"))
.def(
"add_return",
[](migraphx::module& mm, std::vector<migraphx::instruction_ref>& args) {
return mm.add_return(args);
},
py::arg("args"))
.def("__repr__", [](const migraphx::module& mm) { return migraphx::to_string(mm); });
py::class_<migraphx::program>(m, "program")
.def(py::init([]() { return migraphx::program(); }))
.def("get_parameter_names", &migraphx::program::get_parameter_names)
.def("get_parameter_shapes", &migraphx::program::get_parameter_shapes)
.def("get_output_shapes", &migraphx::program::get_output_shapes)
......@@ -277,11 +303,11 @@ MIGRAPHX_PYBIND11_MODULE(migraphx, m)
py::arg("t"),
py::arg("offload_copy") = true,
py::arg("fast_math") = true)
.def("get_main_module",
[](migraphx::program& p) {
auto* mm = p.get_main_module();
return *mm;
})
.def("get_main_module", [](const migraphx::program& p) { return p.get_main_module(); })
.def(
"create_module",
[](migraphx::program& p, const std::string& name) { return p.create_module(name); },
py::arg("name"))
.def("run",
[](migraphx::program& p, py::dict params) {
migraphx::parameter_map pm;
......@@ -399,6 +425,7 @@ MIGRAPHX_PYBIND11_MODULE(migraphx, m)
m.def("get_target", &migraphx::make_target);
m.def("generate_argument", &migraphx::generate_argument, py::arg("s"), py::arg("seed") = 0);
m.def("fill_argument", &migraphx::fill_argument, py::arg("s"), py::arg("value"));
m.def("quantize_fp16",
&migraphx::quantize_fp16,
py::arg("prog"),
......
......@@ -27,6 +27,7 @@ add_py_test(ref test_cpu.py WORKING_DIRECTORY ${TEST_ONNX_DIR})
add_py_test(save_load test_save_load.py WORKING_DIRECTORY ${TEST_ONNX_DIR})
add_py_test(op test_op.py WORKING_DIRECTORY ${TEST_ONNX_DIR})
add_py_test(shape test_shape.py WORKING_DIRECTORY ${TEST_ONNX_DIR})
add_py_test(module_construct test_module_construct.py WORKING_DIRECTORY ${TEST_ONNX_DIR})
if(MIGRAPHX_ENABLE_GPU)
add_py_test(gpu_offload test_gpu_offload.py WORKING_DIRECTORY ${TEST_ONNX_DIR})
add_py_test(gpu test_gpu.py WORKING_DIRECTORY ${TEST_ONNX_DIR})
......
import migraphx
def test_add_op():
p = migraphx.program()
mm = p.get_main_module()
param_shape = migraphx.shape(lens=[3, 3], type="float")
x = mm.add_parameter("x", param_shape)
y = mm.add_parameter("y", param_shape)
add_op = mm.add_instruction(migraphx.op("add"), [x, y])
mm.add_return([add_op])
p.compile(migraphx.get_target("ref"))
params = {}
params["x"] = migraphx.generate_argument(param_shape)
params["y"] = migraphx.generate_argument(param_shape)
output = p.run(params)[-1].tolist()
assert output == [
a + b for a, b in zip(params["x"].tolist(), params["y"].tolist())
]
def test_if_then_else():
param_shape = migraphx.shape(lens=[3, 3], type="float")
cond_shape = migraphx.shape(type="bool", lens=[1], strides=[0])
def create_program():
p = migraphx.program()
mm = p.get_main_module()
cond = mm.add_parameter("cond", cond_shape)
x = mm.add_parameter("x", param_shape)
y = mm.add_parameter("y", param_shape)
then_mod = p.create_module("If_0_if")
x_identity = then_mod.add_instruction(migraphx.op("identity"), [x])
then_mod.add_return([x_identity])
else_mod = p.create_module("If_0_else")
y_identity = else_mod.add_instruction(migraphx.op("identity"), [y])
else_mod.add_return([y_identity])
if_ins = mm.add_instruction(migraphx.op("if"), [cond],
[then_mod, else_mod])
ret = mm.add_instruction(migraphx.op("get_tuple_elem", **{"index": 0}),
[if_ins])
mm.add_return([ret])
return p
params = {}
params["x"] = migraphx.generate_argument(param_shape)
params["y"] = migraphx.generate_argument(param_shape)
def run_prog(cond):
p = create_program()
p.compile(migraphx.get_target("ref"))
params["cond"] = migraphx.fill_argument(cond_shape, cond)
output = p.run(params)[-1]
return output
assert run_prog(True) == params["x"]
assert run_prog(False) == params["y"]
if __name__ == "__main__":
test_add_op()
test_if_then_else()
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment