
Minimal, safe high-level wrappers over the CUDA toolkit offering dynamic/static linking, runtime kernel compilation, device memory management, kernel launch builder and layered safe/result/sys APIs.
This is a Kotlin Multiplatform line-by-line transliteration port of cudarc.
Original Project: This port is based on cudarc. All design credit and project intent belong to the upstream authors; this repository is a faithful port to Kotlin Multiplatform with no behavioural changes intended.
This is an in-progress port. The goal is feature parity with the upstream Rust crate while providing a native Kotlin Multiplatform API. Every Kotlin file carries a // port-lint: source <path> header naming its upstream Rust counterpart so the AST-distance tool can track provenance.
The text below is reproduced from
https://github.com/coreylowman/cudarc. It is the upstream project's own description and remains under the upstream authors' authorship; links have been rewritten to absolute upstream URLs where appropriate so they continue to resolve from this repository.
Checkout cudarc on crates.io and docs.rs.
Contributions welcome!
Safe CUDA wrappers for:
| library | dynamic load | dynamic link | static link |
|---|---|---|---|
| CUDA driver | ✅ | ✅ | N/A |
| NVRTC | ✅ | ✅ | ✅ |
| cuRAND | ✅ | ✅ | ✅ |
| cuBLAS | ✅ | ✅ | ✅ |
| cuBLASLt | ✅ | ✅ | ✅ |
| NCCL | ✅ | ✅ | ✅ |
| cuDNN | ✅ | ✅ | ✅ |
| cuSPARSE | ✅ | ✅ | ✅ |
| cuSOLVER | ✅ | ✅ | N/A |
| cuFILE | ✅ | ✅ | ✅ |
| CUPTI | ✅ | ✅ | ✅ |
| nvtx | ✅ | ✅ | N/A |
| cuFFT | ✅ | ❌ | ❌ |
CUDA Versions supported
CUDNN versions supported:
NCCL versions supported:
Select cuda version with one of:
-F cuda-version-from-build-system: At build time will get the cuda toolkit version using nvcc
-F fallback-latest: can be used to control behavior if this fails. default is not enabled, which will cause the build
script to panic. if -F fallback-latest is enabled, we will use the highest bindings we have.-F cuda-<major>0<minor>0 to build for a specific version of cudaBy default we use -F dynamic-loading, which will not require any libraries to be present at build time.
You can also enable -F dynamic-linking or -F static-linking for your use case.
It's easy to create a new device and transfer data to the gpu:
// Get a stream for GPU 0
let ctx = cudarc::driver::CudaContext::new(0)?;
let stream = ctx.default_stream();
// copy a rust slice to the device
let inp = stream.clone_htod(&[1.0f32; 100])?;
// or allocate directly
let mut out = stream.alloc_zeros::<f32>(100)?;You can also use the nvrtc api to compile kernels at runtime:
let ptx = cudarc::nvrtc::compile_ptx("
extern \"C\" __global__ void sin_kernel(float *out, const float *inp, const size_t numel) {
unsigned int i = blockIdx.x * blockDim.x + threadIdx.x;
if (i < numel) {
out[i] = sin(inp[i]);
}
}")?;
// Dynamically load it into the device
let module = ctx.load_module(ptx)?;
let sin_kernel = module.load_function("sin_kernel")?;cudarc provides a very simple interface to launch kernels using a builder pattern to specify kernel arguments:
let mut builder = stream.launch_builder(&sin_kernel);
builder.arg(&mut out);
builder.arg(&inp);
builder.arg(&100usize);
unsafe { builder.launch(LaunchConfig::for_num_elems(100)) }?;And of course it's easy to copy things back to host after you're done:
let out_host: Vec<f32> = stream.clone_dtoh(&out)?;
assert_eq!(out_host, [1.0; 100].map(f32::sin));Goals are:
safe apis, with low level sys apisTo that end there are three levels to each wrapper (by default the safe api is exported):
use cudarc::driver::{safe, result, sys};
use cudarc::nvrtc::{safe, result, sys};
use cudarc::cublas::{safe, result, sys};
use cudarc::cublaslt::{safe, result, sys};
use cudarc::curand::{safe, result, sys};
use cudarc::nccl::{safe, result, sys};where:
sys is the raw ffi apis generated with bindgenresult is a very small wrapper around sys to return Result from each functionsafe is a wrapper around result/sys to provide safe abstractionsHeavily recommend sticking with safe APIs
Dual-licensed to be compatible with the Rust project.
Licensed under the Apache License, Version 2.0 http://www.apache.org/licenses/LICENSE-2.0 or the MIT license http://opensource.org/licenses/MIT, at your option. This file may not be copied, modified, or distributed except according to those terms.
dependencies {
implementation("io.github.kotlinmania:cudarc-kotlin:0.1.0")
}./gradlew build
./gradlew testSee AGENTS.md and CLAUDE.md for translator discipline, port-lint header convention, and Rust → Kotlin idiom mapping.
This Kotlin port is distributed under the same license terms as the upstream cudarc. See LICENSE (and any sibling LICENSE-* / NOTICE files mirrored from upstream) for the full text.
Original work copyrighted by the cudarc authors.
Kotlin port: Copyright (c) 2026 Sydney Renee and The Solace Project.
Thanks to the cudarc maintainers and contributors for the original Rust implementation. This port reproduces their work in Kotlin Multiplatform; bug reports about upstream design or behavior should go to the upstream repository.
This is a Kotlin Multiplatform line-by-line transliteration port of cudarc.
Original Project: This port is based on cudarc. All design credit and project intent belong to the upstream authors; this repository is a faithful port to Kotlin Multiplatform with no behavioural changes intended.
This is an in-progress port. The goal is feature parity with the upstream Rust crate while providing a native Kotlin Multiplatform API. Every Kotlin file carries a // port-lint: source <path> header naming its upstream Rust counterpart so the AST-distance tool can track provenance.
The text below is reproduced from
https://github.com/coreylowman/cudarc. It is the upstream project's own description and remains under the upstream authors' authorship; links have been rewritten to absolute upstream URLs where appropriate so they continue to resolve from this repository.
Checkout cudarc on crates.io and docs.rs.
Contributions welcome!
Safe CUDA wrappers for:
| library | dynamic load | dynamic link | static link |
|---|---|---|---|
| CUDA driver | ✅ | ✅ | N/A |
| NVRTC | ✅ | ✅ | ✅ |
| cuRAND | ✅ | ✅ | ✅ |
| cuBLAS | ✅ | ✅ | ✅ |
| cuBLASLt | ✅ | ✅ | ✅ |
| NCCL | ✅ | ✅ | ✅ |
| cuDNN | ✅ | ✅ | ✅ |
| cuSPARSE | ✅ | ✅ | ✅ |
| cuSOLVER | ✅ | ✅ | N/A |
| cuFILE | ✅ | ✅ | ✅ |
| CUPTI | ✅ | ✅ | ✅ |
| nvtx | ✅ | ✅ | N/A |
| cuFFT | ✅ | ❌ | ❌ |
CUDA Versions supported
CUDNN versions supported:
NCCL versions supported:
Select cuda version with one of:
-F cuda-version-from-build-system: At build time will get the cuda toolkit version using nvcc
-F fallback-latest: can be used to control behavior if this fails. default is not enabled, which will cause the build
script to panic. if -F fallback-latest is enabled, we will use the highest bindings we have.-F cuda-<major>0<minor>0 to build for a specific version of cudaBy default we use -F dynamic-loading, which will not require any libraries to be present at build time.
You can also enable -F dynamic-linking or -F static-linking for your use case.
It's easy to create a new device and transfer data to the gpu:
// Get a stream for GPU 0
let ctx = cudarc::driver::CudaContext::new(0)?;
let stream = ctx.default_stream();
// copy a rust slice to the device
let inp = stream.clone_htod(&[1.0f32; 100])?;
// or allocate directly
let mut out = stream.alloc_zeros::<f32>(100)?;You can also use the nvrtc api to compile kernels at runtime:
let ptx = cudarc::nvrtc::compile_ptx("
extern \"C\" __global__ void sin_kernel(float *out, const float *inp, const size_t numel) {
unsigned int i = blockIdx.x * blockDim.x + threadIdx.x;
if (i < numel) {
out[i] = sin(inp[i]);
}
}")?;
// Dynamically load it into the device
let module = ctx.load_module(ptx)?;
let sin_kernel = module.load_function("sin_kernel")?;cudarc provides a very simple interface to launch kernels using a builder pattern to specify kernel arguments:
let mut builder = stream.launch_builder(&sin_kernel);
builder.arg(&mut out);
builder.arg(&inp);
builder.arg(&100usize);
unsafe { builder.launch(LaunchConfig::for_num_elems(100)) }?;And of course it's easy to copy things back to host after you're done:
let out_host: Vec<f32> = stream.clone_dtoh(&out)?;
assert_eq!(out_host, [1.0; 100].map(f32::sin));Goals are:
safe apis, with low level sys apisTo that end there are three levels to each wrapper (by default the safe api is exported):
use cudarc::driver::{safe, result, sys};
use cudarc::nvrtc::{safe, result, sys};
use cudarc::cublas::{safe, result, sys};
use cudarc::cublaslt::{safe, result, sys};
use cudarc::curand::{safe, result, sys};
use cudarc::nccl::{safe, result, sys};where:
sys is the raw ffi apis generated with bindgenresult is a very small wrapper around sys to return Result from each functionsafe is a wrapper around result/sys to provide safe abstractionsHeavily recommend sticking with safe APIs
Dual-licensed to be compatible with the Rust project.
Licensed under the Apache License, Version 2.0 http://www.apache.org/licenses/LICENSE-2.0 or the MIT license http://opensource.org/licenses/MIT, at your option. This file may not be copied, modified, or distributed except according to those terms.
dependencies {
implementation("io.github.kotlinmania:cudarc-kotlin:0.1.0")
}./gradlew build
./gradlew testSee AGENTS.md and CLAUDE.md for translator discipline, port-lint header convention, and Rust → Kotlin idiom mapping.
This Kotlin port is distributed under the same license terms as the upstream cudarc. See LICENSE (and any sibling LICENSE-* / NOTICE files mirrored from upstream) for the full text.
Original work copyrighted by the cudarc authors.
Kotlin port: Copyright (c) 2026 Sydney Renee and The Solace Project.
Thanks to the cudarc maintainers and contributors for the original Rust implementation. This port reproduces their work in Kotlin Multiplatform; bug reports about upstream design or behavior should go to the upstream repository.