TornadoVM 7.0(2026-09-22)把 NVIDIA CUDA Tile(cuTile)接到 Java:方法首参换成 TileContext 后,按 tile 写 kernel,由 tile 编译器选线程映射与 Tensor Core 指令。文档侧原先的 Kernel API 已改称 KernelContext API;7.0.1(2026-09-24)把 CUDA backend(含 cuTile 编译路径)以及 cuBLAS、cuDNN 等 library bindings 发上 Maven Central。站内此前没有 TornadoVM 条目,下面按 GitHub Release、README、programming guide 与 tile-api 文档核对后写。

7.0 / 7.0.1 事实表

项 内容
仓库 beehive-lab/TornadoVM
版本 v7.0.0(2026-09-22)、跟进 v7.0.1(2026-09-24)
JDK 21–27;预构建 SDK 分 jdk21 与 jdk22plus 两族
许可证 Tornado-API、Examples、Annotation 等为 Apache 2.0;Tornado-Runtime、Tornado-Drivers 为 GPLv2 with Classpath Exception(README「Licenses per module」)
SDK 分发 按加速后端拆包:opencl、cuda、metal、full;GitHub Release assets 与 SDKMAN! 候选版本同名
Maven io.github.beehive-lab:tornado-api / tornado-runtime,版本 7.0.1-jdk21 或 7.0.1-jdk22plus;7.0.1 起另有 tornado-drivers-cuda 与 tornado-cublas、tornado-cudnn、tornado-cufft、tornado-curand、tornado-cusparse、tornado-cudf、tornado-cutlass(Central 已有上述版本)
官网 tornadovm.org

7.0.0 里和选题直接相关的条目:#1083 引入 Java CUDA Tile 执行路径(TileContext API);#1112 在 programming guide 文档化 TileContext,并把 Kernel API 章节改名为 KernelContext API;#1110 增加 cuDF library-task;#1085 增加 Method-based task API,便于运行时生成的方法也进图。半精度读写、MMA accumulator、Metal half、寄存器过重 1D kernel 等修复一并进了 7.0。recover.bailout 在 7.0 改为默认关闭(#1107)。

7.0.1 的 #1116 补上 Central 缺口:此前 Central 主要是 tornado-api、tornado-runtime、tornado-matrices,依赖 CUDA library task 或 CUDA backend 的工程(例如 jitllm)在 7.0.0 上解析失败。合并后按 JDK 族发布 tornado-drivers-cuda(含 cuTile 编译路径)和上述 library bindings;cudnn-jni / cudf-jni 等 CMake 原生 shim 仍只进 SDK,Central 上是纯 Java、运行时用 java.lang.foreign 加载 NVIDIA 库。

jdk21 构建带 --enable-preview,类文件钉在 JDK 21;jdk22plus 面向 22 及以上(含 27),换同族 JDK 通常不用重装 SDK。Maven 坐标后缀必须与所用 SDK 族一致。

Release 资产命名大致是 tornadovm-<ver>-<jdk族>-<backend>-<os>-<arch>.zip|tar.gz。Linux amd64 上常见 opencl / cuda / full;Windows 有 opencl 与 cuda;macOS aarch64 有 opencl 与 metal。选包时先定 JDK 族,再定后端,避免装了 opencl 包却去跑 TileContext(tile 只在 cuda 包 / full 包里的 CUDA 路径可用)。

TileContext、KernelContext,以及和原先路径的关系

TornadoVM 挂在现有 OpenJDK 或 GraalVM 上,把选定的 Java 方法 JIT 成 CUDA / OpenCL / Metal,自己管理主机与设备间的缓冲迁移。并行怎么写,由方法签名与注解决定,三种写法共用 TaskGraph 与 TornadoExecutionPlan,可以混在一张图里。

Loop Parallel(@Parallel) 在循环上标注并行维,运行时推断全局与局部工作大小。同一方法也能当普通顺序 Java 跑,适合先写通再上设备。

KernelContext 要求方法首参是 KernelContext。写法接近 CUDA / OpenCL:用 globalIdx / localIdx、分配 local(shared)内存、插 barrier,也可在 CUDA 上走 mma.sync 一类 Tensor Core 内建。JIT 仍走 SIMT 路径(NVIDIA 上大致是 Graal IR → PTX → NVRTC → cubin)。7.0 文档把这块从「Kernel API」统一叫成 KernelContext API,类名与用法本身是延续,主要是命名与章节对齐。

