cudaverse

Lightweight CUDA computing for R. cudaverse lets R users run dense and sparse matrix operations, PCA, distances, exact k-nearest neighbours, and clustering on an NVIDIA GPU through one familiar package.

Use cudaverse when your analysis has outgrown ordinary R execution and you want GPU acceleration without adopting a large deep-learning framework. The native backend is included in the package, discovers CUDA libraries already installed on your system, and keeps supported multi-stage workflows on the GPU until you ask for an R result.

Why use cudaverse?

Requirements

GPU execution requires a CUDA-capable NVIDIA GPU and compatible NVIDIA runtime libraries. The easiest supported setup is:

Use NVIDIA’s current Windows installation guide or Linux installation guide. After installing the driver, confirm that nvidia-smi can see the GPU before starting R.

Install

Install the current release from GitHub:

# install.packages("pak")
pak::pak("cudaverse/cudaverse@v0.4.1")

Then verify the complete runtime—not only GPU detection:

library(cudaverse)

diagnostics <- cuda_diagnostics()
diagnostics$summary
diagnostics$next_steps

# Strict: returns a CUDA selection or explains why CUDA is not ready.
cuda_select_device("cuda")

The native backend needs the NVIDIA driver, cuBLAS 12, and cuSOLVER 11. If Windows or Linux cannot find the libraries automatically, set CUDAVERSE_CUBLAS_PATH and CUDAVERSE_CUSOLVER_PATH to their absolute paths before loading cudaverse. See the CUDA setup guide for platform-specific examples and troubleshooting.

A five-minute CUDA workflow

The following workflow uploads a matrix once, computes PCA and exact kNN with CUDA, and transfers only the final neighbour result back to R:

library(cudaverse)

set.seed(1)
x <- matrix(rnorm(10000 * 100), nrow = 10000, ncol = 100)

pca <- cuda_pca(
  x,
  n_components = 20,
  device = "cuda"
)

neighbors <- cuda_knn(
  pca$x,
  k = 15,
  device = "cuda"
)

head(neighbors$index)
head(neighbors$distance)
cuda_provenance(neighbors)

Use tensors when you want direct control over GPU-resident matrix operations:

x_gpu <- cuda_tensor(x, device = "cuda", dtype = "float32")
crossprod_gpu <- tensor_matmul(t(x_gpu), x_gpu)

tensor_device(crossprod_gpu)
crossprod <- to_cpu(crossprod_gpu)  # transfer only when the R matrix is needed

Sparse matrices use the same CUDA-facing API:

counts <- Matrix::rsparsematrix(10000, 100, density = 0.03)
counts@x <- abs(counts@x)

counts_gpu <- cuda_sparse(counts, device = "cuda")
normalized_gpu <- sparse_normalize(
  counts_gpu,
  margin = "rows",
  scale_factor = 10000,
  log1p = TRUE
)
sparse_pca <- cuda_pca(normalized_gpu, n_components = 20, device = "cuda")
sparse_knn <- cuda_knn(sparse_pca$x, k = 15, device = "cuda")

How fast is it?

The retained full benchmark uses five warmups and ten timed runs and validates numerical parity before accepting a timing. Selected host-boundary medians are shown below; times include the public R call boundary.

Workload Base R Native CUDA R torch Native vs base Native vs torch
1024 x 1024 float32 matrix multiplication 0.332 s 0.024 s 0.039 s 13.7x 1.6x
Dense PCA + exact kNN, 10,000 x 100 11.915 s 0.275 s 6.094 s 43.4x 22.2x
Sparse PCA + exact kNN, 10,000 x 100 10.265 s 0.203 s 5.198 s 50.6x 25.6x
Dense PCA + exact kNN, 50,000 x 128 668.418 s 2.807 s 126.552 s 238.1x 45.1x

These are workload-specific measurements from one fixed NVIDIA GPU environment, not guarantees for every machine. Small jobs can be dominated by launch and transfer overhead: in the retained sparse 1,000 x 50 case, base R was faster than native CUDA. See the complete benchmark evidence and the performance articles before choosing a workload size.

The versioned benchmark contract defines the workload sizes, warmups, timed runs, transfer boundaries, validation tolerances, and evidence fields used by the retained report.

Learn by task

Graph and embedding helpers are also available. Some currently delegate stages to established CPU packages; cuda_provenance() makes those boundaries visible. The task guides identify which operations are fully native CUDA and which are hybrid.