Learn R Programming

ggmlR — Neural Networks for R

A native R package for building, training, and deploying neural networks. Backed by the ggml C library, designed primarily for Vulkan GPU acceleration with full CPU fallback — no Python, no TensorFlow, everything runs inside your R session.

GPU-first design: when a Vulkan-capable GPU is available (NVIDIA, AMD, Intel, ARM Mali, Qualcomm Adreno), all operations run on GPU automatically. On machines without a GPU the package falls back to CPU transparently — no code changes needed.

Two complementary APIs:

APIStyleWhen to use
Sequential / FunctionalKeras-like, static graphProduction models, CRAN-standard workflow
Dynamic autograd (ag_*)PyTorch-like, eagerResearch, custom architectures, Transformers

Also serves as the backend engine for llamaR (LLM inference) and sd2R (Stable Diffusion).

Installation

install.packages("ggmlR")

GPU (Vulkan) support is auto-detected at build time.

Ubuntu / Debian — to enable GPU:

sudo apt install libvulkan-dev glslc

Windows — install Rtools and optionally the Vulkan SDK for GPU support.

Build options

Force-enable or disable Vulkan GPU backend:

install.packages("ggmlR", configure.args = "--with-vulkan")
install.packages("ggmlR", configure.args = "--without-vulkan")

Enable CPU SIMD acceleration (AVX2, SSE4, etc.) for faster inference on your machine:

install.packages("ggmlR", configure.args = "--with-simd")

Enable the hard-exit path used by multi-GPU standalone scripts (ggml_vulkan_shutdown(hard = TRUE); see Clean shutdown below and vignette("multi-gpu")). Off by default — the released package must not call _exit(), as CRAN policy forbids a package terminating the R session:

install.packages("ggmlR", configure.args = "--enable-hard-exit")

Options can be combined:

install.packages("ggmlR", configure.args = "--with-vulkan --with-simd --enable-hard-exit")

Linux (detailed)

Full step-by-step setup on Ubuntu/Debian, from a clean system to a working GPU build.

1. R and the Vulkan loader/tools:

sudo apt install -y r-base

sudo apt install vulkan-tools libvulkan-dev