TileContext(7.0 新增,仅 CUDA backend) 要求方法首参是 TileContext。你写的是一块 tile 上的运算:view 出张量视图、partition 切块、load / store、mma / matmul、归约与 elementwise 等。API 里不出现 thread、warp、fragment。编译走 nvcc -tilecubin --tile-only,由 tile 编译器决定背后用多少线程、发哪条 Tensor Core 指令、shared memory 怎么铺。tile 边长必须是编译期常量且为 2 的幂(字面量或 static final int);问题规模(extent)可以是运行时参数,不会特化整颗 kernel。WorkerGrid 计的是 tile block 数,不要设 local work(CUDATileScheduler 钉成 1x1x1)。

硬件门槛(官方 tile-api):CUDA Toolkit 13.3+、驱动 R580+、算力 8.0+。缺任一条件时抛 TornadoDeviceTileNotSupported。每一条 TileContext 操作在 JVM 上也有实现,同一方法可以在 CPU 上调试;recover.bailout 默认关闭,避免编译失败时静默退回主机却看起来「算对了」。

关系上,TileContext 是第三条编译路径,并不取代 KernelContext。需要显式 local memory、barrier、按线程写算法,或从现有 CUDA/OpenCL 思路平移时,继续用 KernelContext;愿意把工作单位抬到 tile、少碰线程映射时,用 TileContext。README 与 unittests(如 TestTileChaining)强调:@Parallel、KernelContext、TileContext 与 native library task 可共享设备缓冲与同一 CUDA stream,并可 withCUDAGraph() 整图捕获后一次 launch 重放。

选型上不必追求「全部改成 tile」。很多预处理、后处理、不规则索引仍更适合 @Parallel 或 KernelContext;GEMM 类热点若已有 cuBLAS,直接 libraryTask 往往更省事。TileContext 的价值集中在:想用 Java 表达 tile 级算法,又希望由编译器去挑 Tensor Core 与 shared 布局,而不是手写 mma.sync 形状。

Java GPU kernel 与 hybrid library tasks 怎么分工

自己写的 Java kernel(三种 API 任一)适合应用特有逻辑:布局转换、融合激活、量化反量化、库里没有或要对中间张量动手的那段。vendor 库已经调得很满的稠密算子(GEMM、FFT、部分深度学习原语、RAPIDS 侧关系算子等),用 libraryTask 直接绑原生入口,和 JIT kernel 共用 TornadoVM 管的设备缓冲,中间结果可以不回主机、也不必额外做主机侧同步。

官网 hybrid 形态如下(符号与 README 一致):

TaskGraph tg = new TaskGraph("hybrid")
    .transferToDevice(DataTransferMode.EVERY_EXECUTION, matrix, vector)
    .task("preprocess", MyKernels::preprocess, matrix)   // JIT 编译的 Java kernel
    .libraryTask("gemv", CuBlas::cublasSgemv,
            CUBLAS_OP_T, m, n, alpha, matrix, lda, vector, incx, beta, output, incy)
    .task("postprocess", MyKernels::activate, output)
    .transferToHost(DataTransferMode.EVERY_EXECUTION, output);

try (TornadoExecutionPlan plan = new TornadoExecutionPlan(tg.snapshot())) {
    plan.withCUDAGraph().execute();
}

README 当前列出的库侧入口包括 cuBLAS / cuBLASLt、cuFFT、cuDNN、cuDF;KernelContext 另可直接发 FP16 / INT8 的 mma.sync。实务上可以这样选:定制与融合前处理写 Java kernel;能对上 cuBLAS / cuDNN 等的,优先 libraryTask;希望在 tile 层表达 matmul、softmax、attention,并让编译器选 Tensor Core 指令时,用 TileContext(仍可与 libraryTask 同图)。官网首页有 SGEMM / SGEMV 在特定 GPU 与 CUDA 版本上的对比数字,那是官方演示环境的结果,本稿不转述为普适结论;换卡、换精度、换图结构后差异会很大,以本机 tornado 示例与 profiler 为准。

和「纯绑定」路线的差别也值得分清:TornadoVM 的 JIT kernel 是从 Java 字节码生成设备代码;library task 才是对已有 NVIDIA 库的绑定。两者可以同图,但责任不同:前者你要保证可并行语义与 TornadoVM 支持的语言子集,后者你要保证本机装了对应 CUDA 库且参数约定正确。

最小上手

先确认 JAVA_HOME 指向目标 JDK,再装与族、后端匹配的 SDK。SDKMAN! 示例:

sdk install tornadovm 7.0.1-jdk21-cuda
# OpenCL 默认包:sdk install tornadovm
# Apple Silicon Metal:sdk install tornadovm 7.0.1-jdk21-metal
tornado --devices
tornado --version

