Skip to main content

Documentation 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 is the central building block of every TornadoVM program. It is a fluent, mutable container that accumulates tasks (Java method references), data-transfer directives, and device hints into a named graph. Once the graph is fully specified, calling snapshot() seals it into an immutable form that can be handed to a TornadoExecutionPlan for execution. Because TaskGraph is itself mutable, you can modify it between snapshot calls — enabling dynamic workloads — without affecting any previously snapshotted graphs that are already in flight.
Every task name within a single TaskGraph must be unique. Registering two tasks with the same id throws a TornadoTaskRuntimeException at runtime. Prefix task IDs with a short namespace (e.g. "myGraph.add") to avoid collisions when composing multiple graphs.

Constructor

TaskGraph(String name)
constructor
Creates a new, empty task graph with the given name. The name is used as an identifier in logging, profiler output, and when addressing individual tasks from an execution plan (e.g. "graphName.taskId").
TaskGraph tg = new TaskGraph("vectorOps");

Adding Tasks

TornadoVM maps each overloaded task() variant to the number of parameters your kernel method accepts. All variants return this, enabling fluent chaining.
task(String id, Task code)
TaskGraph
Adds a zero-argument task. Useful for side-effect-free initialization kernels that operate entirely on device-side state.
ParameterTypeDescription
idStringUnique task identifier within this graph.
codeTaskA reference to a Java method with no parameters.
task(String id, Task1<T1> code, T1 arg)
TaskGraph
Adds a task with one typed argument. The generic type T1 is inferred from the argument.
ParameterTypeDescription
idStringUnique task identifier.
codeTask1<T1>Method reference — e.g. MyKernels::vectorAdd.
argT1The single argument passed to the kernel.
task(String id, Task2<T1,T2> code, T1 arg1, T2 arg2)
TaskGraph
Adds a task with two typed arguments. The pattern extends uniformly through Task3, Task4, … up to Task20, each accepting the corresponding number of typed positional arguments.
TornadoVM ships typed variants from Task (zero args) through Task20 (twenty args). Choose the overload whose arity matches your kernel signature exactly — the compiler uses the type parameters to infer argument layouts for the JIT.

Library Tasks

Library tasks invoke functions from external native libraries (e.g., NVIDIA cuBLAS) via a factory interface pattern. The factory lambda receives the typed arguments, calls the native binding, and returns a TornadoNativeFunction that the runtime dispatches.
libraryTask(String id, LibraryTask1<T1> code, T1 arg1)
TaskGraph
Adds a single-argument library task. The LibraryTask1<T1> functional interface is a factory: it receives arg1 and produces the native-function descriptor that TornadoVM schedules.
tg.libraryTask("t0", CuBlas::cublasSgemv, handleWrapper);
Variants exist from LibraryTask1 through LibraryTask20, matching the arity of the underlying library call.
Library tasks are supported only on the CUDA backend when the corresponding native library (e.g., cuBLAS) is installed and discoverable at runtime. Using a library task on the OpenCL or PTX fallback backend will throw a runtime exception.

Data Transfer

Data transfers between the JVM heap and device memory are declared explicitly on the TaskGraph. The runtime uses the specified mode to decide when to perform each copy, eliminating redundant transfers across repeated executions.
transferToDevice(int mode, Object... objects)
TaskGraph
Tags one or more Java objects for upload to the device. The mode constant from DataTransferMode controls the transfer schedule.
ParameterTypeDescription
modeintA DataTransferMode constant (see table below).
objectsObject...Varargs list of arrays or TornadoVM typed arrays to upload.
transferToHost(int mode, Object... objects)
TaskGraph
Tags one or more Java objects for readback from the device after kernel execution. Typically called with EVERY_EXECUTION for output buffers or UNDER_DEMAND when you want to control readback timing explicitly via TornadoExecutionResult.transferToHost().
ParameterTypeDescription
modeintA DataTransferMode constant.
objectsObject...Varargs list of arrays to read back to host memory.
persistOnDevice(Object... objects)
TaskGraph
Tags objects to remain on the device after execution without being copied back to the host. Equivalent to transferToHost(DataTransferMode.UNDER_DEMAND, objects). Useful for pipeline stages where intermediate buffers feed the next graph without ever touching the CPU.
consumeFromDevice(Object... objects)
TaskGraph
Instructs the runtime to consume input objects directly from device memory belonging to a previous task graph, skipping any host-to-device transfer. The objects must have been produced and persisted by a preceding TaskGraph execution within the same execution plan.

