Supported CUDA Features: a guide to the CUDA-C backend, KernelContext and the hybrid library API #1026
Pinned
mikepapadim
announced in
announcements
Replies: 0 comments
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Uh oh!
There was an error while loading. Please reload this page.
Uh oh!
There was an error while loading. Please reload this page.
This is a map of everything the CUDA-C backend exposes today, written against
develop@ba28f1526. It covers the three ways you can reach NVIDIA hardware from Java in TornadoVM — the JIT compiler,KernelContext, and the hybrid library API — plus the CUDA-specific execution-plan switches and how to profile any of it.Every snippet below is taken from code in the repository, not written for the occasion; each one links to its source so you can run it.
Everything under "Available today" is on
developwith unit tests behind it. Items still in review are listed separately at the end, so nothing here should surprise you when you try it.1. Getting started
make BACKEND=cuda tornado --devices # confirm the CUDA driver enumerates your GPUThree levels of control, from least to most explicit:
@Parallel/@Reduceon plain Java loopsKernelContextlibraryTask(...)calling cuBLAS, cuDNN, cuFFT, cuSPARSE, CUTLASSAll three compose inside one
TaskGraph, sharing the same device buffers — no round trip to the host between them.The shape every example below plugs into:
2.
KernelContext— the CUDA programming model in Java2.1 Thread indexing and synchronisation
globalIdx/globalIdy/globalIdz,localIdx/localIdy/localIdz,groupIdx/groupIdy/groupIdz, the grid dimensionsglobalGroupSizeX/Y/ZandlocalGroupSizeX/Y/Z, pluslocalBarrier()(__syncthreads()) andglobalBarrier().2.2 Shared (local) memory
Available for
int,byte,long,float,double,HalfFloatandHalf2.2.3 Atomics
A histogram is the whole story in two lines —
TestHistogram.java:atomicAdd(IntArray / LongArray / FloatArray / DoubleArray / int[], index, value)atomicAdd(double needs compute ≥ 6.0)atomicCAS(int[], index, expected, value)atomicCASatomicExchange/atomicMin/atomicMaxonint[]atomicExch/atomicMin/atomicMax2.4 Warp-level primitives
simdSum(float),simdShuffleDown(float, delta)andsimdBroadcastFirst(float)give you warp shuffles without shared memory. A block-wide suffix scan, warp-level fold plus one shared-memory carry pass —TestWarpShuffleScan.java:Note
simdShuffleDownonly pulls from a higher lane (shfl.sync.down) and has nointoverload — which is why that kernel computes a suffix scan onfloatrather than a conventional prefix scan.2.5 Tensor cores (
mma.sync)MMA fragments are first-class, in shapes
M16N8K16andM16N8K32:mmaFragment,mmaLoadA,mmaLoadB,mmaLoadBSwizzled,mma,mmaStoremmaBF16mmaFragmentInt,mmaLoadAInt8,mmaLoadBInt8,mmaInt8,mmaStoreIntmmaLoadAFP8,mmaLoadBFP8,mmaFP8E4M3,mmaFP8E5M2One warp computing a 16×16 output tile, two
M16N8K16accumulators side by side — condensed fromTestMatrixMultiplicationMMA.java:Supporting cast: bank-conflict-free shared access via
swizzleLoadFp16Stride16/32,swizzleStoreFp16Stride16/32,swizzleLoadInt8,swizzleStoreInt8; andMatrix8x8FloathelperssimdgroupMatrixZero/Load/MultiplyAccumulate/Storefor a portable 8×8 tile API.More end-to-end examples:
MatrixMultiplicationMMA.java,LowPrecisionGemmBenchmark.java,FP8GemmStage.java.2.6 Asynchronous global → shared copies (
cp.async)The simple form — stage a tile, commit, wait, publish:
And the reason
cp.asyncexists — a double-buffered pipeline that stages chunk k+1 while consuming chunk k, fromTestAsyncCopyToLocal.java:Source overloads:
ByteArray,HalfFloatArray,FP8Array.2.7 Low-precision conversion, dot products, printf
float16ToFloat,bf16FromFloat/bf16ToFloat,e4m3ToFloat/e5m2ToFloat,dp4a/dp4a_packed(4-way INT8 dot-product-accumulate), andprintf(...)lowered to device-sideprintf.3. Data types
Off-heap,
MemorySegment-backed native arrays — no copies, no boxing:ByteArray,CharArray,ShortArray,IntArray,LongArray,FloatArray,DoubleArray,HalfFloatArray(FP16),BFloat16Array(BF16),FP8Array(E4M3 / E5M2),Int8Array.Plus vector types (
Float2/3/4/8/16,Int*,Double*,Byte3/4,Half2) and matrix types (Matrix2DFloat,Matrix3DFloat,Matrix4x4Float,Matrix8x8Float, and int/double/short variants).4. Hybrid library tasks — NVIDIA libraries inside a TaskGraph
A
libraryTaskruns a native vendor kernel on the buffers already resident on the device, in the middle of a normal task graph — fromTestCuBlas.java:Available providers on
develop:cublasSgemv,cublasSgemm,cublasSgemmTF32,cublasSgemmStridedBatched,cublasGemmExFP16,cublasGemmExFP16FP32,cublasGemmExBF16; cuBLASLt:ltMatmulFP32,ltMatmulFP16,ltMatmulFP8,ltMatmulBiasFP16,ltMatmulGeluBiasFP16cudnnSoftmax,cudnnRelu,cudnnSigmoid,cudnnTanh,cudnnMaxPool2d,cudnnConv2d,sdpaForward(fused scaled-dot-product attention)cufftForwardC2C/cufftInverseC2C,cufftForwardR2C/cufftInverseC2R,cufftForwardZ2Z/cufftInverseZ2Z(double),cufftForward2dC2C/cufftInverse2dC2CcusparseSpMV,cusparseSpMM(CSR)cutlassSgemm,cutlassHgemm,cutlassBgemm,cutlassHgemmBatched, and fused epiloguescutlassGemmBiasRelu/Gelu/Silu/Sigmoid/Tanh/HardSwishLibrary tasks are automatically wrapped in an NVTX range named
<library>/<function>, so they show up as labelled spans on an Nsight timeline alongside the JIT kernels.Tests:
unittests.cublas.TestCuBlas,TestCuBlasLt,unittests.cudnn.TestCuDnn,unittests.cufft.TestCuFft,unittests.cusparse.TestCusparse,unittests.cutlass.TestCutlass.5. CUDA-specific execution-plan options
withCUDAGraph()withIntraPlanConcurrency()withStagedTransfers()tornado.staged.*tunes chunk size, ring depth, threshold, fill threads)withConcurrentDevices()withBatch("512MB")withMemoryLimit("2GB")withPreCompilation(),withWarmUpIterations(n),withWarmUpTime(ms)withProfiler(ProfilerMode)withPrintKernel(),withThreadInfo()Useful properties:
-Dtornado.cuda.priority,-Dtornado.max.events,-Dtornado.reuse.device.buffers,-Dtornado.eventpool.size.Compiled kernels are cached as cubins on disk (#1008), so repeat runs of the same application skip NVRTC entirely.
6. Profiling
6.1 See what was generated
6.2 TornadoVM's own profiler
Reports per task:
TASK_COMPILE_GRAAL_TIME,TASK_COMPILE_DRIVER_TIME(NVRTC),TASK_CODE_GENERATION_TIME,TASK_KERNEL_TIME(device events),COPY_IN_TIME/COPY_OUT_TIME,TOTAL_DISPATCH_KERNEL_TIME, allocation and transfer byte counts, plus power via NVML.Programmatically:
plan.withProfiler(ProfilerMode.SILENT)thenexecutionResult.getProfilerResult().Caveat worth knowing. The profiler reads each event's timestamp inline, which serialises host and device. On short kernels that both slows the run down several times over and inflates its own transfer numbers — measured at 3.3× on a 512-element
saxpy, reportingcopyInAvg = 12.9 µsfor a copy Nsight measures at 0.65 µs. #1024 addresses this. For microsecond-scale work, trust Nsight over the built-in numbers.6.3 Nsight Systems — the timeline
nsys profile -t cuda,nvtx --sample=none --cpuctxsw=none -o report \ tornado -m tornado.benchmarks/uk.ac.manchester.tornado.benchmarks.BenchmarkRunner \ --params="sgemm 100 1024" nsys stats --report cuda_api_sum,cuda_gpu_kern_sum,cuda_gpu_mem_time_sum,nvtx_sum report.nsys-repThe reports that answer the usual questions:
cuda_api_sumcuda_gpu_kern_sumcuda_gpu_mem_time_sumnvtx_sumTornadoVM labels its own NVTX ranges, so the timeline is readable without guesswork: transfers appear as
H2D 2.0 KB/D2H 24.0 MB, kernels under their generated name, and hybrid library calls as<library>/<function>(e.g.cublas/cublasSgemm).A worked example of reading these — GPU work was 3.31 µs of a 17.46 µs iteration, with the rest in host-side dispatch, which is what #1022–#1024 came from.
6.4 Nsight Compute — inside a kernel
ncu --set full --kernel-name regex:myKernel -o profile \ tornado -m ... --params="..."Kernel names in the report are the generated CUDA-C function names, so
--printKernelfirst if you are unsure what to match.-lineinfo(see #1010) makes Nsight attribute samples back to the generated source.6.5 Profiling the Java side
Standard JFR works, and is the right tool when you suspect the runtime rather than the kernel:
stackdepth=192matters — the default of 64 truncates TornadoVM'sexecute()stack into unattributable roots. The ratio ofjdk.ExecutionSample(in Java) tojdk.NativeMethodSample(inside a JNI/CUDA call) tells you immediately whether you are runtime-bound or device-bound.7. Where to look in the tree
Every feature above has runnable code in the repository. Paths are relative to the repo root.
Runnable examples
tornado-examples/.../examples/compute/MatrixMultiplicationMMA.javatornado-examples/.../examples/kernelcontext/matrices/LowPrecisionGemmBenchmark.javacp.asynctornado-examples/.../examples/kernelcontext/matrices/FP8GemmStage.javaKernelContextbasics, reductions, matricestornado-examples/.../examples/kernelcontext/@Parallel/@Reducestyle kernelstornado-examples/.../examples/compute/,.../examples/reductions/Tests, which double as the specification
tornado-unittests/.../kernelcontext/matrices/TestMatrixMultiplicationMMA.javaTestMatrixMultiplicationMMABF16.java,TestMatrixMultiplicationMMAInt8.java,TestMatrixMultiplicationMMAFP8.java(same directory)cp.asyncTestMatrixMultiplicationMMACpAsync.java(same directory)cp.asyncsemantics, including the double-buffered pipelinetornado-unittests/.../kernelcontext/api/TestAsyncCopyToLocal.javaatomicAddon global memorytornado-unittests/.../kernelcontext/reductions/TestHistogram.javaatomicCAS/atomicExchange/atomicMin/atomicMaxtornado-unittests/.../kernelcontext/api/TestAtomicRmw.java,TestGlobalAtomics.javatornado-unittests/.../kernelcontext/reductions/TestWarpShuffleScan.javaKernelContextdoes not support per backendtornado-unittests/.../kernelcontext/api/TestUnsupportedKernelContextOps.javatornado-unittests/.../{cublas,cudnn,cufft,cusparse,cutlass}/Run any of them with:
Backend internals, if you want to add an intrinsic
tornado-api/.../api/KernelContext.javatornado-drivers/cuda/.../graal/compiler/plugins/CUDAGraphBuilderPlugins.javatornado-drivers/cuda/.../graal/lir/CUDALIRStmt.javatornado-drivers/cuda-jni/src/main/cpp/source/CUDACommandQueue.cpptornado-drivers/cuda-jni/src/main/cpp/source/CUDAProgram.cppCorrections welcome
If something here is wrong, out of date, or you expected a CUDA feature that is not listed, reply on this thread and I will fold it in.
All reactions