The TornadoVM Hybrid API is the bridge between Java-authored GPU kernels and NVIDIA’s hand-tuned native libraries. A singleDocumentation Index
Fetch the complete documentation index at: https://mintlify.com/Deepak-Sangle/TornadoVM/llms.txt
Use this file to discover all available pages before exploring further.
TaskGraph can interleave @Parallel or KernelContext tasks with calls into cuBLAS, cuFFT, cuDNN, cuSPARSE, cuBLASLt, and CUTLASS — all sharing the same TornadoVM-managed device buffers on one CUDA stream. There are no manual cudaMemcpy calls between the JIT and native sides, no host synchronization points, and no separate memory management to maintain. Every library call becomes a library task: a first-class citizen in the TaskGraph that flows through the same ALLOC/TRANSFER/LAUNCH bytecodes as any other task.
The Hybrid API requires the CUDA backend. Build with
make BACKEND=cuda and source setvars.sh. Library tasks on OpenCL or Metal backends are silently reported as UNSUPPORTED.Core Concepts
Library Tasks
A library task is a
SchedulableTask without a JIT sketch. Its argument access descriptors (READ_ONLY, WRITE_ONLY, READ_WRITE) come from the provider factory, so the data-flow graph tracks transfers automatically — just like any other task.Shared Device Buffers
JIT kernels and library calls operate on the same TornadoVM buffer objects. Data produced by a Java kernel stays on the GPU and feeds directly into the native library call — no host round-trips.
Same CUDA Stream
Every provider binds its native handle to the backend’s CUDA stream (via
cublasSetStream, cudnnSetStream, etc.). JIT kernels, transfers, and library calls all execute in order on one stream — no manual synchronization.The prepare() Hook
Shape-dependent allocations (cuFFT plans, cuDNN descriptors, cuBLAS workspaces) happen in a
prepare() hook called before CUDA Graph capture. This makes library tasks capture-safe — dispatch() allocates nothing.The libraryTask Method
The only new API surface is .libraryTask(id, factory, args...) — a sibling of .task(...) on TaskGraph. There are 20 overloads accepting 1–20 typed arguments. The second argument is always a method reference to a provider factory that returns a LibraryTaskDescriptor.
Provider Catalog
nvidia/cublas — Dense Linear Algebra
nvidia/cublas — Dense Linear Algebra
FP32, TF32, FP16, and BF16 GEMV and GEMM operations. cuBLAS uses column-major storage; for row-major TornadoVM arrays either pass the transpose op (
SGEMV) or swap operands (SGEMM).| Factory | Operation |
|---|---|
CuBlas::cublasSgemv | y = α·op(A)·x + β·y |
CuBlas::cublasSgemm | C = α·op(A)·op(B) + β·C |
CuBlas::cublasSgemmTF32 | SGEMM on TF32 Tensor Cores |
CuBlas::cublasGemmExFP16 | FP16 inputs, FP16 output, FP32 Tensor Core accumulation |
CuBlas::cublasGemmExFP16FP32 | FP16 inputs, FP32 output, FP32 Tensor Core accumulation |
CuBlas::cublasGemmExBF16 | BF16 inputs and output, FP32 accumulation |
CuBlas::cublasSgemmStridedBatched | Batched SGEMM over flat arrays |
nvidia/cublaslt — Fused-Epilogue GEMM
nvidia/cublaslt — Fused-Epilogue GEMM
FP32, FP16, and FP8 matmul with fused bias and activation epilogues via the cuBLASLt API. Plans (descriptors + heuristic-selected algorithm) are created once per problem shape and cached with a 32 MiB device workspace.
| Factory | Epilogue | Notes |
|---|---|---|
CuBlasLt::ltMatmulFP32 | None | FP32 matmul with plan caching |
CuBlasLt::ltMatmulFP16 | None | FP16 matmul, FP32 Tensor Core accumulation |
CuBlasLt::ltMatmulFP8 | None | E4M3 operands, FP16 output, TN layout, ld must be multiple of 16 B |
CuBlasLt::ltMatmulBiasFP16 | BIAS | C = op(A)·op(B) + bias, fused |
CuBlasLt::ltMatmulGeluBiasFP16 | GELU_BIAS | C = GELU(op(A)·op(B) + bias), tanh approximation, fully fused |
nvidia/cufft — Fast Fourier Transforms
nvidia/cufft — Fast Fourier Transforms
1D and 2D FFT transforms with automatic plan caching per
(n, batch) pair.| Factory | Transform |
|---|---|
CuFft::cufftForwardC2C / cufftInverseC2C | 1D FP32 complex-to-complex |
CuFft::cufftForwardR2C / cufftInverseC2R | 1D real ↔ complex (Hermitian) |
CuFft::cufftForwardZ2Z / cufftInverseZ2Z | 1D FP64 complex-to-complex |
CuFft::cufftForward2dC2C / cufftInverse2dC2C | 2D FP32 complex-to-complex |
nvidia/cudnn — Deep Learning Primitives
nvidia/cudnn — Deep Learning Primitives
FP32/NCHW activations, pooling, and convolution, plus fused FP16 flash attention via the cuDNN graph API.
| Factory | Operation |
|---|---|
CuDnn::cudnnSoftmax | Per-row numerically stable softmax |
CuDnn::cudnnRelu / cudnnSigmoid / cudnnTanh | Element-wise activations |
CuDnn::cudnnMaxPool2d | 2D max pooling |
CuDnn::cudnnConv2d | 2D cross-correlation convolution |
CuDnn::sdpaForward | Fused scaled-dot-product attention (FP16) |
nvidia/cusparse — Sparse Linear Algebra
nvidia/cusparse — Sparse Linear Algebra
FP32 sparse-matrix products over CSR format (32-bit, zero-based indices).
| Factory | Operation |
|---|---|
Cusparse::cusparseSpMV | y = A·x, CSR sparse-dense |
Cusparse::cusparseSpMM | C = A·B, sparse-dense, row-major output |
nvidia/cutlass — Open-Template GEMM
nvidia/cutlass — Open-Template GEMM
FP32 SIMT and FP16 Tensor Core GEMM with fused epilogues. Row-major natively — no operand-swap needed.
| Factory | Operation |
|---|---|
Cutlass::cutlassSgemm | FP32 SIMT GEMM |
Cutlass::cutlassHgemm | FP16 Tensor Core GEMM |
Cutlass::cutlassGemmBiasRelu | Fused relu(A·B + bias) |
Cutlass::cutlassGemmBiasGelu | Fused gelu(A·B + bias) |
Composition Patterns
- JIT → Library → JIT
- Library Chains
- Mixed Precision
The canonical “sandwich” pattern: a JIT kernel preprocesses data, a library call does the heavy compute, and a second JIT kernel post-processes the result — all on the same device buffers with no host round-trip.
Profiling Library Tasks
Library tasks are profiled through the same mechanism as JIT tasks. Enable the console profiler with the--enableProfiler console flag — each library task reports TASK_KERNEL_TIME (host-timed, bounded by CUDA stream markers) alongside BACKEND, DEVICE, and METHOD.
Writing Your Own Provider
Adding a new library requires no changes to the TornadoVM core runtime. Providers are discovered viajava.util.ServiceLoader. Follow these four steps, mirroring the tornado-cublas module as the reference implementation.
Create a Factory class
Build a
LibraryTaskDescriptor that declares the library name, function name, parameter list, and per-argument access modes.Implement TornadoLibraryProvider
Create a context per
(device, planId), bind the native handle to the CUDA stream, implement prepare() for shape-dependent allocations (idempotent), and dispatch() for the actual native call.Register the provider in module-info.java
Declare the service provision in the module descriptor and the corresponding Also add
META-INF/services file.vendor.mylib.provider.MyProvider to:
src/main/resources/META-INF/services/uk.ac.manchester.tornado.runtime.library.spi.TornadoLibraryProviderAdd a JNI native module
Create a
tornado-drivers/mylib-jni CMake module (see cudnn-jni for a host library, cutlass-jni for device-code compilation) under the cuda-backend Maven profile. Wire it into the root pom.xml, tornado-assembly, and tornado.py (--add-modules).The native module is self-guarding: if its shared library is missing at build time, the .so is skipped, and the provider reports UNSUPPORTED at runtime instead of failing the build.Troubleshooting
| Symptom | Cause & Fix |
|---|---|
Task reports UNSUPPORTED | Default device is not CUDA, or the native .so / vendor library is missing. Build with make BACKEND=cuda; install the required library. |
UnsatisfiedLinkError: libtornado-<x> | Native module was skipped at build time. Set the corresponding *_ROOT environment variable and rebuild. |
| Wrong result from cuBLAS | Column-major mismatch — use transpose op for SGEMV, or swap operands for SGEMM. |
| CUTLASS FP16 rejects a shape | k or n not a multiple of 4 (8-byte alignment constraint). Pad dimensions or switch to cutlassSgemm (FP32, no constraint). |
CUDA_ERROR_LAUNCH_FAILED after a Tensor Core call | Kernel built for the wrong SM. Rebuild with CUDA_ARCH=<your compute capability>. |
Build Requirements
| Provider | Extra Dependency | How to Install |
|---|---|---|
| cuBLAS, cuBLASLt, cuFFT, cuSPARSE | Bundled with the CUDA Toolkit | Nothing extra required |
| cuDNN | libcudnn9 (separate package) | apt install libcudnn9-cuda-12 libcudnn9-dev-cuda-12 |
| CUTLASS | Header-only, fetched by CMake | Automatic via FetchContent (v3.5.1); requires CUDA 12+ |