DataTransferMode Constants

DataTransferMode is a utility class (not an enum) in uk.ac.manchester.tornado.api.enums that exposes three static final int constants. Pass these constants directly to transferToDevice() and transferToHost().
FIRST_EXECUTION
int = 0
Copies data to/from the device only during the very first execution of the task graph. Subsequent executions reuse the on-device buffer as read-only. Use for constant inputs such as model weights or look-up tables.
EVERY_EXECUTION
int = 1
Copies data to/from the device on every call to execute(). Use for inputs that change between invocations or for output buffers that must always be read back.
UNDER_DEMAND
int = 2
Suppresses automatic copy-out. Data remains on the device until the programmer explicitly calls TornadoExecutionResult.transferToHost(objects). Use to pipeline multi-graph workflows where intermediate results are consumed on-device.

Snapshotting

snapshot()
ImmutableTaskGraph
Seals the current state of the TaskGraph into an ImmutableTaskGraph. The immutable snapshot can be passed to a TornadoExecutionPlan. The original TaskGraph remains mutable and can be modified to produce further snapshots.
ImmutableTaskGraph itg = tg.snapshot();

Pre-built Native Tasks

For advanced use cases, TornadoVM can schedule pre-built native kernels (e.g., OpenCL C source files) without going through the Java JIT path.
prebuiltTask(String id, String entryPoint, String filename, AccessorParameters accessorParameters)
TaskGraph
Adds a pre-built native kernel task. TornadoVM loads and compiles the native source at the path specified by filename and invokes the function named entryPoint.
ParameterTypeDescription
idStringUnique task identifier within this graph.
entryPointStringName of the kernel function to invoke (e.g., "vectorAdd").
filenameStringPath to the native kernel source file (e.g., an OpenCL C .cl file).
accessorParametersAccessorParametersDescribes read/write access mode for each kernel parameter.
prebuiltTask(String id, String entryPoint, String filename, AccessorParameters accessorParameters, int[] atomics)
TaskGraph
Variant of prebuiltTask() that additionally supplies an atomics region (int[]) for kernels that use atomic operations on a pre-allocated integer buffer.
ParameterTypeDescription
idStringUnique task identifier.
entryPointStringKernel entry-point name.
filenameStringPath to the native kernel source file.
accessorParametersAccessorParametersAccess mode descriptors for each parameter.
atomicsint[]Integer array allocated for atomic operations within the kernel.

Complete Fluent Example

The following example shows the full lifecycle of a TaskGraph: declare inputs, add a task, declare outputs, snapshot, and execute.
import uk.ac.manchester.tornado.api.*;
import uk.ac.manchester.tornado.api.enums.DataTransferMode;
import uk.ac.manchester.tornado.api.annotations.Parallel;

public class VectorAdd {

    public static void add(float[] a, float[] b, float[] c) {
        for (@Parallel int i = 0; i < a.length; i++) {
            c[i] = a[i] + b[i];
        }
    }

    public static void main(String[] args) {
        int size = 1024;
        float[] a = new float[size], b = new float[size], c = new float[size];
        // ... fill a and b ...

        TaskGraph tg = new TaskGraph("vectorOps")
            .transferToDevice(DataTransferMode.EVERY_EXECUTION, a, b)
            .task("t0", VectorAdd::add, a, b, c)
            .transferToHost(DataTransferMode.EVERY_EXECUTION, c);

        ImmutableTaskGraph itg = tg.snapshot();
        try (TornadoExecutionPlan plan = new TornadoExecutionPlan(itg)) {
            plan.execute();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

Execution Plan

Learn how to wrap ImmutableTaskGraph in a TornadoExecutionPlan and control execution policy.

Annotations

Use @Parallel and @Reduce to mark loops and accumulators for automatic GPU parallelisation.

Build docs developers (and LLMs) love