| # Dynamically loaded custom module sample |
| |
| This sample derives from the [basic](./samples/custom_module/basic/) sample to |
| show how to build a custom C++ module that can be dynamically loaded by the IREE |
| runtime. |
| |
| The custom module is implemented using a C++ module wrapper layer in |
| [`module.cc`](./module.cc) and loaded by the `iree-run-module` tool using the |
| `--module=` flag. Any IREE tool can use the module and user applications hosting |
| the IREE runtime can programmatically load the module using |
| `iree_vm_dynamic_module_load_from_file`. |
| |
| ## Background |
| |
| IREE's VM is used to dynamically link modules of various types together at |
| runtime (C, C++, IREE's VM bytecode, etc). Via this mechanism any number of |
| modules containing exported functions and types that can be used across modules |
| can extend IREE's base functionality. When possible it's preferred to statically |
| link modules to allow for smaller binaries and a better development experience |
| but it can be desirable to inject custom user modules into pre-built IREE |
| release tools or extend user applications with hermetically built modules from |
| others without fully rebuilding/synchronizing versions. It's easy to fall into |
| [dependency hell](https://en.wikipedia.org/wiki/Dependency_hell) and usage of |
| dynamic modules should be carefully considered. |
| |
| ## Instructions |
| |
| 1. Build or install the `iree-base-compiler` binary: |
| |
| ```sh |
| python -m pip install iree-base-compiler |
| ``` |
| |
| [See here](https://iree.dev/reference/bindings/python/) |
| for general instructions on installing the compiler. |
| |
| 3. Compile the [example module](./test/example.mlir) to a .vmfb file: |
| |
| ```sh |
| # This simple sample doesn't use tensors and can be compiled in host-only |
| # mode to avoid the need for the HAL. |
| iree-compile \ |
| --iree-hal-target-device=local \ |
| --iree-hal-local-target-device-backends=vmvx \ |
| samples/custom_module/dynamic/test/example.mlir \ |
| -o=/tmp/example.vmfb |
| ``` |
| |
| 3. Build the `iree_samples_custom_module_dynamic_module` CMake target : |
| |
| ```sh |
| cmake -B ../iree-build/ -G Ninja -DCMAKE_BUILD_TYPE=RelWithDebInfo . \ |
| -DCMAKE_C_FLAGS=-DIREE_VM_EXECUTION_TRACING_FORCE_ENABLE=1 |
| cmake --build ../iree-build/ \ |
| --target iree-run-module \ |
| --target iree_samples_custom_module_dynamic_module |
| ``` |
| |
| (here we force runtime execution tracing for demonstration purposes) |
| |
| [See here](https://iree.dev/building-from-source/getting-started/) |
| for general instructions on building using CMake. |
| |
| 4. Run the example program using the main `iree-run-module` tool: |
| |
| ```sh |
| ../iree-build/tools/iree-run-module \ |
| --module=../iree-build/samples/custom_module/dynamic/module.so@create_custom_module \ |
| --module=/tmp/example.vmfb \ |
| --function=main |
| ``` |
| |
| ## Limitations |
| |
| Currently tracing with Tracy is not supported in dynamic modules. The hosting |
| application can be built with tracing enabled but the module shared libraries |
| must not have Tracy linked in. |
| |
| ## Exporting dynamic modules |
| |
| Custom dynamic modules are identical to static ones as seen in the other samples |
| but contain a single exported function that can be used by the runtime to |
| instantiate the module and provide it with parameters. |
| |
| By default the name of the creation function is `iree_vm_dynamic_module_create` |
| but users can override this to allow a single shared library to provide multiple |
| modules. In this sample the custom name is `create_custom_module` and the tools |
| are instructed to call that function via the `shared_library.so@fn_name` syntax. |
| |
| ### Versioning |
| |
| The creation function must check the incoming `max_version` to ensure that the |
| dynamic module API is compatible. Today the API is unstable and it's expected |
| that dynamic modules are rebuilt alongside new runtime versions. |
| |
| ### Parameters |
| |
| Module creation functions are provided with a list of key value parameters |
| either programmatically provided to `iree_vm_dynamic_module_load_from_file` or |
| passed as flags. To pass the flags use a URI query string: |
| |
| ``` |
| iree-run-module --module=library.so?key0=value0&key1=value1 |
| ``` |
| |
| ### Type registration |
| |
| Custom types defined by the dynamic module must be registered with the |
| `iree_vm_instance_t` provided to the creation function. |
| |
| Any externally defined types such as the builtin VM types |
| (`!vm.list`/`iree_vm_list_t`) or the HAL types |
| (`!hal.buffer_view`/`iree_hal_buffer_view_t`) must be resolved from the instance |
| prior to use. `iree_vm_resolve_builtin_types` and |
| `iree_hal_module_resolve_all_types` (or one of the more restricted sets like |
| `iree_hal_module_resolve_common_types`) can be used to perform the resolution. |