Apache TVM
Apache TVM 0.8 integration for optimized model inference
Apache TVM
The nd4j-tvm module integrates Apache TVM 0.8 for compiler-optimized model inference. TVM is a machine learning compiler that takes a model from a framework (PyTorch, TensorFlow, ONNX, MXNet, etc.), applies hardware-specific optimization passes (operator fusion, layout optimization, auto-tuning), and compiles it to a native binary for a target hardware backend.
The resulting compiled module is loaded in Java via the TVM runtime and nd4j-tvm bindings.
What TVM Provides
TVM operates in two phases:
Compile-time (Python): load a model, apply optimization passes, auto-tune for target hardware, and export a compiled module (
.soshared library + metadata JSON)Runtime (Java): load the compiled module, provide input tensors, run the optimized kernel
The key benefit is that TVM can produce kernels significantly faster than the original runtime, especially on CPUs with specific instruction sets (AVX-512, ARM NEON) and on GPUs and NPUs.
Maven Dependency
<dependency>
<groupId>org.nd4j</groupId>
<artifactId>nd4j-tvm</artifactId>
<version>${dl4j.version}</version>
</dependency>The module includes the TVM 0.8 runtime library. The compilation step (Python) must be done separately.
Step 1: Compile Your Model with TVM (Python)
TVM model compilation is done in Python using the tvm Python package.
Install TVM
Compile an ONNX Model
Compile a PyTorch Model
Auto-Tuning for Better Performance
Auto-tuning searches for the best kernel configurations for your hardware. This can take minutes to hours but typically improves inference speed significantly:
Step 2: Load and Run the Compiled Module in Java
TvmRunner Builder Options
TvmRunner is AutoCloseable. Use try-with-resources to ensure native resources are released:
Supported Target Backends
TVM can compile for many hardware targets. The target string is specified at compile time (Python):
x86 CPU (generic)
"llvm"
x86 with AVX2
"llvm -mcpu=core-avx2"
x86 with AVX-512
"llvm -mcpu=skylake-avx512"
ARM CPU
"llvm -device=arm_cpu -target=arm-linux-gnueabihf"
ARM64
"llvm -device=arm_cpu -target=aarch64-linux-gnu"
CUDA GPU
"cuda"
Vulkan
"vulkan"
Metal (macOS)
"metal"
WebAssembly
"wasm"
Compile-time target selection is independent of the Java runtime module; the compiled .so is target-specific.
Troubleshooting
UnsatisfiedLinkError loading the .so: ensure the compiled .so was built for the same target CPU/OS as where it is being loaded. Cross-compiled binaries (e.g., compiled on x86, loaded on ARM) will fail.
Input name mismatch: the input name passed to runner.exec() must match the name used during TVM compilation. If the name was "input_1" in the ONNX model, use "input_1" in the Java map.
Performance not as expected: if auto-tuning was not performed, performance may be similar to unoptimized execution. Run auto-tuning for the target hardware to see TVM's full benefit.
TVM version mismatch: the nd4j-tvm module bundles TVM 0.8 runtime libraries. A compiled module from a different TVM version may not load. Compile with TVM 0.8 to match.
Last updated
Was this helpful?