Provides single-cell analysis primitives for sparse count matrices, including library-size normalization, log-normalization, highly variable feature selection, principal component analysis, and nearest-neighbour construction. Integrates the 'cudaverse' numerical and sparse layers while preserving matrix identifiers and recording the computation backend for each stage. Optional adapters preserve native 'SingleCellExperiment' and 'SeuratObject' version 5 object structures.
cudacellr takes a single-cell count matrix through normalization, variable
feature selection, PCA, and exact nearest neighbours. Use it to accelerate
PCA and neighbour search with NVIDIA CUDA while keeping familiar R matrices,
cell identifiers, and optional SingleCellExperiment or SeuratObject results.
The native CUDA backend comes from cudaverse and does not require torch or LibTorch. Sparse normalization and feature selection run on the CPU; PCA, distance calculations, and deterministic top-k selection can run on CUDA.
cudaverse;cudaverse;For CUDA execution, prepare a Windows or Linux machine with an NVIDIA driver, cuBLAS 12, and cuSOLVER 11. Follow the CUDA setup guide before running the GPU examples. Current CUDA execution is unavailable on macOS; use a Windows or Linux GPU machine for these workflows.
# install.packages("pak")
pak::pak("cudaverse/cudacellr")
library(cudacellr)
health <- cudaverse::cuda_diagnostics()
health$summary
health$next_steps
health$selected_backend # "native" for the lightweight CUDA path
cudaverse::cuda_select_device("cuda")
An explicit device = "cuda" request fails with diagnostics when CUDA is
unavailable; it does not silently run the requested GPU stages on the CPU.
Provide features in rows and cells in columns:
library(cudacellr)
library(Matrix)
set.seed(1)
counts <- Matrix(
matrix(
rpois(1000 * 300, lambda = 1.5), 1000, 300,
dimnames = list(
paste0("gene", seq_len(1000)),
paste0("cell", seq_len(300))
)
),
sparse = TRUE
)
fit <- cudacell_workflow(
counts,
n_hvg = 300,
n_components = 20,
k = 15,
batch_size = 128,
device = "cuda"
)
fit$pca
fit$neighbors
Feature and cell identifiers are preserved throughout the workflow:
identical(rownames(fit$normalized), rownames(counts))
identical(colnames(fit$normalized), colnames(counts))
identical(rownames(fit$pca$x), colnames(counts))
identical(rownames(fit$neighbors$index), colnames(counts))
HVG results also include the original feature index, so repeated feature
names do not cause PCA to select the wrong matrix row.
Continue from this result through graph clustering and embedding in the cudaverse end-to-end workflow.
Neighbour search is exact but uses bounded distance blocks. At most
min(batch_size, cells) * cells distances are held at once instead of a full
cell-by-cell matrix. Reduce batch_size when memory is constrained; the
selected neighbours are deterministic and do not change with batch size.
With the native backend, the compute boundaries are:
| Function | Native CUDA work | CPU work and R outputs |
|---|---|---|
cuda_normalize_counts() |
none | sparse normalization |
cuda_hvg() |
none | sparse feature statistics and ranking |
cuda_cell_pca() |
PCA centring/scaling and decomposition | normalization, HVG selection, selected dense input, and the public PCA model |
cuda_cell_neighbors() |
distance blocks and deterministic top-k selection | input validation and final neighbour matrices |
cudacell_workflow() |
PCA and exact kNN | sparse preprocessing and public R results |
The complete workflow is hybrid because normalization and HVG selection are
CPU stages. Native PCA returns ordinary R scores and loadings and also retains
a device-side score cache; passing the PCA result directly to
cuda_cell_neighbors() lets kNN reuse that cache without uploading the scores
again. CUDA neighbour selection is not a fixed CPU stage.
The optional torch compatibility backend can have different stage boundaries. Check provenance for the backend actually selected rather than inferring it from the requested device.
Inspect the runtime and any result without guessing from its function name:
cudaverse::cuda_diagnostics()
cuda_provenance(fit)
The provenance table separates the requested device, actual compute device, output device, and an automatic fallback. See Backend provenance and CUDA diagnostics for a worked CUDA example, a small CPU reference, and dense-PCA/kNN memory guidance.
The numerical core accepts base, Matrix, and cudasparse matrices.
cudacell_sce() adds an optional native SingleCellExperiment workflow
without making Bioconductor packages hard dependencies:
library(SingleCellExperiment)
sce <- SingleCellExperiment(assays = list(counts = counts))
sce <- cudacell_sce(
sce,
n_hvg = 300,
n_components = 20,
k = 15,
batch_size = 128,
device = "cuda"
)
assayNames(sce)
reducedDimNames(sce)
colPairNames(sce)
cuda_provenance(sce)
The adapter writes natural-log normalized expression to
cudacell_logcounts, PCA scores to CUDACELL_PCA, HVG statistics to
namespaced rowData columns, and directed kNN relationships to
CUDACELL_KNN. Existing assays, metadata, reduced dimensions, alternative
experiments, labels, pairings, and size factors remain unchanged.
Output names are deliberately namespaced and never silently replaced.
overwrite = TRUE replaces only the explicitly named cudacellr fields.
Delayed assays also remain lazy unless realize = TRUE is requested after
checking that the assay fits in memory. See the
SingleCellExperiment workflow
for the complete object contract.
Seurat v5 objects have the same non-destructive workflow through
cudacell_seurat(). Only the lightweight SeuratObject package is needed;
the full Seurat package is not required:
object <- SeuratObject::CreateSeuratObject(counts = counts)
object <- cudacell_seurat(
object,
assay = "RNA",
layer = "counts",
n_hvg = 300,
n_components = 20,
k = 15,
batch_size = 128,
device = "cuda"
)
SeuratObject::Assays(object)
SeuratObject::Reductions(object)
SeuratObject::Neighbors(object)
cuda_provenance(object)
Normalized expression and feature statistics are written to a native
Assay5, PCA scores and loadings to a DimReduc, exact neighbour indices
and distances to a Neighbor, size factors to cell metadata, and parameters
and compute provenance to the cudacell_seurat tool record. Existing assays,
layers, reductions, graphs, neighbours, identities, metadata, and tools are
preserved.
All output names and Seurat keys are checked before device selection,
realization, or computation. overwrite = TRUE targets only the named
cudacellr outputs, and non-memory-backed layers require the explicit
realize = TRUE opt-in. See the
SeuratObject v5 workflow
for the full contract.
For installation, device verification, memory advice, and common failures, see the cudaverse GPU setup and troubleshooting guide.
MIT © Yaoxiang Li