2. The glslc shader compiler (needed to build ggmlR's Vulkan backend):

# Ubuntu 24.04 (Noble)
sudo add-apt-repository universe
sudo apt update
sudo apt install glslc

# Ubuntu 22.04 (Jammy) — install the LunarG Vulkan SDK instead
wget -qO- https://packages.lunarg.com/lunarg-signing-key-pub.asc | \
  sudo tee /etc/apt/trusted.gpg.d/lunarg.asc

sudo wget -qO /etc/apt/sources.list.d/lunarg-vulkan-jammy.list \
  https://packages.lunarg.com/vulkan/lunarg-vulkan-jammy.list

sudo apt update
sudo apt install -y vulkan-sdk

3. Verify the GPU is visible to Vulkan:

vulkaninfo --summary

4. Install ggmlR with CPU SIMD acceleration:

sudo Rscript -e 'install.packages("ggmlR", configure.args = "--with-simd")'

5. Confirm GPU support from R:

Rscript -e 'library(ggmlR)
ggml_vulkan_status()'

Windows build options

Important: on Windows, R ignores configure.args / --configure-args (they are only honoured by the Unix ./configure path). Use environment variables instead, set in the same R session before installing:

Sys.setenv(GGML_USE_SIMD = "1")     # enable CPU SIMD (AVX2/SSE4/FMA/F16C)
Sys.setenv(GGML_USE_VULKAN = "1")   # force-enable Vulkan  (or "0" to disable)
Sys.setenv(GGML_VK_HARD_EXIT = "1") # enable ggml_vulkan_shutdown(hard = TRUE)

The flags are read by configure.win, which only runs when the package is built from source. The CRAN binary for Windows is pre-built without them, so pass type = "source" to force a source build:

# From CRAN (force a source build so the flags take effect):
install.packages("ggmlR", type = "source")

# From GitHub (always builds from source):
remotes::install_github("Zabis13/ggmlR", force = TRUE)

Vulkan is still auto-detected when the Vulkan SDK is present, so GGML_USE_VULKAN is only needed to force it on/off. Accepted values: 1 / yes / true / on (and 0 / no / false / off for Vulkan). OpenMP (multi-threaded CPU executor) is detected automatically on Rtools.

Diagnostics

GGMLR_LOG_DEVICE — when set to a non-empty value other than 0, enables Vulkan telemetry logging. Two messages are emitted:

  1. The selected device and its capabilities, once a backend context is created:

    ggml_vulkan: device #0 'Vulkan0' selected | fp16=1 bf16=1 coopmat=1 coopmat2=0 bda=1 max_buffer=4095 MB suballoc_block=1024 MB sysmem_fallback=0
  2. A per-graph summary of any ops the Vulkan backend could not run and fell back to CPU (e.g. OUT_PROD, CROSS_ENTROPY_LOSS_BACK during training):

    ggml_vulkan: 12 op(s) not supported on GPU during graph compute, ran on CPU (per-type: OUT_PROD=12)

Both are off by default so they do not clutter output (notably during tests, where many contexts and training graphs are created). Enable them to diagnose which GPU was picked, which acceleration paths (fp16 / bf16 / coopmat) are active, and which ops are silently running on CPU:

Sys.setenv(GGMLR_LOG_DEVICE = "1")

CPU performance: multithreaded BLAS/LAPACK

ggmlR runs the heavy linear algebra on the GPU, but some steps stay on the CPU through R's BLAS/LAPACK — most notably the eigendecomposition in PCA (RunGGML(op = "embed")) and any eigen() / prcomp() fallback. R ships with the reference BLAS/LAPACK, which is single-threaded: on a multi-core machine those CPU phases use just one core. Switching to OpenBLAS parallelises them (e.g. PCA on a 3000-gene object dropped from ~24 s to ~1.6 s here).

This is a system-level change (outside the package, needs sudo). On Debian/Ubuntu:

# 1. Install OpenBLAS. Prefer the OpenMP variant over the default pthreads one
#    (the R-admin manual recommends the openmp build): its threads are governed
#    by OMP_NUM_THREADS and it is better behaved under tools like valgrind.
sudo apt update
sudo apt install libopenblas-openmp-dev   # or libopenblas-dev for the pthreads build

# 2. Point BLAS at OpenBLAS (pick the openblas entry from the list):
sudo update-alternatives --config libblas.so.3-x86_64-linux-gnu

# 3. Point LAPACK at OpenBLAS too — eigen() goes through LAPACK, not BLAS:
sudo update-alternatives --config liblapack.so.3-x86_64-linux-gnu
# 4. Confirm R picked it up — both lines should name openblas, not
#    /usr/lib/.../blas/libblas.so or /usr/lib/.../lapack/liblapack.so:
si <- sessionInfo(); cat("BLAS:  ", si$BLAS, "\nLAPACK:", si$LAPACK, "\n")

OpenBLAS grabs all cores by default. If that oversubscribes alongside parallel resampling (tidymodels / mlr3) or trips CRAN's 2-thread limit in checks, cap it: Sys.setenv(OPENBLAS_NUM_THREADS = 2).

Note (valgrind). A multithreaded OpenBLAS spawns worker threads, and valgrind reports each worker's thread-local storage as a one-off "possibly lost" block (definitely lost: 0). This is a known false positive, not a leak. Run checks with OPENBLAS_NUM_THREADS=1 OMP_NUM_THREADS=1 for a clean valgrind report; CRAN's own machines use single-threaded reference BLAS, so it does not appear there.

GPU linear algebra (drop-in for %*%)

Accelerate an ordinary R matrix multiply on the GPU without rewriting your code — plain matrices in, plain matrices out, with a transparent CPU fallback.

library(ggmlR)

A <- matrix(rnorm(2000 * 1500), 2000, 1500)
B <- matrix(rnorm(1500 * 1000), 1500, 1000)

C <- ggml_matmul(A, B)        # A %*% B on the GPU, returns a plain matrix
G <- ggml_crossprod(A)        # t(A) %*% A
H <- ggml_tcrossprod(A)       # A %*% t(A)

Prefer the operators? Wrap one operand and %*% / crossprod() / tcrossprod() dispatch to the GPU — nothing else in your code changes:

Ag <- as_gpu_matrix(A)
C  <- Ag %*% B                # GPU
G  <- crossprod(Ag)           # GPU
  • Dispatchdevice = "auto" (default) uses the GPU when one is present and the multiply is large enough to amortise the host↔VRAM transfer; small multiplies and machines without a GPU stay on the CPU. Force it with device = "gpu" / "cpu".
  • Precision — R multiplies in double precision (f64); a GPU offers f32 at best, so the GPU path is a fast approximate multiply, not a bit-for-bit replacement. prec = "f32" (default) requests f32 accumulation; how close the result lands depends on the Vulkan driver (some, e.g. RADV/Mesa, accumulate in f16 regardless, giving ~1e-3 relative error either way). prec = "f16" only lowers precision further, for speed.
  • Full double precision — need bit-accurate results? ggml_matmul_f64(A, B) runs the multiply in fp64 on the GPU, matching R's %*% to ~1e-15. It only pays off on data-centre cards with fast fp64 (Tesla P100/V100, Instinct); consumer GPUs cripple fp64, so it falls back to (and is usually slower than) the CPU there.

Sequential API

The fastest way to get a model running — stack layers with the pipe, compile, train.

library(ggmlR)

model <- ggml_model_sequential() |>
  ggml_layer_dense(128L, activation = "relu",    input_shape = 784L) |>
  ggml_layer_dropout(rate = 0.3) |>
  ggml_layer_dense(10L,  activation = "softmax")

model <- ggml_compile(model,
                      optimizer = "adam",
                      loss      = "categorical_crossentropy",
                      metrics   = "accuracy")

model <- ggml_fit(model, x_train, y_train,
                  epochs           = 10L,
                  batch_size       = 32L,
                  validation_split = 0.1,
                  verbose          = 1L)
# Important: always assign the return value back to model —
# ggml_fit() returns the model with updated weights.

plot(model$history)

ggml_evaluate(model, x_test, y_test)
preds <- ggml_predict(model, x_new)

Available layers (Sequential)

LayerFunction
Denseggml_layer_dense(units, activation)
Conv1Dggml_layer_conv_1d(filters, kernel_size)
Conv2Dggml_layer_conv_2d(filters, kernel_size, padding)
MaxPooling2Dggml_layer_max_pooling_2d(pool_size)
GlobalAvgPool2Dggml_layer_global_average_pooling_2d()
BatchNormggml_layer_batch_norm()
Flattenggml_layer_flatten()
Dropoutggml_layer_dropout(rate)
Embeddingggml_layer_embedding(vocab_size, dim)
LSTMggml_layer_lstm(units, return_sequences)
GRUggml_layer_gru(units, return_sequences)

CNN example (MNIST)

model <- ggml_model_sequential() |>
  ggml_layer_conv_2d(32L, kernel_size = c(3L, 3L), activation = "relu",
                     input_shape = c(28L, 28L, 1L)) |>
  ggml_layer_max_pooling_2d(pool_size = c(2L, 2L)) |>
  ggml_layer_conv_2d(64L, kernel_size = c(3L, 3L), activation = "relu") |>
  ggml_layer_global_average_pooling_2d() |>
  ggml_layer_dense(10L, activation = "softmax")

Functional API

Wire layers into arbitrary graphs — residual connections, multi-input/output, shared weights.

Residual (skip) connection

inp <- ggml_input(shape = 64L)
x   <- inp |> ggml_layer_dense(64L, activation = "relu")
res <- ggml_layer_add(list(inp, x))        # element-wise add
out <- res |> ggml_layer_dense(10L, activation = "softmax")

m <- ggml_model(inputs = inp, outputs = out)
m <- ggml_compile(m, optimizer = "adam", loss = "categorical_crossentropy")
m <- ggml_fit(m, x_train, y_train, epochs = 5L, batch_size = 32L)

Embedding + GRU + skip connection (NLP)

inp <- ggml_input(shape = 30L, dtype = "int32", name = "tokens")
emb <- inp |> ggml_layer_embedding(vocab_size = 500L, dim = 32L)

# Branch A: GRU path
proj_a <- emb |>
  ggml_layer_gru(32L, return_sequences = FALSE) |>
  ggml_layer_dense(32L)

# Branch B: flatten + projection
proj_b <- emb |>
  ggml_layer_flatten() |>
  ggml_layer_dense(32L, activation = "relu") |>
  ggml_layer_dense(32L)

# Residual merge
out <- ggml_layer_add(list(proj_a, proj_b)) |>
  ggml_layer_dropout(rate = 0.3) |>
  ggml_layer_dense(2L, activation = "softmax")

m <- ggml_model(inputs = inp, outputs = out)

Token values must be 0-based integers in [0, vocab_size - 1].

Multi-input model

inp1 <- ggml_input(shape = 20L, name = "timeseries")
inp2 <- ggml_input(shape = 3L,  name = "metadata")

br1 <- inp1 |> ggml_layer_dense(16L, activation = "relu")
br2 <- inp2 |> ggml_layer_dense(8L,  activation = "relu")

out <- ggml_layer_concatenate(list(br1, br2), axis = 0L) |>
  ggml_layer_dense(2L, activation = "softmax")

m <- ggml_model(inputs = list(inp1, inp2), outputs = out)
m <- ggml_compile(m, optimizer = "adam", loss = "categorical_crossentropy")

# Pass x as a list — one matrix per input
m <- ggml_fit(m, x = list(x_ts, x_meta), y = y,
              epochs = 10L, batch_size = 32L)
preds <- ggml_predict(m, list(x_ts, x_meta))

Multi-output model

inp    <- ggml_input(shape = 64L)
hidden <- inp    |> ggml_layer_dense(64L, activation = "relu")
out    <- hidden |> ggml_layer_dense(10L, activation = "softmax")

m     <- ggml_model(inputs = inp, outputs = list(hidden, out))
preds <- ggml_predict(m, x)
# preds[[1]] — hidden activations  [n × 64]
# preds[[2]] — class probabilities [n × 10]

ResNet-like image classifier

residual_block <- function(x, filters, name) {
  main     <- x |> ggml_layer_conv_2d(filters, c(3L, 3L), padding = "same",
                                       name = paste0(name, "_conv"))
  shortcut <- x |> ggml_layer_conv_2d(filters, c(1L, 1L), padding = "same",
                                       name = paste0(name, "_proj"))
  ggml_layer_add(list(main, shortcut), name = paste0(name, "_add"))
}

inp <- ggml_input(shape = c(32L, 32L, 3L))
x   <- inp |> ggml_layer_conv_2d(16L, c(3L, 3L), activation = "relu",
                                  padding = "same")
x   <- residual_block(x, 16L, "res1")
x   <- residual_block(x, 32L, "res2")
out <- x |>
  ggml_layer_global_average_pooling_2d() |>
  ggml_layer_dropout(rate = 0.4) |>
  ggml_layer_dense(3L, activation = "softmax")

m <- ggml_model(inputs = inp, outputs = out)

Shared layers (Siamese / weight sharing)

enc <- ggml_dense(32L, activation = "relu", name = "encoder")

x1 <- ggml_input(shape = 16L, name = "left")
x2 <- ggml_input(shape = 16L, name = "right")

h1 <- ggml_apply(x1, enc)   # identical weights
h2 <- ggml_apply(x2, enc)

out <- ggml_layer_add(list(h1, h2)) |>
  ggml_layer_dense(2L, activation = "softmax")

m <- ggml_model(inputs = list(x1, x2), outputs = out)

Differences from Keras

FeatureKeras (Python)ggmlR
Batch dimensionpart of input_shapeexcluded from shape
Merge layersadd([a, b])ggml_layer_add(list(a, b))
Shared layersreuse layer objectggml_dense() + ggml_apply()
Multi-input datalist of arrayslist() of R matrices
Multi-output predictlist of numpy arraysR list of matrices
BackendTensorFlow / JAX / PyTorchggml (Vulkan GPU, CPU fallback)

Dynamic Autograd Engine (PyTorch-style)

Build and train arbitrary architectures with eager execution and automatic differentiation.

library(ggmlR)

# Define parameters
W <- ag_param(matrix(rnorm(4 * 8) * 0.1, 8, 4))
b <- ag_param(matrix(0, 8, 1))

# Forward + backward
with_grad_tape({
  h    <- ag_add(ag_matmul(W, x_batch), b)
  h    <- ag_relu(h)
  loss <- ag_mse_loss(h, y_batch)
})
grads <- backward(loss)

opt <- optimizer_adam(list(W = W, b = b), lr = 1e-3)
opt$step(grads)
opt$zero_grad()

Transformer encoder block

model <- ag_sequential(
  ag_linear(64L, 128L, activation = "relu"),
  ag_batch_norm(128L),
  ag_dropout(0.1),
  ag_linear(128L, 10L)
)

params <- model$parameters()
opt    <- optimizer_adam(params, lr = 1e-3)
sch    <- lr_scheduler_cosine(opt, T_max = 50L, lr_min = 1e-5)

dl <- ag_dataloader(x_train, y_train, batch_size = 32L, shuffle = TRUE)

for (epoch in 1:50) {
  for (batch in dl$epoch()) {
    with_grad_tape({
      out  <- model$forward(batch$x)
      loss <- ag_softmax_cross_entropy_loss(out, batch$y)
    })
    grads <- backward(loss)
    clip_grad_norm(params, grads, max_norm = 1.0)
    opt$step(grads)
    opt$zero_grad()
  }
  sch$step()
}

Data-parallel training

dp_train() splits data across N replicas, averages gradients, and keeps weights in sync automatically.

make_model <- function() {
  W <- ag_param(matrix(rnorm(4 * 2) * 0.1, 2, 4))
  b <- ag_param(matrix(0, 2, 1))
  list(
    forward    = function(x) ag_add(ag_matmul(W, x), b),
    parameters = function() list(W = W, b = b)
  )
}

result <- dp_train(
  make_model  = make_model,
  data        = my_dataset,           # list of samples
  loss_fn     = function(out, tgt) ag_mse_loss(out, tgt),
  forward_fn  = function(model, s) model$forward(s$x),
  target_fn   = function(s) s$y,
  n_gpu       = 2L,                   # number of replicas
  n_iter      = 100L,
  lr          = 1e-3,
  max_norm    = 5.0
)

result$loss_history   # numeric vector, one value per iteration
result$model          # trained replica 0

Multi-GPU: tensor & pipeline parallelism

For machines with several Vulkan GPUs, ggmlR ships a native tensor-parallel and pipeline-parallel path (not in upstream ggml, which does tensor-split only for CUDA/SYCL). The cross-device transport defaults to portable host staging (device→host→device), correct on every driver.

Tensor parallelism — split a weight matrix's rows across GPUs, compute each slice on its own device, gather the result:

W <- matrix(rnorm(4096 * 256), nrow = 4096)   # 4096 outputs x 256 inputs
X <- matrix(rnorm(8 * 256),    nrow = 8)       # batch of 8

Y <- ggml_vulkan_split_mul_mat(W, X, n_devices = 2)   # == X %*% t(W)

TP × DP hybrid — data-parallel over the batch across replicas of tensor-parallel device groups (e.g. 2 replicas × TP=2 on a 4-GPU box):

# replica A = GPUs {0,1}, replica B = GPUs {2,3}; batch split across replicas,
# weights tensor-split within each pair. No cross-replica traffic at inference.
Y <- ggml_tp_dp_forward(W, X, replicas = list(c(0, 1), c(2, 3)))

Pipeline parallelism — split a model by layers across GPUs; the activation tensor is handed between stages just once per pass (a single cross-device copy). Suits models too large for one card:

# stage 1 (layers 1..k) on GPU 0  ->  stage 2 (layers k+1..n) on GPU 1
mk <- function(dev, Wt) list(
  device = dev, in_shape = c(K, M),
  build  = function(ctx, input) {
    w <- ggml_new_tensor_2d(ctx, GGML_TYPE_F32, K, K)
    list(output      = ggml_relu(ctx, ggml_mul_mat(ctx, w, input)),
         set_weights = function() ggml_backend_tensor_set_data(w, as.numeric(Wt)))
  })
y <- ggml_pp_forward(list(mk(0L, W1), mk(1L, W2)), x = as.numeric(X), out_shape = c(K, M))

See inst/examples/tp_dp_hybrid.R and inst/examples/pp_pipeline.R for complete runnable demos.

Benchmark: which split strategy to use

Measured with llamaR (which links libggml.a statically) driving Qwen2.5-1.5B-Instruct Q4_K_M (Vulkan, host-staging cross-device transport) on two 4-GPU hosts, decode throughput, median of 3 runs of 128 tokens:

  • P100 — 4× Tesla P100-SXM2-16GB
  • V100 — 4× Tesla V100-32GB, 2× Xeon E5-2698 v4, 256 GB RAM
StrategyGPUsSplitDecode t/s (P100)Decode t/s (V100)Notes
Baseline1none419.7516.9model fits in one card — fastest
Pipeline (PP)2layer150.4221.5layers spread across 2 GPUs
Tensor (TP)2row150.4223.2rows split, all-reduce per layer
Pipeline (PP)4layer133.3176.3more hops → slower
Tensor (TP)4row130.0176.6more hops → slower
TP=2 × DP=24row + replicas3064462 replicas × TP=2, run concurrently
DP=44replicas97513004 single-GPU replicas, run concurrently

Same model on an 8× Tesla V100-32GB host (2× Xeon E5-2698 v4, 256 GB RAM), showing how the pattern holds as GPU count doubles:

StrategyGPUsSplitDecode t/sNotes
Baseline1none684.9model fits in one card — fastest
Pipeline (PP)2layer229.7layers spread across 2 GPUs
Tensor (TP)2row231.3rows split, all-reduce per layer
Pipeline (PP)4layer187.5more hops → slower
Tensor (TP)4row191.0more hops → slower
Pipeline (PP)8layer142.88-way split — slowest single-context
Tensor (TP)8row137.1per-layer all-reduce across 8 cards
TP=2 × DP=48row + replicas8974 replicas × TP=2, run concurrently
DP=88replicas22908 single-GPU replicas, run concurrently

Takeaway: when a model fits in one GPU, data parallelism (DP — independent replicas) wins by a wide margin: DP=4 delivers ~2.3× the single-card throughput and ~7.5× any split mode. Splitting such a model across cards (PP/TP) only adds cross-device overhead — the ~1 GB/s host-staging transport dominates. PP and TP earn their keep only when the model does not fit in one card (e.g. a 30B+ model on 16 GB cards): there a split is the only way to run it at all, and PP minimizes cross-device hops (one activation copy per pass) while TP maximizes per-token parallelism at the cost of a per-layer all-reduce. Reproduce with llamaR's inst/examples/bench_pp_tp_dp.sh.

Clean shutdown: when a standalone script uses several GPUs, make ggml_vulkan_shutdown(hard = TRUE) its last statement. This tears down Vulkan and then calls _exit(0), skipping the exit-time loader-static-destruction phase that can otherwise flakily segfault after your results are printed (the results are already computed by then, so the crash is harmless-but-noisy). Use plain ggml_vulkan_shutdown() (no hard) mid-session — it releases the devices and is safe to call repeatedly, but does not guarantee a clean process exit on its own.

The _exit(0) path is compiled out by default, because CRAN policy forbids a package terminating the R session. In a default build hard = TRUE does the normal teardown and warns instead of exiting — never silently — so the flaky exit-time segfault can still fire. Compile it in with --configure-args="--enable-hard-exit" (Windows: Sys.setenv(GGML_VK_HARD_EXIT = "1") before installing), and check the current build with ggml_vulkan_hard_exit_available().

When to use it — and when not. hard = TRUE only pays off for multi-GPU scripts (tensor/pipeline parallelism, split_mul_mat/pp_forward), where late device finalizers race the loader teardown on exit. A single-GPU script never triggers that race, so it does not need hard = TRUE. Do not use it under a Jupyter / Kaggle notebook: there _exit(0) kills the R kernel, and the notebook runner (papermill/nbclient) reports it as DeadKernelError: Kernel died even though all results were already computed and written. In a notebook, either drop the call or use plain ggml_vulkan_shutdown() (soft teardown, kernel stays alive). A portable one-liner that keeps the hard exit only outside notebooks:

is_notebook <- nzchar(Sys.getenv("KAGGLE_KERNEL_RUN_TYPE")) || nzchar(Sys.getenv("JPY_PARENT_PID"))
ggml_vulkan_shutdown(hard = !is_notebook)

Autograd op reference

CategoryFunctions
Linearag_matmul, ag_add, ag_sub, ag_mul, ag_scale
Activationsag_relu, ag_sigmoid, ag_tanh, ag_softmax
Reductionsag_sum, ag_mean (with dim, keepdim)
Mathag_log, ag_exp, ag_pow, ag_clamp
Shapeag_reshape, ag_transpose
Attentionag_multihead_attention
Lossag_mse_loss, ag_cross_entropy_loss, ag_softmax_cross_entropy_loss
Layersag_linear, ag_batch_norm, ag_dropout, ag_embedding
Containersag_sequential
Optimizersoptimizer_sgd, optimizer_adam
Schedulerslr_scheduler_step, lr_scheduler_cosine
Utilitiesclip_grad_norm, ag_gradcheck, dp_train

mlr3 Integration

ggmlR ships with mlr3 learners for tabular classification and regression. After library(ggmlR) (with mlr3 installed), sequential and functional ggmlR networks become available as first-class learners:

library(mlr3)
library(ggmlR)

# Classification on iris (GPU auto-detected via backend = "auto")
task <- tsk("iris")

learner <- lrn("classif.ggml",
               epochs     = 50L,
               batch_size = 16L,
               backend    = "auto")      # "auto" | "cpu" | "gpu"
learner$predict_type <- "prob"

learner$train(task)
pred <- learner$predict(task)
pred$score(msr("classif.logloss"))

Features

  • Both ggmlR APIsmodel_fn can return a ggml_sequential_model or ggml_functional_model. The default builder is ggml_default_mlp(), an exported MLP builder you can also use directly.
  • Vulkan GPU — set backend = "gpu" (or leave "auto") and the learner trains and predicts on GPU.
  • Parallel tuning — the learners declare properties = "marshal" and implement in-memory marshalling (SHA-256-checksummed container), so trained models can be shipped to future / callr workers without file-system round-trips.
  • Weighted trainingclassif.ggml honours task$weights_learner, mapping them to sample_weight in ggml_fit().
  • Callbacks for tuning — pass ggml_callback_early_stopping() etc. via the callbacks parameter to drive early stopping inside mlr3 tuning runs.
  • Custom architectures — set learner$model_fn <- function(task, n_features, n_out, pars) { ... } to build any ggmlR network you like; the learner handles task → matrix conversion, compilation, training, and prediction.
# Regression with a custom architecture
library(mlr3)
library(ggmlR)

learner <- lrn("regr.ggml", epochs = 100L)
learner$model_fn <- function(task, n_features, n_out, pars) {
  ggml_model_sequential() |>
    ggml_layer_dense(256L, activation = "gelu", input_shape = n_features) |>
    ggml_layer_dropout(0.2) |>
    ggml_layer_dense( 64L, activation = "gelu") |>
    ggml_layer_dense(n_out, activation = "linear")
}

learner$train(tsk("mtcars"))

Only numeric features are supported: wrap the learner in a pipeline (po("encode") %>>% po("scale") %>>% lrn("classif.ggml")) when the task has factor columns. mlr3, paradox, R6, and mlr3pipelines are Suggests; ggmlR only wires up the integration when they are installed.

tidymodels / parsnip Integration

ggmlR registers a "ggml" engine for parsnip::mlp(), letting you use ggmlR networks inside the tidymodels ecosystem.

library(ggmlR)
library(parsnip)

spec <- mlp(
  hidden_units = 64,
  epochs       = 100,
  dropout      = 0.2,
  learn_rate   = 0.001
) |>
  set_engine("ggml",
             batch_size = 32,
             backend    = "auto",   # "auto" | "cpu" | "gpu"
             verbose    = 0) |>
  set_mode("classification")

fit_obj <- fit(spec, Species ~ ., data = iris)
predict(fit_obj, new_data = iris)
predict(fit_obj, new_data = iris, type = "prob")

Regression works the same way:

spec_reg <- mlp(hidden_units = 32, epochs = 200) |>
  set_engine("ggml", batch_size = 8, backend = "gpu") |>
  set_mode("regression")

fit_reg <- fit(spec_reg, mpg ~ ., data = mtcars)
predict(fit_reg, new_data = mtcars)

parsnip, tibble, rlang, and dials are in Suggests — ggmlR only wires up the engine when they are installed.

Single-cell GPU Acceleration (Seurat)

Run GPU-accelerated operations directly on Seurat objects — no conversion on your side, and no hard dependency: Seurat/SeuratObject stay in Suggests, so ggmlR installs fine without them and the adapter activates only when they are present.

Setup. The adapter needs two packages installed alongside ggmlR — Seurat (the object model and its pipeline) and a couple of light helpers it leans on for speed (Matrix for the sparse graphs, FNN for the kd-tree kNN). They are all Suggests, so install them yourself:

install.packages(c("Seurat", "Matrix", "FNN"))   # ggmlR is already installed

library(ggmlR)
library(Seurat)        # ggmlR's S3 methods (RunGGML, ggml_extract, ...) activate
                       # automatically once SeuratObject is on the search path

If FNN is absent the kNN falls back to the GPU/CPU distance matrix; if Matrix is absent the "neighbors" op is unavailable (the graphs are sparse). The rest works with Seurat alone.

RunGGML() is the one-call, Seurat-style entry point (object in, object out — pipe-friendly, mirrors RunPCA()). Vulkan is used automatically when a GPU is present, with a transparent CPU fallback. The supported operations are the heavy matrix steps of a standard pipeline:

opReplacesWhat runs on the GPU
"normalize"NormalizeData() (LogNormalize)sparse log1p(x / colSum × sf) over the stored non-zeros (sparse_lognorm.comp) — the counts stay a dgCMatrix, never densified
"scale"ScaleData()per-gene z-score (x − mean) / sd + clamp over the full dense matrix
"embed"RunPCA()gene-by-gene covariance multiply (eigendecomposition stays on the CPU — ggml has no eigensolver)
"umap"RunUMAP()two custom compute shaders: pairwise_dist.comp (kNN distances, honest f32) and umap_sgd.comp (SGD layout)
"neighbors"FindNeighbors()kNN distances feeding the SNN/Jaccard graph; the FNN kd-tree by default, or a fused GPU kNN (knn_tiled.comp) with knn_backend = "vulkan". Exact kNN either way
"largest_gene"percent.Largest.Geneper-cell highest-expressed gene + its share of the cell total, over the sparse dgCMatrix CSC slots (no densify); bit-exact with qlcMatrix::colMax

"normalize" and "scale" write the transformed matrix back into the assay (the data and scale.data layers), so the rest of the Seurat pipeline picks them up unchanged. "embed" and "umap" add a dimensionality reduction; "neighbors" writes the <assay>_nn and <assay>_snn graphs into @graphs, exactly where FindClusters() looks; "largest_gene" adds largest_gene and percent.Largest.Gene columns to meta.data / colData.

What runs where

A standard Seurat workflow maps onto the adapter like this — five of the heavy steps move to the GPU, and only the final community detection stays on the CPU:

Standard stepggmlRRuns on
NormalizeData()RunGGML(op = "normalize")GPU
ScaleData()RunGGML(op = "scale")GPU
RunPCA()RunGGML(op = "embed")GPU matrix multiply (eigensolve on CPU — ggml has none)
RunUMAP()RunGGML(op = "umap")GPU (distance + SGD shaders)
FindNeighbors()RunGGML(op = "neighbors")kNN on CPU (FNN kd-tree) or GPU (knn_backend = "vulkan", knn_tiled.comp) → sparse SNN
FindClusters()— (use Seurat's)CPU — iterative graph Louvain/Leiden, a poor GPU fit and already fast on the CPU

On a Vulkan GPU (AMD RADV) the GPU steps are markedly faster than a naive reference. Indicative numbers at 2000 cells:

StepWhat was sped upSpeed-up
neighbors distance kerneltiled f32 vs stats::distup to ~4×
neighbors GPU kNN (knn_backend = "vulkan")fused knn_tiled.comp vs FNN kd-tree~2–3× at 25–50k cells, and grows — the kNN cost is linear in n rather than the kd-tree's ~O(n²) in ~10-D
largest_genesparse CSC argmax vs qlcMatrix::colMax~30× (≈20 s → 0.6 s at 53k cells)
umap pipelinekd-tree kNN + sparse fuzzy graph + GPU SGD~13× (≈1.45 s → 0.11 s)
umap SGD shader aloneone GPU dispatch per epoch~10⁹ edge-updates/s

The whole pipeline A/B is reproducible with inst/examples/seurat_op2_gpu.R, which runs the classic Seurat route twice — stock CPU vs RunGGML() on the GPU — on the Kaggle Open Problems – Single-Cell Perturbations counts (18 211 genes × 240 090 PBMCs), then checks the two arms agree. A representative run (11 % subsample = 23 279 cells, 2000 HVGs, 50 PCs, --gpu-knn, AMD RADV):

stepcpu (s)gpu (s)speedup
largest_gene8.920.2832.2×
normalize2.841.611.8×
scale1.841.940.9×
embed (PCA)15.923.035.3×
neighbors4.431.453.1×
umap15.325.342.9×
TOTAL (GPU ops)49.2713.663.6×

Every accelerated step matches Seurat to float noise (normalize/scale max abs err ~1e-6, PCA |cor| = 1.0000 over PC1–10, clusters ARI 0.94, largest_gene top-gene agreement 1.0000). scale comes out ~1× — it is memory-bound with nothing to accelerate, so it defaults to the CPU even under Vulkan; PCA's covariance multiply is the biggest matrix-multiply win. See the single-cell-seurat vignette for the full breakdown.

(Numbers are hardware-dependent; reproduce the UMAP shaders separately with inst/examples/umap_shaders_bench.R.)

library(Seurat)

# A whole standard pipeline, GPU-accelerated end to end — every heavy step is a
# RunGGML() call; only FindClusters (graph Louvain) stays on Seurat's side:
pbmc <- RunGGML(pbmc, op = "normalize")                       # -> "data" layer
pbmc <- RunGGML(pbmc, op = "scale")                           # -> "scale.data" layer
pbmc <- RunGGML(pbmc, op = "embed", n_components = 30,
                reduction_name = "pca")                       # -> reduction "pca"

# UMAP on the PC coordinates — both phases on the GPU (distance + SGD shaders):
pbmc <- RunGGML(pbmc, op = "umap", reduction = "pca", dims = 1:30,
                reduction_name = "umap")                      # -> reduction "umap"

# Neighbour graphs on the PC coordinates -> @graphs, then cluster as usual:
pbmc <- RunGGML(pbmc, op = "neighbors", reduction = "pca", dims = 1:30)
pbmc <- FindClusters(pbmc, graph.name = paste0(DefaultAssay(pbmc), "_snn"))

DimPlot(pbmc, reduction = "umap", group.by = "seurat_clusters")

The "umap" op has two phases. The graph/distance phase uses a tiled f32 pairwise-distance kernel that sidesteps mul_mat (whose f16 accumulation reorders nearest neighbours and corrupts the graph), with a kd-tree kNN and a sparse fuzzy graph. The SGD layout phase defaults to the single-threaded reference, which runs in compiled C (R_umap_sgd_cpu) — the earlier interpreted-R loop took ~700 s on ~10k cells; the C version is bit-for-bit identical but finishes in seconds, so it stays the default for best embedding quality. Passing sgd_backend = "vulkan" opts into the umap_sgd.comp shader (one dispatch per epoch, Hogwild updates — faster still, but the lock-free races smear dense-graph clusters, a known hard problem for async UMAP-SGD). Layout numerics match the CPU reference to float32 precision; the SNN graph matches FindNeighbors() bit-for-bit on identical exact kNN.

The adapter is layered, and each layer is a public generic you can call on its own:

FunctionLayerResponsibility
ggml_extract()ExtractionPull a feature × cell matrix out of a Seurat/dgCMatrix/matrix; handles Seurat v4 (GetAssayData) vs v5 (LayerData) and sparse → dense
ggml_run()DispatchValidate against ggml_ops_registry(), route to Vulkan GPU or CPU (auto, with fallback)
ggml_inject()InjectionWrite the result back into the object — a reduction (CreateDimReducObject()) for "embed"/"umap", an assay layer for the "normalize"/"scale" transforms, or <assay>_nn/<assay>_snn Graph objects in @graphs for "neighbors"
# Compose the layers manually (e.g. on a bare matrix, no Seurat needed):
mat  <- ggml_extract(expr_matrix)               # genes × cells, dense
task <- ggml_task("embed", mat, params = list(n_components = 30))
res  <- ggml_run(task)                           # ggml_result: cells × components
res$embedding

# Check capabilities before dispatch:
ggml_ops_registry()        # all supported operations
ggml_ops_registry("embed") # required params + description

A SingleCellExperiment (Bioconductor) path with an S4 runGGML() generic is planned next.

ONNX Model Import

Load pre-trained ONNX models from PyTorch, TensorFlow, or other frameworks and run inference on Vulkan GPU or CPU. No Python or external libraries required — ggmlR includes a built-in zero-dependency protobuf parser.

Quick start

library(ggmlR)

# 1. Load the model
model <- onnx_load("squeezenet.onnx")
model
#> ONNX Model: torch_jit
#>   Producer: pytorch 2.0.1
#>   IR version: 8 / Opset: 18
#>   Nodes: 66 / Weights: 26

# 2. Check expected inputs
onnx_inputs(model)
#> $x.1
#> [1]   1   3 224 224

# 3. Prepare input data (flat numeric vector, row-major NCHW order)
img <- runif(1 * 3 * 224 * 224)

# 4. Run inference — pass a named list matching input names
result <- onnx_run(model, list(x.1 = img))

# 5. Get predictions
scores <- result[[1]]
cat("Predicted class:", which.max(scores) - 1L, "\n")

Loading models

onnx_load() parses the .onnx file, builds a ggml computation graph, and allocates tensors on the specified device. Weights are loaded from the file via memory-mapping (zero-copy).

# Auto-detect device (Vulkan GPU if available, else CPU)
model <- onnx_load("model.onnx")

# Force CPU
model <- onnx_load("model.onnx", device = "cpu")

# Force Vulkan GPU
model <- onnx_load("model.onnx", device = "vulkan")

Dynamic shapes

Some models (BERT, RoBERTa, etc.) have dynamic dimensions for batch size or sequence length. Specify fixed shapes at load time:

model <- onnx_load("bert.onnx",
                    input_shapes = list(
                      input_ids      = c(1L, 128L),
                      attention_mask = c(1L, 128L)
                    ))

If you forget, onnx_load() will tell you which inputs need shapes:

Error: Input 'input_ids' has dynamic shape [?x?].
  Specify fixed shape via input_shapes parameter.

Inspecting the model

# Print overview
model
#> ONNX Model: torch_jit
#>   Nodes: 533 / Weights: 199
#>   Ops: MatMul, Add, LayerNormalization, Softmax, ...

# Detailed metadata
onnx_summary(model)

# Input names and shapes (what to pass to onnx_run)
onnx_inputs(model)

# Backend placement: GPU vs CPU split, scheduler info
onnx_device_info(model)

Running inference

# Single input model
result <- onnx_run(model, list(x = my_data))

# Multiple inputs
result <- onnx_run(model, list(
  input_ids      = as.numeric(token_ids),
  attention_mask = rep(1, 128)
))

# Result is a named list of output tensors
str(result)
#> List of 1
#>  $ output: num [1:1000] 0.00123 0.00045 ...

Preparing input data

ONNX models expect inputs in row-major order (batch, channels, height, width for images). R matrices are column-major, so you may need to transpose:

# Image classification: model expects [1, 3, 224, 224]
# If you have a 224x224x3 R array:
img_array <- array(runif(224 * 224 * 3), dim = c(224, 224, 3))

# Rearrange to NCHW: [1, 3, 224, 224] — channel first
img_chw <- aperm(img_array, c(3, 1, 2))  # [3, 224, 224]
input <- as.numeric(img_chw)              # flat vector, row-major

result <- onnx_run(model, list(x = input))

For NLP models, inputs are typically 1D integer sequences:

# BERT-style: token IDs as numeric vector
tokens <- c(101, 2023, 2003, 1037, 3231, 102, rep(0, 122))  # pad to 128
result <- onnx_run(model, list(input_ids = as.numeric(tokens)))

Interpreting outputs

# Classification: get top-5 predictions
scores <- result[[1]]
top5 <- order(scores, decreasing = TRUE)[1:5]
cat("Top-5 classes:", top5 - 1L, "\n")  # 0-based class indices
cat("Top-5 scores:", scores[top5], "\n")

# Apply softmax if model outputs logits (not probabilities)
probs <- exp(scores) / sum(exp(scores))

Repeated inference

Models can be run multiple times with zero overhead — weights live on GPU permanently and are never re-transferred:

model <- onnx_load("classifier.onnx")

for (batch in data_batches) {
  result <- onnx_run(model, list(x = batch))
  # process result...
}

Tested models

13 out of 15 ONNX Model Zoo models load and run successfully (native 5D tensor support):

ModelNodesKey ops
mnist-812Conv, Relu, MaxPool, Reshape, MatMul
squeezenet1.0-866Conv, Relu, MaxPool, Concat, GlobalAveragePool, Softmax
adv_inception_v3 (Opset 17/18)215Conv, BatchNorm, Relu, Concat, AveragePool
emotion-ferplus-852Conv, Relu, MaxPool, Gemm, Constant
bat_resnext26ts (Opset 18)570Conv, BatchNorm, SiLU, Concat, Expand, Split
bert (Opset 17)533MatMul, LayerNorm, GELU/Erf, Softmax, Shape, Gather, Where
gptneox (Opset 18)482MatMul, LayerNorm, GELU, Softmax, Shape, Gather
MaskRCNN-12-int8937QLinearConv, DequantizeLinear, Resize, Concat, Reshape
roberta-91180MatMul, LayerNorm, Erf, Softmax, Shape, Gather, Cast
sageconv (Opset 16)24MatMul, Add, Mul, Sigmoid, ScatterElements
super-resolution-1012Conv, Reshape, Transpose
botnet26t_256 (Opset 16)530Conv, BatchNorm, RelPosBias2D (fused custom op), Softmax
xcit_tiny436MatMul, LayerNorm, Softmax, Concat, Transpose

Supported ONNX ops (50+)

Arithmetic: Add, Sub, Mul, Div, Pow, Sqrt, Exp, Log, Abs, Neg, Floor, Ceil, Clip, Erf, Equal. Linear: MatMul (batched), Gemm. Convolution: Conv (1D/2D, grouped, depthwise), ConvTranspose (1D/2D), with auto_pad (SAME_UPPER, SAME_LOWER). Pooling: MaxPool, AveragePool, GlobalAveragePool, Resize/Upsample (nearest, bilinear). Normalization: BatchNorm, LayerNorm, GroupNorm, RMSNorm. Activations: Relu, Sigmoid, Tanh, GELU, SiLU, Softmax, LeakyRelu, Elu. Shape: Reshape, Transpose, Concat, Flatten, Squeeze, Unsqueeze, Expand, Slice, Split, Gather, Pad, Shape, Cast, Identity, EyeLike. Constants: Constant (TensorProto + scalar), ConstantOfShape (INT64/INT32/DOUBLE/FLOAT value). Scatter/Gather: ScatterElements (axis=0, reduction=none/add, Vulkan atomicAdd), Gather (axis=0 on rank>2 via reshape). Logic: Where, Equal. Reduction: ReduceMean, ReduceSum. Quantization: DequantizeLinear, QuantizeLinear, QLinearConv, QLinearAdd, QLinearMatMul, QLinearSigmoid, QLinearConcat. Fused custom ops: RelPosBias2D (BoTNet-style 2D relative position bias). Pass-through: Dropout.

GGUF Pre-trained Weights

Load pre-trained weights from GGUF files (llama.cpp, Hugging Face, etc.) with automatic dequantization. Supports all ggml quantization types (F32, F16, Q4_0, Q8_0, K-quants, IQ, MXFP4, Q1_0, NVFP4).

library(ggmlR)

# Load a GGUF file
g <- gguf_load("model.gguf")
g
#> GGUF file: model.gguf
#>   Version:  3
#>   Tensors:  291
#>   Metadata: 24 key-value pairs

# Inspect metadata (architecture, tokenizer, quant info)
meta <- gguf_metadata(g)
meta[["general.architecture"]]

# List all tensor names
gguf_tensor_names(g)

# Get shape and type for a specific tensor
gguf_tensor_info(g, "blk.0.attn_q.weight")
#> $name:  "blk.0.attn_q.weight"
#> $shape: 4096 4096
#> $type:  "Q4_0"

# Extract dequantized weights as R numeric array
w <- gguf_tensor_data(g, "blk.0.attn_q.weight")
dim(w)
#> [1] 4096 4096

# Free when done (also freed by GC)
gguf_free(g)

Examples

Ready-to-run example scripts in inst/examples/:

ScriptDescription
titanic_classification.RBinary classification with feature engineering, dropout, stratified split, manual metrics (~82% val accuracy)
mnist_cnn.RCNN image classifier on MNIST
functional_resnet_cifar.RResNet-style model with skip connections (Functional API)
functional_text_gru.RText classification with GRU + embedding (Functional API)
transformer_encoder_demo.RTransformer encoder with multi-head attention (autograd)
dp_train_demo.RData-parallel training across multiple replicas
benchmark_onnx.RGPU vs CPU inference benchmark for ONNX models
benchmark_ops.RPer-op micro-benchmark: every ggml op on CPU and GPU with auto-batching
profile_onnx_superres_gpu.RGPU profiler for SuperResolution ONNX model across input sizes
mlr3_integration.Rmlr3 learners: CPU vs GPU comparison, iris + mtcars, 3-fold CV
tidymodels_integration.Rparsnip engine: CPU vs GPU comparison, iris + mtcars

Save / Load

ggml_save_model(model, "my_model.rds")
model <- ggml_load_model("my_model.rds")

ONNX Benchmark: GPU (Vulkan) vs CPU

Measured on AMD Ryzen 5 5600 + AMD RX 9070, single-image inference:

ModelCPU (ms)GPU (ms)SpeedupCPU FPSGPU FPS
Inception V3265.39.727.5x3.8103.4
MNIST0.00.0InfInf
SqueezeNet 1.022.31.713.4x44.8600.0
SuperResolution100.03.330.0x10.0300.0
EmotionFerPlus31.32.313.4x31.9428.6
Inception V3 Op18204.78.324.6x4.9120.0
BAT-ResNeXt26ts116.07.315.8x8.6136.4
BERT (Opset17)243.79.027.1x4.1111.1
GPT-NeoX1.33.30.4x750.0300.0

Benchmark scripts: inst/examples/benchmark_onnx.R, inst/examples/profile_onnx_superres_gpu.R

LLM Inference Benchmark

Measured on AMD Ryzen 5 5600 + AMD RX 9070, via llamaR. Model: Ministral-3-3B-Instruct-2512-Q8_0, 50 tokens, avg of 3 runs:

BackendSpeed (tokens/sec)Speedup
CPU (8 threads)8.51.0x
GPU (Vulkan)108.012.7x

Flux Image Generation Benchmark (10 steps)

Measured on AMD Ryzen 5 5600 + AMD RX 9070, via sd2R:

ScenarioResolutionTime (s)
Direct768×76813.94
Tiled VAE1024×102425.32
Highres fix2048×102452.53
img2img768×7688.73
Direct1024×102425.40

GPU Acceleration

ggmlR is designed GPU-first: Vulkan is auto-detected at build time and, when available, 90%+ of operations run on GPU with up to 78x speedup over CPU. On machines without a Vulkan-capable GPU the package falls back to CPU transparently — no code changes required.

ggml_vulkan_available()   # TRUE if a Vulkan GPU was detected
ggml_vulkan_status()      # device name, memory, capabilities

# Dynamic autograd: switch device at runtime
ag_device("gpu")   # move subsequent ops to GPU (f16 by default)
ag_device("cpu")   # fall back to CPU

Supported GPUs: NVIDIA, AMD, Intel, ARM Mali, Qualcomm Adreno.

Vulkan optimizations

  • Vulkan 1.4 — push constants limit raised to 256 bytes, enabling full 5D tensor parameter blocks in compute shaders without staging buffers.
  • Push Descriptors (VK_KHR_push_descriptor) — when available, descriptors are pushed directly into the command buffer, eliminating descriptor pool allocation overhead. Falls back to descriptor pools on older hardware.
  • Q4_K flash attentionGGML_OP_FLASH_ATTN_EXT with Q4_K key/value tensors now runs fully on GPU (FA_SCALAR and FA_COOPMAT1 paths). Previously Q4_K attention fell back to CPU. Relevant for llamaR with quantized LLMs on AMD/Intel GPU (KHR cooperative matrix).
  • Subgroup-shuffle mmq (USE_SUBGROUP_NO_SHMEM) — on wavefront-64 devices (RDNA4, subgroup_size=64) Q4_K / Q5_K / Q6_K weight tiles are loaded directly into registers via subgroupShuffle, eliminating the shared-memory staging round-trip. ~10-15% token-generation throughput gain on LLaMA 3.x models.

System Requirements

  • R ≥ 4.1.0, C++17 compiler
  • Optional GPU: Vulkan 1.2+, libvulkan-dev + glslc (Linux) or Vulkan SDK (Windows)
  • Platforms: Linux, macOS, Windows (x86-64, ARM64)

See Also

  • llamaR — LLM inference in R
  • sd2R — Stable Diffusion in R
  • ggml — underlying C library

License

MIT

Copy Link

Version

Install

install.packages('ggmlR')

Monthly Downloads

628

Version

0.8.1

License

MIT + file LICENSE

Issues

Pull Requests

Stars

Forks

Maintainer

Yuri Baramykov

Last Published

July 13th, 2026

Functions in ggmlR (0.8.1)

ag_clamp

Element-wise clamp
ag_cross_entropy_loss

Categorical Cross-Entropy loss
ag_batch_norm

Create a Batch Normalisation layer
ag_dataloader

Create a mini-batch data loader
abind_first

Bind Two Arrays Along the First Dimension
ag_add

Element-wise addition with broadcasting
RunGGML.SingleCellExperiment

Run a GGML GPU operation on a Seurat object
GGML_GLU_OP_REGLU

GLU Operation Types
GGML_SORT_ORDER_ASC

Sort Order Constants
GGML_TYPE_F32

GGML Data Types
ag_eval

Switch a layer or sequential model to eval mode
ag_device

Set the default compute device for ag_* operations
ag_default_dtype

Return the current default dtype for GPU operations
ag_dtype

Set the default floating-point precision for ag_* GPU operations
ag_embedding

Create an Embedding layer
ag_gradcheck

Numerical gradient check (like torch.autograd.gradcheck)
ag_linear

Create a dense layer with learnable parameters
ag_default_device

Return the current default compute device
ag_exp

Element-wise exponential
ag_dropout

Create a Dropout layer
ag_mse_loss

Mean Squared Error loss
ag_pow

Element-wise power
ag_mean

Mean of elements (or along a dim)
ag_load_model

Load an autograd module from a saved state
ag_param

Create a parameter tensor (gradient tracked)
ag_multihead_attention

Create a Multi-Head Attention layer
ag_relu

ReLU activation
ag_mul

Element-wise multiplication
ag_sequential

Create a sequential container of layers
ag_sum

Sum all elements (or along a dim): out = sum(x)
ag_reshape

Reshape tensor
ag_scale

Scale tensor by a scalar constant
ag_softmax_cross_entropy_loss

Fused softmax + cross-entropy loss (numerically stable)
ag_matmul

Matrix multiplication
ag_log

Element-wise natural logarithm
ag_sigmoid

Sigmoid activation
ag_sub

Element-wise subtraction
ag_tanh

Tanh activation
ag_softmax

Softmax activation (column-wise)
ag_save_model

Save an autograd module's state to disk
ag_train

Switch a layer or sequential model to training mode
ag_tensor

Create a dynamic tensor (no gradient tracking)
as.matrix.ggml_matrix

Extract the underlying matrix from a ggml_matrix
as_gpu_matrix

Wrap a matrix so multiplies run on the GPU
ag_to_device

Move a tensor to the specified device
clip_grad_norm

Clip gradients by global L2 norm
compile.ggml_sequential_model

Compile a Model
augment.ggmlr_parsnip_model

Augment new data with predictions from a fitted ggml parsnip model
backward

Run backward pass from a scalar loss tensor
ag_transpose

Transpose a tensor
.ggmlr_largest_gene

Highest-expressed gene per cell (op = "largest_gene")
dequantize_row_iq2_xxs

Dequantize Row (IQ)
dequantize_row_tq1_0

Dequantize Row (Ternary)
dequantize_row_q1_0

Dequantize Q1_0 Data
dequantize_row_nvfp4

Dequantize NVFP4 Data
dequantize_row_q4_0

Dequantize Row (Q4_0)
.ggmlr_batch_shards

Split a batch index range into (near) equal contiguous shards
dequantize_row_q2_K

Dequantize Row (K-quants)
dequantize_row_mxfp4

Dequantize Row (MXFP4)
.ggmlr_neighbors_gpu

kNN + shared-nearest-neighbour graphs (op = "neighbors")
.ggmlr_normalize_gpu

GPU-accelerated LogNormalize (op = "normalize")
evaluate.ggml_sequential_model

Evaluate a Model
fit.ggml_sequential_model

Train a Model
dp_train

Data-parallel training across multiple GPUs
ggml_abs

Absolute Value (Graph)
ggml_abort_is_r_enabled

Check if R Abort Handler is Enabled
.ggmlr_pca_gpu

GPU-accelerated PCA on a dense expression matrix
.ggmlr_umap_gpu

GPU-bound UMAP embedding (op = "umap")
.ggmlr_scale_gpu

GPU-accelerated ScaleData / z-score (op = "scale")
ggmlR-package

ggmlR: 'GGML' Tensor Operations for Machine Learning
ggml_add1

Add Scalar to Tensor (Graph)
ggml_are_same_shape

Compare Tensor Shapes
ggml_abs_inplace

Absolute Value In-place (Graph)
ggml_add_inplace

Element-wise Addition In-place (Graph)
ggml_add_rel_pos

Add Relative Position Bias (Graph)
ggml_add

Add tensors
ggml_arange

Arange (Graph)
ggml_are_same_layout

Check if Two Tensors Have the Same Layout
ggml_are_same_stride

Compare Tensor Strides
ggml_apply

Apply a Layer Object to a Tensor Node
ggml_backend_buffer_is_multi_buffer

Check if buffer is a multi-buffer
ggml_backend_buffer_clear

Clear buffer memory
ggml_backend_alloc_ctx_tensors

Allocate Context Tensors to Backend
ggml_backend_buffer_name

Get Backend Buffer Name
ggml_argsort

Argsort - Get Sorting Indices (Graph)
ggml_argmax

Argmax (Graph)
ggml_backend_buffer_get_usage

Get buffer usage
ggml_backend_buffer_get_size

Get Backend Buffer Size
ggml_backend_buffer_free

Free Backend Buffer
ggml_backend_buffer_is_host

Check if buffer is host memory
ggml_backend_cpu_set_n_threads

Set CPU Backend Threads
ggml_backend_buffer_usage_any

Buffer usage: Any
ggml_backend_dev_count

Get number of available devices
ggml_backend_buffer_reset

Reset buffer
ggml_backend_dev_by_type

Get device by type
ggml_backend_dev_by_name

Get device by name
ggml_backend_buffer_usage_weights

Buffer usage: Weights
ggml_backend_cpu_init

Initialize CPU Backend
ggml_backend_buffer_usage_compute

Buffer usage: Compute
ggml_backend_buffer_set_usage

Set buffer usage hint
ggml_backend_dev_description

Get device description
ggml_backend_dev_init

Initialize backend from device
ggml_backend_dev_get_props

Get device properties
ggml_backend_dev_supports_buft

Check if device supports buffer type
ggml_backend_dev_supports_op

Check if device supports operation
ggml_backend_dev_type

Get device type
ggml_backend_dev_offload_op

Check if device should offload operation
ggml_backend_dev_memory

Get device memory
ggml_backend_dev_get

Get device by index
ggml_backend_dev_name

Get device name
ggml_backend_event_new

Create new event
ggml_backend_device_register

Register a device
ggml_backend_device_type_igpu

Device type: Integrated GPU
ggml_backend_event_synchronize

Synchronize event
ggml_backend_device_type_cpu

Device type: CPU
ggml_backend_device_type_gpu

Device type: GPU
ggml_backend_device_type_accel

Device type: Accelerator
ggml_backend_event_record

Record event
ggml_backend_event_free

Free event
ggml_backend_event_wait

Wait for event
ggml_backend_graph_plan_create

Create graph execution plan
ggml_backend_graph_compute_async

Compute graph asynchronously
ggml_backend_init_by_name

Initialize backend by name
ggml_backend_get_device

Get device from backend
ggml_backend_free

Free Backend
ggml_backend_init_best

Initialize best available backend
ggml_backend_graph_plan_compute

Execute graph plan
ggml_backend_graph_plan_free

Free graph execution plan
ggml_backend_init_by_type

Initialize backend by type
ggml_backend_graph_compute

Compute Graph with Backend
ggml_backend_reg_dev_get

Get device from registry
ggml_backend_load_all

Load all available backends
ggml_backend_multi_buffer_alloc_buffer

Allocate multi-buffer
ggml_backend_meta_device

Create a Meta Backend Device
ggml_backend_name

Get Backend Name
ggml_backend_reg_by_name

Get backend registry by name
ggml_backend_reg_count

Get number of registered backends
ggml_backend_reg_dev_count

Get number of devices in registry
ggml_backend_load

Load backend from dynamic library
ggml_backend_multi_buffer_set_usage

Set usage for all buffers in a multi-buffer
ggml_backend_sched_get_tensor_backend

Get tensor backend assignment
ggml_backend_sched_get_backend

Get backend from scheduler
ggml_backend_reg_name

Get registry name
ggml_backend_register

Register a backend
ggml_backend_sched_free

Free backend scheduler
ggml_backend_sched_alloc_graph

Allocate graph on scheduler
ggml_backend_sched_get_n_splits

Get number of graph splits
ggml_backend_sched_get_n_copies

Get number of tensor copies
ggml_backend_sched_get_n_backends

Get number of backends in scheduler
ggml_backend_reg_get

Get backend registry by index
ggml_backend_tensor_copy_async

Copy tensor asynchronously between backends
ggml_backend_tensor_get_and_sync

Backend Tensor Get and Sync
ggml_backend_sched_synchronize

Synchronize scheduler
ggml_backend_sched_reset

Reset scheduler
ggml_backend_sched_new

Create a new backend scheduler
ggml_backend_sched_set_tensor_backend

Set tensor backend assignment
ggml_backend_sched_graph_compute_async

Compute graph asynchronously
ggml_backend_sched_reserve

Reserve memory for scheduler
ggml_backend_synchronize

Synchronize backend
ggml_backend_sched_graph_compute

Compute graph using scheduler
ggml_backend_tensor_get_async

Get tensor data asynchronously
ggml_batch_norm

Create a Batch Normalization Layer Object
ggml_backend_tensor_get_data

Get Tensor Data via Backend
ggml_backend_tensor_set_data

Set Tensor Data via Backend
ggml_build_forward_expand

Build forward expand
ggml_callback_early_stopping

Early stopping callback
ggml_backend_unload

Unload backend
ggml_backend_tensor_get_f32_first

Get First Float from Backend Tensor
ggml_blck_size

Get Block Size
ggml_backend_tensor_set_async

Set tensor data asynchronously
ggml_conv_1d

1D Convolution (Graph)
ggml_conv_2d

2D Convolution (Graph)
ggml_conv_1d_dw

Depthwise 1D Convolution (Graph)
ggml_compile.ggml_functional_model

Compile a Sequential Model
ggml_can_repeat

Check If Tensor Can Be Repeated
ggml_ceil_inplace

Ceiling In-place (Graph)
ggml_concat

Concatenate Tensors (Graph)
ggml_ceil

Ceiling (Graph)
ggml_clamp

Clamp (Graph)
ggml_cont

Make Contiguous (Graph)
ggml_conv_2d_direct

Direct 2D Convolution (Graph)
ggml_conv_transpose_2d_p0

Transposed 2D Convolution, zero padding (Graph)
ggml_cpu_features

Get All CPU Features
ggml_cpu_add

Element-wise Addition (CPU Direct)
ggml_conv_2d_dw

Depthwise 2D Convolution (Graph)
ggml_conv_2d_dw_direct

Depthwise 2D Convolution, direct (Graph)
ggml_cos

Cosine (Graph)
ggml_count_equal

Count Equal Elements (Graph)
ggml_conv_transpose_1d

Transposed 1D Convolution (Graph)
ggml_cpu_get_rvv_vlen

Get RISC-V Vector Length
ggml_cpu_get_sve_cnt

Get SVE Vector Length (ARM)
ggml_cpu_has_arm_fma

CPU Feature Detection - ARM FMA
ggml_cpu_has_avx

CPU Feature Detection - AVX
ggml_cpu_has_avx512_vnni

CPU Feature Detection - AVX-512 VNNI
ggml_cpu_has_avx512_bf16

CPU Feature Detection - AVX-512 BF16
ggml_cpu_has_avx512_vbmi

CPU Feature Detection - AVX-512 VBMI
ggml_cpu_has_avx_vnni

CPU Feature Detection - AVX-VNNI
ggml_cpu_has_avx2

CPU Feature Detection - AVX2
ggml_cpu_has_avx512

CPU Feature Detection - AVX-512
ggml_cpu_has_amx_int8

CPU Feature Detection - AMX INT8
ggml_cpu_has_fp16_va

CPU Feature Detection - FP16 Vector Arithmetic (ARM)
ggml_cpu_has_dotprod

CPU Feature Detection - Dot Product (ARM)
ggml_cpu_has_f16c

CPU Feature Detection - F16C
ggml_cpu_has_sme

CPU Feature Detection - SME (ARM)
ggml_cpu_has_neon

CPU Feature Detection - NEON (ARM)
ggml_cpu_has_fma

CPU Feature Detection - FMA
ggml_cpu_has_llamafile

CPU Feature Detection - Llamafile
ggml_cpu_has_matmul_int8

CPU Feature Detection - INT8 Matrix Multiply (ARM)
ggml_cpu_has_bmi2

CPU Feature Detection - BMI2
ggml_cpu_has_riscv_v

CPU Feature Detection - RISC-V Vector
ggml_cpu_has_vxe

CPU Feature Detection - VXE (IBM z/Architecture)
ggml_cpu_has_ssse3

CPU Feature Detection - SSSE3
ggml_cpu_has_wasm_simd

CPU Feature Detection - WebAssembly SIMD
ggml_cpu_has_sse3

CPU Feature Detection - SSE3
ggml_cycles

Get CPU Cycles
ggml_cpy

Copy Tensor with Type Conversion (Graph)
ggml_crossprod

GPU cross product (drop-in for crossprod)
ggml_cpu_has_vsx

CPU Feature Detection - VSX (PowerPC)
ggml_cpu_mul

Element-wise Multiplication (CPU Direct)
ggml_cpu_has_sve

CPU Feature Detection - SVE (ARM)
ggml_cycles_per_ms

Get CPU Cycles per Millisecond
ggml_div

Element-wise Division (Graph)
ggml_div_inplace

Element-wise Division In-place (Graph)
ggml_dense

Create a Dense Layer Object
ggml_diag_mask_inf_inplace

Diagonal Mask with -Inf In-place (Graph)
ggml_dup

Duplicate Tensor (Graph)
ggml_diag_mask_inf

Diagonal Mask with -Inf (Graph)
ggml_default_mlp

Default MLP builder for classification and regression
ggml_diag

Diagonal Matrix (Graph)
ggml_diag_mask_zero

Diagonal Mask with Zero (Graph)
ggml_exp

Exponential (Graph)
ggml_elu_inplace

ELU Activation In-place (Graph)
ggml_dup_inplace

Duplicate Tensor In-place (Graph)
ggml_dup_tensor

Duplicate Tensor
ggml_embedding

Create an Embedding Layer Object
ggml_evaluate.ggml_functional_model

Evaluate a Trained Model
ggml_exp_inplace

Exponential In-place (Graph)
ggml_estimate_memory

Estimate Required Memory
ggml_elu

ELU Activation (Graph)
ggml_element_size

Get Element Size
ggml_flash_attn_back

Flash Attention Backward (Graph)
ggml_freeze_weights

Freeze Layer Weights
ggml_floor_inplace

Floor In-place (Graph)
ggml_extract

Extract a feature-by-cell matrix from a single-cell container
ggml_free

Free GGML context
ggml_flash_attn_ext

Flash Attention (Graph)
ggml_fit.ggml_functional_model

Train a Model (dispatcher)
ggml_floor

Floor (Graph)
ggml_fit_opt

Fit model with R-side epoch loop and callbacks
ggml_ftype_to_ggml_type

Convert ftype to ggml_type
ggml_gallocr_get_buffer_size

Get Graph Allocator Buffer Size
ggml_gallocr_free

Free Graph Allocator
ggml_gallocr_alloc_graph

Allocate Memory for Graph
ggml_gallocr_new

Create Graph Allocator
ggml_geglu_quick

GeGLU Quick (Fast GeGLU) (Graph)
ggml_geglu

GeGLU (GELU Gated Linear Unit) (Graph)
ggml_gelu

GELU Activation (Graph)
ggml_gallocr_reserve

Reserve Memory for Graph
ggml_geglu_split

GeGLU Split (Graph)
ggml_gelu_erf

Exact GELU Activation (Graph)
ggml_get_max_tensor_size

Get Maximum Tensor Size
ggml_gelu_quick

GELU Quick Activation (Graph)
ggml_get_mem_size

Get Context Memory Size
ggml_get_f32_nd

Get Single Float Value by N-D Index
ggml_gelu_inplace

GELU Activation In-place (Graph)
ggml_get_f32

Get F32 data
ggml_get_first_tensor

Get First Tensor from Context
ggml_get_i32

Get I32 Data
ggml_get_layer

Get a Layer from a Sequential Model
ggml_get_i32_nd

Get Single Int32 Value by N-D Index
ggml_get_rel_pos

Get Relative Position (Graph)
ggml_get_op_params_i32

Get Integer Op Parameter
ggml_get_rows_back

Get Rows Backward (Graph)
ggml_get_rows

Get Rows by Indices (Graph)
ggml_get_next_tensor

Get Next Tensor from Context
ggml_get_no_alloc

Get No Allocation Mode
ggml_graph_node

Get Graph Node
ggml_get_op_params_f32

Get Float Op Parameter
ggml_glu

Generic GLU (Gated Linear Unit) (Graph)
ggml_graph_overhead

Get Graph Overhead
ggml_get_unary_op

Get Unary Operation from Tensor
ggml_get_op_params

Get Tensor Operation Parameters
ggml_graph_n_nodes

Get Number of Nodes in Graph
ggml_glu_split

Generic GLU Split (Graph)
ggml_graph_get_tensor

Get Tensor from Graph by Name
ggml_graph_compute

Compute graph
ggml_get_name

Get Tensor Name
ggml_graph_compute_with_ctx

Compute Graph with Context (Alternative Method)
ggml_get_n_threads

Get Number of Threads
ggml_graph_dump_dot

Export Graph to DOT Format
ggml_graph_view

Create a View of a Subgraph
ggml_im2col

Image to Column (Graph)
ggml_group_norm

Group Normalization (Graph)
ggml_hardswish

Hard Swish Activation (Graph)
ggml_gru

Create a GRU Layer Object
ggml_hardsigmoid

Hard Sigmoid Activation (Graph)
ggml_group_norm_inplace

Group Normalization In-place (Graph)
ggml_graph_print

Print Graph Information
ggml_graph_reset

Reset Graph (for backpropagation)
ggml_is_available

Check if GGML is available
ggml_is_contiguous_channels

Check Channel-wise Contiguity
ggml_init_auto

Create Context with Auto-sizing
ggml_is_contiguous_1

Check Tensor Contiguity (Dimensions >= 1)
ggml_is_contiguous

Check if Tensor is Contiguous
ggml_is_contiguous_rows

Check Row-wise Contiguity
ggml_is_contiguous_2

Check Tensor Contiguity (Dimensions >= 2)
ggml_input

Declare a Functional API Input Tensor
ggml_is_contiguous_0

Check Tensor Contiguity (Dimension 0)
ggml_init

Initialize GGML context
ggml_inject

Inject a single-cell result back into its container
ggml_layer_batch_norm

Add Batch Normalization Layer
ggml_l2_norm_inplace

L2 Normalization In-place (Graph)
ggml_l2_norm

L2 Normalization (Graph)
ggml_is_transposed

Check if Tensor is Transposed
ggml_layer_concatenate

Concatenate Tensor Nodes Along an Axis
ggml_is_permuted

Check if Tensor is Permuted
ggml_is_contiguously_allocated

Check If Tensor is Contiguously Allocated
ggml_layer_add

Element-wise Addition of Two Tensor Nodes
ggml_is_quantized

Check If Type is Quantized
ggml_layer_conv_1d

Create a Conv1D Layer Object
ggml_layer_flatten

Add Flatten Layer
ggml_layer_dropout

Add Dropout Layer
ggml_layer_global_max_pooling_2d

Global Max Pooling for 2D Feature Maps
ggml_layer_dense

Add Dense (Fully Connected) Layer
ggml_layer_conv_2d

Create a Conv2D Layer Object
ggml_layer_embedding

Add Embedding Layer
ggml_layer_lstm

Add an LSTM Layer
ggml_layer_gru

Add a GRU Layer
ggml_marshal_model

Marshal a ggmlR model to an in-memory container
ggml_log_inplace

Natural Logarithm In-place (Graph)
ggml_leaky_relu

Leaky ReLU Activation (Graph)
ggml_lstm

Create an LSTM Layer Object
ggml_load_weights

Load Model Weights from File
ggml_load_model

Load a Full Model (Architecture + Weights)
ggml_log

Natural Logarithm (Graph)
ggml_log_set_r

Enable R-compatible GGML Logging
ggml_log_set_default

Restore Default GGML Logging
ggml_layer_global_average_pooling_2d

Global Average Pooling for 2D Feature Maps
ggml_log_is_r_enabled

Check if R Logging is Enabled
ggml_layer_max_pooling_2d

Add 2D Max Pooling Layer
ggml_matrix-class

A GPU-backed matrix wrapper
ggml_matmul

GPU matrix multiply (drop-in for %*%)
ggml_matmul_f64

GPU double-precision matrix multiply
ggml_mul_mat

Matrix Multiplication (Graph)
ggml_model

Create a Functional Model
ggml_mul_inplace

Element-wise Multiplication In-place (Graph)
ggml_model_sequential

Create a Sequential Neural Network Model
ggml_mean

Mean (Graph)
ggml_model_backend

Backend a fitted ggml model actually ran on
ggml_mul

Multiply tensors
ggml_nbytes

Get number of bytes
ggml_nelements

Get number of elements
ggml_mul_mat_id

Matrix Multiplication with Expert Selection (Graph)
ggml_n_dims

Get Number of Dimensions
ggml_new_tensor_1d

Create 1D tensor
ggml_new_f32

Create Scalar F32 Tensor
ggml_new_i32

Create Scalar I32 Tensor
ggml_neg_inplace

Negation In-place (Graph)
ggml_new_tensor

Create Tensor with Arbitrary Dimensions
ggml_neg

Negation (Graph)
ggml_new_tensor_4d

Create 4D Tensor
ggml_op_name

Get Operation Name
ggml_new_tensor_2d

Create 2D tensor
ggml_norm

Layer Normalization (Graph)
ggml_new_tensor_3d

Create 3D Tensor
ggml_op_can_inplace

Check if Operation Can Be Done In-place
ggml_op_symbol

Get Operation Symbol
ggml_op_desc

Get Operation Description from Tensor
ggml_nrows

Get Number of Rows
ggml_norm_inplace

Layer Normalization In-place (Graph)
ggml_opt_dataset_free

Free optimization dataset
ggml_opt_dataset_shuffle

Shuffle dataset
ggml_opt_dataset_labels

Get labels tensor from dataset
ggml_opt_dataset_ndata

Get number of datapoints in dataset
ggml_ops_registry

Supported single-cell operations
ggml_opt_context_optimizer_type

Get optimizer type from context
ggml_opt_dataset_data

Get data tensor from dataset
ggml_opt_alloc

Allocate graph for evaluation
ggml_opt_dataset_init

Create a new optimization dataset
ggml_opt_dataset_get_batch

Get batch from dataset
ggml_opt_epoch

Run one training epoch
ggml_opt_grad_acc

Get gradient accumulator for a tensor
ggml_opt_default_params

Get default optimizer parameters
ggml_opt_init_for_fit

Initialize optimizer context for R-side epoch loop
ggml_opt_get_lr

Get current learning rate from optimizer context
ggml_opt_free

Free optimizer context
ggml_opt_fit

Fit model to dataset
ggml_opt_eval

Evaluate model
ggml_opt_dataset_weights

Get dataset per-datapoint weights tensor
ggml_opt_init

Initialize optimizer context
ggml_opt_inputs

Get inputs tensor from optimizer context
ggml_opt_loss_type_mean

Loss type: Mean
ggml_opt_loss_type_cross_entropy

Loss type: Cross Entropy
ggml_opt_loss_type_mse

Loss type: Mean Squared Error
ggml_opt_optimizer_name

Get optimizer name
ggml_opt_loss

Get loss tensor from optimizer context
ggml_opt_loss_type_sum

Loss type: Sum
ggml_opt_labels

Get labels tensor from optimizer context
ggml_opt_ncorrect

Get number of correct predictions tensor
ggml_opt_loss_type_weighted_mse

Loss type: Weighted Mean Squared Error
ggml_opt_pred

Get predictions tensor from optimizer context
ggml_opt_optimizer_type_adamw

Optimizer type: AdamW
ggml_opt_reset

Reset optimizer context
ggml_opt_outputs

Get outputs tensor from optimizer context
ggml_opt_prepare_alloc

Prepare allocation for non-static graphs
ggml_opt_result_init

Initialize optimization result
ggml_opt_result_free

Free optimization result
ggml_opt_optimizer_type_sgd

Optimizer type: SGD
ggml_opt_result_loss

Get loss from result
ggml_opt_result_accuracy

Get accuracy from result
ggml_opt_result_reset

Reset optimization result
ggml_pad_reflect_1d

Reflective 1D Padding (Graph)
ggml_opt_result_pred

Get predictions from result
ggml_opt_set_lr

Set learning rate in optimizer context
ggml_pad

Pad Tensor with Zeros (Graph)
ggml_opt_result_ndata

Get number of datapoints from result
ggml_pool_1d

1D Pooling (Graph)
ggml_opt_static_graphs

Check if using static graphs
ggml_out_prod

Outer Product (Graph)
ggml_permute

Permute Tensor Dimensions (Graph)
ggml_pp_dp_forward

Pipeline + data parallel forward pass (PP x DP)
ggml_pool_2d

2D Pooling (Graph)
ggml_predict_classes

Predict Classes from a Trained Model
ggml_quant_block_info

Get Quantization Block Info
ggml_print_mem_status

Print Context Memory Status
ggml_pop_layer

Remove the Last Layer from a Sequential Model
ggml_predict.ggml_functional_model

Get Predictions from a Trained Model
ggml_pp_forward

Pipeline-parallel forward pass across per-device layer stages
ggml_quantize_chunk

Quantize Data Chunk
ggml_print_objects

Print Objects in Context
ggml_quantize_free

Free Quantization Resources
ggml_repeat_back

Repeat Backward (Graph)
ggml_relu_inplace

ReLU Activation In-place (Graph)
ggml_reglu

ReGLU (ReLU Gated Linear Unit) (Graph)
ggml_repeat

Repeat (Graph)
ggml_quantize_init

Initialize Quantization Tables
ggml_relu

ReLU Activation (Graph)
ggml_quantize_requires_imatrix

Check if Quantization Requires Importance Matrix
ggml_reglu_split

ReGLU Split (Graph)
ggml_reset

Reset GGML Context
ggml_rms_norm_inplace

RMS Normalization In-place (Graph)
ggml_reshape_3d

Reshape to 3D (Graph)
ggml_reshape_1d

Reshape to 1D (Graph)
ggml_rms_norm_back

RMS Norm Backward (Graph)
ggml_rms_norm

RMS Normalization (Graph)
ggml_rope

Rotary Position Embedding (Graph)
ggml_reshape_2d

Reshape to 2D (Graph)
ggml_reshape_4d

Reshape to 4D (Graph)
ggml_result

Construct a single-cell result
ggml_roll

Roll (Graph)
ggml_save_model

Save a Full Model (Architecture + Weights)
ggml_rope_multi

Multi-RoPE for Vision Models (Graph)
ggml_round_inplace

Round In-place (Graph)
ggml_rope_ext_back

RoPE Extended Backward (Graph)
ggml_run

Run a single-cell task on the GGML backend
ggml_rope_inplace

Rotary Position Embedding In-place (Graph)
ggml_rope_ext_inplace

Extended RoPE Inplace (Graph)
ggml_rope_ext

Extended RoPE with Frequency Scaling (Graph)
ggml_rope_multi_inplace

Multi-RoPE Inplace (Graph)
ggml_round

Round (Graph)
ggml_set_1d

Set 1D Tensor Region (Graph)
ggml_set_abort_callback_default

Restore Default Abort Behavior
ggml_schedule_reduce_on_plateau

Reduce on plateau LR scheduler
ggml_set_2d

Set 2D Tensor Region (Graph)
ggml_schedule_step_decay

Step decay LR scheduler
ggml_schedule_cosine_decay

Cosine annealing LR scheduler
ggml_scale

Scale (Graph)
ggml_scale_inplace

Scale Tensor In-place (Graph)
ggml_set_i32

Set I32 Data
ggml_set_f32_nd

Set Single Float Value by N-D Index
ggml_set_f32

Set F32 data
ggml_set_n_threads

Set Number of Threads
ggml_set_name

Set Tensor Name
ggml_set_abort_callback_r

Enable R-compatible Abort Handling
ggml_save_weights

Save Model Weights to File
ggml_set

Set Tensor Region (Graph)
ggml_set_omp_threads

Set OpenMP Thread Count
ggml_set_no_alloc

Set No Allocation Mode
ggml_set_input

Mark Tensor as Input
ggml_set_i32_nd

Set Single Int32 Value by N-D Index
ggml_set_op_params_i32

Set Integer Op Parameter
ggml_set_zero

Set Tensor to Zero
ggml_set_op_params

Set Tensor Operation Parameters
ggml_set_output

Mark Tensor as Output
ggml_sigmoid_inplace

Sigmoid Activation In-place (Graph)
ggml_sigmoid

Sigmoid Activation (Graph)
ggml_soft_max

Softmax (Graph)
ggml_set_seed

Set the random seed for reproducible ggmlR runs
ggml_sgn

Sign Function (Graph)
ggml_silu

SiLU Activation (Graph)
ggml_soft_max_ext_back_inplace

Extended Softmax Backward Inplace (Graph)
ggml_silu_inplace

SiLU Activation In-place (Graph)
ggml_soft_max_ext_back

Softmax Backward Extended (Graph)
ggml_sin

Sine (Graph)
ggml_soft_max_inplace

Softmax In-place (Graph)
ggml_silu_back

SiLU Backward (Graph)
ggml_soft_max_ext_inplace

Extended Softmax Inplace (Graph)
ggml_set_op_params_f32

Set Float Op Parameter
ggml_soft_max_ext

Extended Softmax with Masking and Scaling (Graph)
ggml_set_param

Set Tensor as Trainable Parameter
ggml_sqrt_inplace

Square Root In-place (Graph)
ggml_sqr

Square (Graph)
ggml_step

Step Function (Graph)
ggml_sqrt

Square Root (Graph)
ggml_softplus_inplace

Softplus Activation In-place (Graph)
ggml_sub

Element-wise Subtraction (Graph)
ggml_sub_inplace

Element-wise Subtraction In-place (Graph)
ggml_sqr_inplace

Square In-place (Graph)
ggml_softplus

Softplus Activation (Graph)
ggml_sum

Sum (Graph)
ggml_swiglu_split

SwiGLU Split (Graph)
ggml_tcrossprod

GPU transposed cross product (drop-in for tcrossprod)
ggml_tanh_inplace

Tanh Activation In-place (Graph)
ggml_sum_rows

Sum Rows (Graph)
ggml_tensor_copy

Copy Tensor Data
ggml_task

Construct a single-cell compute task
ggml_tanh

Tanh Activation (Graph)
ggml_tensor_num

Count Tensors in Context
ggml_swiglu

SwiGLU (Swish/SiLU Gated Linear Unit) (Graph)
ggml_tensor_nb

Get Tensor Strides (nb)
ggml_tensor_overhead

Get Tensor Overhead
ggml_time_ms

Get Time in Milliseconds
ggml_tensor_type

Get Tensor Type
ggml_timestep_embedding

Timestep Embedding (Graph Operation)
ggml_time_init

Initialize GGML Timer
ggml_time_us

Get Time in Microseconds
ggml_test

Test GGML
ggml_tensor_shape

Get Tensor Shape
ggml_tensor_set_f32_scalar

Fill Tensor with Scalar
ggml_top_k

Top-K Indices (Graph)
ggml_training_history

Training history of a fitted ggml model
ggml_unfreeze_weights

Unfreeze Layer Weights
ggml_type_size

Get Type Size in Bytes
ggml_tp_dp_forward

TPxDP hybrid matrix multiply across replicas of Vulkan device groups
ggml_type_sizef

Get Type Size as Float
ggml_transpose

Transpose (Graph)
ggml_upscale

Upscale Tensor (Graph)
ggml_unary_op_name

Get Unary Operation Name
ggml_unmarshal_model

Unmarshal a ggmlR model from an in-memory container
ggml_type_name

Get Type Name
ggml_view_3d

3D View with Byte Offset (Graph)
ggml_vulkan_backend_name

Get Vulkan backend name
ggml_view_tensor

View Tensor
ggml_vulkan_device_caps

Get Vulkan device capabilities
ggml_vulkan_available

Check if Vulkan support is available
ggml_view_2d

2D View with Byte Offset (Graph)
ggml_version

Get GGML version
ggml_view_1d

1D View with Byte Offset (Graph)
ggml_view_4d

4D View with Byte Offset (Graph)
ggml_used_mem

Get Used Memory
ggml_vulkan_list_devices

List all Vulkan devices
ggml_vulkan_is_backend

Check if backend is Vulkan
ggml_vulkan_p2p_selftest

Opaque-fd device-to-device P2P self-test
ggml_vulkan_free

Free Vulkan backend
ggml_vulkan_device_count

Get number of Vulkan devices
ggml_vulkan_hard_exit_available

Is the Vulkan hard-exit path compiled in?
ggml_vulkan_init

Initialize Vulkan backend
ggml_vulkan_device_memory

Get Vulkan device memory
ggml_vulkan_device_description

Get Vulkan device description
ggml_vulkan_device_groups

Probe Vulkan device groups (NVLink / multi-GPU peer access)
ggml_vulkan_split_mul_mat

Tensor-parallel matrix multiply across Vulkan devices
ggml_vulkan_stage_handoff

Hand a pipeline stage's activation tensor to the next stage's input
ggml_vulkan_split_row_ranges

Compute tensor-parallel row-split ranges
ggml_vulkan_status

Print Vulkan status
ggml_win_part

Window Partition (Graph)
ggml_with_temp_ctx

Execute with Temporary Context
ggml_win_unpart

Window Un-partition (Graph)
ggml_vulkan_split_buffer_type

Create a Vulkan tensor-split buffer type
ggml_vulkan_shutdown

Explicitly tear down the Vulkan instance and devices
ggmlr_parsnip_fit_classif

parsnip ggml engine: classification fit
gguf_tensor_data

Extract Tensor Data
iq2xs_free_impl

Free IQ2 Quantization Tables
gguf_load

Load a GGUF File
glance.ggmlr_parsnip_model

One-row summary of a fitted ggml parsnip model
gguf_metadata

Get GGUF Metadata
iq2xs_init_impl

Initialize IQ2 Quantization Tables
gguf_tensor_info

Get Tensor Info
gguf_free

Free GGUF Resources
ggmlr_parsnip_fit_regr

parsnip ggml engine: regression fit
gguf_tensor_names

List Tensor Names in a GGUF File
nn_build_dense

Build dense forward pass
iq3xs_free_impl

Free IQ3 Quantization Tables
lr_scheduler_step

Step-decay learning rate scheduler
lr_scheduler_cosine

Cosine-annealing learning rate scheduler
iq3xs_init_impl

Initialize IQ3 Quantization Tables
nn_build_batch_norm

Build batch_norm forward pass
nn_apply_activation

Apply activation function
nn_build_conv_1d

Build conv_1d forward pass
is_ag_tensor

Check if object is an ag_tensor
nn_build_conv_2d

Build conv_2d forward pass
nn_build_gru

Build GRU forward pass for Sequential model
nn_build_global_max_pooling_2d

Build global_max_pooling_2d forward pass
nn_build_layer

Build a layer's forward pass
nn_build_dropout

Build dropout forward pass
nn_build_flatten

Build flatten forward pass
nn_init_recurrent_uniform

Initialize recurrent weight tensor with small deterministic values
nn_build_functional_node

Build a single ggml tensor for one functional node
nn_init_zeros

Initialize bias tensor to zeros
nn_build_functional_graph

Build ggml computation graph for a functional model
nn_build_graph

Build computation graph with allocated weights and inputs
nn_build_lstm

Build LSTM forward pass for Sequential model
nn_gru_step

Build one GRU step
nn_build_global_average_pooling_2d

Build global_average_pooling_2d forward pass
nn_init_glorot_uniform

Initialize weight tensor with Glorot uniform distribution
nn_count_layer_params

Count parameters for a single layer
nn_functional_output_shape

Infer output shape of a functional node given its parent shapes
nn_infer_shapes

Infer shapes for all layers in model
nn_build_embedding

Build embedding forward pass
nn_init_he_uniform

Initialize weight tensor with He uniform distribution
nn_build_max_pooling_2d

Build max_pooling_2d forward pass
plot.ggml_history

Plot training history
optimizer_sgd

Create an SGD optimizer
nn_topo_sort

Topologically sort nodes reachable from output nodes
onnx_device_info

ONNX model device/scheduler diagnostics
onnx_run

Run ONNX model inference
onnx_inputs

List ONNX model inputs
onnx_load

Load an ONNX model
nn_lstm_step

Build one LSTM step
onnx_summary

ONNX model summary
optimizer_adam

Create an Adam optimizer
print.ggml_sequential_model

Print method for ggml_sequential_model
print.ggml_history

Print method for ggml_history
print.ag_tensor

Print method for ag_tensor
print.onnx_model

Print ONNX model summary
print.ggml_functional_model

Print method for ggml_functional_model
predict.ggml_sequential_model

Predict with a Trained Model
quantize_iq2_xxs

Quantize Data (IQ)
quantize_nvfp4

Quantize Data (NVFP4)
quantize_q1_0

Quantize Data (Q1_0)
quantize_mxfp4

Quantize Data (MXFP4)
quantize_row_iq3_xxs_ref

Quantize Row Reference (IQ)
quantize_row_q2_K_ref

Quantize Row Reference (K-quants)
quantize_tq1_0

Quantize Data (Ternary)
quantize_row_q4_0_ref

Quantize Row Reference (Basic)
quantize_q4_0

Quantize Data (Q4_0)
quantize_q2_K

Quantize Data (K-quants)
quantize_row_mxfp4_ref

Quantize Row Reference (MXFP4)
reexports

Objects exported from other packages
quantize_row_tq1_0_ref

Quantize Row Reference (Ternary)
slice_first_dim

Slice an Array or Matrix Along Its First Dimension
summary.ggml_sequential_model

Summary method for ggml_sequential_model
with_grad_tape

Run code with gradient tape enabled
tidy.ggmlr_parsnip_model

Tidy a fitted ggml parsnip model into a per-layer table
rope_types

RoPE Mode Constants