也可从 v7.0.1 Release 下载 zip/tar(例如 tornadovm-7.0.1-jdk21-opencl-linux-amd64.zip),解压后设 TORNADOVM_HOME 并把 $TORNADOVM_HOME/bin 加入 PATH。官网还提供 sdk install tornadovm 与 downloads 页。

Maven 侧至少需要 API 与 runtime(版本后缀跟 SDK 族走):

<dependency>
  <groupId>io.github.beehive-lab</groupId>
  <artifactId>tornado-api</artifactId>
  <version>7.0.1-jdk21</version>
</dependency>
<dependency>
  <groupId>io.github.beehive-lab</groupId>
  <artifactId>tornado-runtime</artifactId>
  <version>7.0.1-jdk21</version>
</dependency>

仅加 API jar 不够跑设备;实际执行依赖本机驱动与对应后端的 SDK / driver 模块。编译期要用 CUDA library task 或 CUDA backend(含 cuTile)时,再引入 tornado-cublas 等与 tornado-drivers-cuda(版本同上)。跑通后可用官方示例确认:

java @$TORNADOVM_HOME/tornado-argfile \
  -cp $TORNADOVM_HOME/share/java/tornado/tornado-examples-7.0.1.jar \
  uk.ac.manchester.tornado.examples.compute.MatrixVectorRowMajor

TileContext 极简形态(摘自 programming / tile-api,略去完整 main):

public static void gemm(TileContext tc, HalfFloatArray a, HalfFloatArray b, FloatArray c,
                        int m, int n, int k) {
    PartitionView av = tc.partition(tc.view(a, m, k), 64, 32);
    PartitionView bv = tc.partition(tc.view(b, k, n), 32, 64);
    PartitionView cv = tc.partition(tc.view(c, m, n), 64, 64);

    Tile acc = tc.zeros(DType.F32, 64, 64);
    for (int step = 0; step < k / 32; step++) {
        acc = tc.mma(av.load(tc.bidX(), step), bv.load(step, tc.bidY()), acc);
    }
    cv.store(acc, tc.bidX(), tc.bidY());
}

WorkerGrid2D worker = new WorkerGrid2D(m / 64, n / 64); // tile blocks
GridScheduler grid = new GridScheduler("s0.gemm", worker);

tornado-examples 下 uk.ac.manchester.tornado.examples.tile 有 TileMatrixMultiply、TileSoftmax、TileAttention 等可跑样例。不确定生成结果时,用 tornado --printKernel 看输出的 CUDA Tile C++(应看到 ct:: 调用,而不是手写内联 PTX)。

适用边界

OpenCL backend 覆盖 NVIDIA / AMD / Intel 等与多核 CPU;Metal 面向 Apple Silicon;TileContext 与 NVIDIA library tasks 只在 CUDA backend。Tile 额外要求 Toolkit 13.3+、R580+、CC 8.0+。数据请用 FloatArray、HalfFloatArray 等 off-heap 类型(基于 Panama MemorySegment),并在图上显式声明 transferToDevice / transferToHost。

官方 known limitations 里几条对混图有影响:tile 任务暂不支持 withBatch;@Reduce 不宜与 tile 同图(reduction 改写会改图名,导致 GridScheduler 对不上,tile 可能静默按单 block 跑);部分 CUDA Tile C++ 表面(masked atomics、atomic_compare_exchange、permute 等)尚未暴露。调试时保持 recover.bailout 关闭,并用 --printKernel 确认设备侧确实生成了 kernel。

业务代码通常只链接 Apache 2.0 的 API 模块;打包或分发 Runtime / Drivers 时按仓库各模块的 GPLv2+CE 自行核对。TornadoVM 不替代 JVM:未放入 TaskGraph 的代码仍按普通 Java 执行;放入图中的方法则受加速器与后端能力约束(例如 Metal 上没有 TileContext,也没有 cuBLAS library task)。

若目标是多厂商可移植,优先 @Parallel / KernelContext + OpenCL(或按平台选 Metal);若目标是 NVIDIA 上把 Java 业务与 CUDA 生态拼在一张图里,再考虑 cuda SDK、libraryTask 与 TileContext。更细的操作表见 Core Programming 与仓库 docs/source/tile-api.rst。版本号、资产名与 Maven 坐标以 v7.0.0、v7.0.1 与 Maven Central 为准。

— 感谢阅读 —

一起交流

分享你的思考,让讨论更进一步。