---
title: "GPU Backend"
output: rmarkdown::html_vignette
vignette: >
%\VignetteIndexEntry{GPU Backend}
%\VignetteEngine{knitr::rmarkdown}
%\VignetteEncoding{UTF-8}
---
```{r setup, include=FALSE}
knitr::opts_chunk$set(collapse = TRUE, comment = "#>")
```
## Overview
The batch `Lowess` type can execute on a GPU-accelerated backend powered by
`wgpu` (Vulkan / Metal / DX12 / GLES on Android). The GPU backend reimplements almost the entire
LOWESS pipeline — local regression fitting, robustness iterations, interval
bounds, and cross-validation — as compute shaders, so all anchor points are
fitted in parallel.
> **Batch only.** GPU support applies to the batch `Lowess` type only.
> `StreamingLowess` and `OnlineLowess` remain CPU-only.
GPU acceleration is worth enabling for roughly 10K+ points. For smaller inputs
the CPU backend (optionally with `parallel = TRUE`) is typically faster once GPU
dispatch overhead is accounted for.
---
## Supported Features on GPU
| Feature | CPU | GPU |
| --- | --- | --- |
| Batch fitting | ✅ | ✅ |
| Streaming / Online | ✅ | ❌ |
| All weight / robustness / scaling methods | ✅ | ✅ |
| Confidence / prediction intervals | ✅ | ✅ |
| Cross-validation (k-fold, LOOCV) | ✅ | ✅ |
| Unsorted inputs and `return_sorted` | ✅ | ✅ |
| Custom per-observation weights | ✅ | ✅ |
GPU fits preserve Batch output ordering for unsorted input and `return_sorted`.
Custom per-observation weights are applied in GPU fit and cross-validation
candidate kernels.
Each compute pipeline binds only its own resources, so compatible adapter
limits depend on the largest individual GPU pass rather than all shader
bindings combined.
---
## Checking GPU Availability
```{r gpu_backend_1}
library(rfastlowess)
gpu_available()
```
Returns `TRUE` if the currently loaded library was built with GPU support,
`FALSE` otherwise.
---
## Installing GPU Support
GPU support is opt-in and not included in standard CRAN / R-universe builds.
Install it with a one-time download:
```{r gpu_backend_2, eval=FALSE}
library(rfastlowess)
install_gpu() # interactive — prompts for confirmation
install_gpu(yes = TRUE) # non-interactive
```
`install_gpu()` downloads a prebuilt GPU-enabled library from the
[`gpu-builds` release](https://github.com/thisisamirv/lowess-project/releases/tag/gpu-builds)
— a single perpetual release holding GPU artifacts for every version, so
individual version release pages stay uncluttered — and copies it into the
installed package's `libs/` directory.
Prebuilt R GPU libraries are built for Linux x86_64/ARM64 with glibc or
musl (Alpine), macOS x86_64/ARM64, and Windows x86_64/ARM64. The installer
selects a matching R architecture and the libc linked by R, and verifies GPU
support in the candidate library after confirmation. On Windows, the library
is installed in a versioned sidecar directory, leaving the loaded CPU DLL
untouched; after restarting R, the package activates the matching sidecar's
native routines. Other platforms require atomic replacement of the installed
library. Local candidates use the platform's canonical library filename,
regardless of their original filename extension.
Downloads must match the SHA-256 digest published in GitHub release metadata
before any native code is executed. Missing digests cause installation to
fail closed. Candidate probes have a 30-second timeout and require a matching
package version, native ABI contract, and registered argument counts. GPU
artifacts built before this contract was introduced must be rebuilt.
On Windows, a broken newest sidecar is skipped in favor of an older compatible
one. Activated sidecars remain mapped until R exits, so unloading the namespace
cannot invalidate finalizers belonging to live models. Probing isolates crashes
but is not a security sandbox: install only trusted local native libraries.
**Restart R after installation.**
Alternatively, build from source with GPU support:
```sh
make -f bindings/r/Makefile WITH_GPU=1
```
---
## Using the GPU Backend
Once GPU support is installed, pass `backend = "gpu"` to `Lowess()`:
```{r gpu_backend_3, eval=FALSE}
library(rfastlowess)
set.seed(42)
n <- 100000
x <- seq(0, 2 * pi, length.out = n)
y <- sin(x) + rnorm(n, sd = 0.3)
model <- Lowess(
fraction = 0.5,
iterations = 3,
backend = "gpu"
)
result <- fit(model, x, y)
```
---
## Performance Guidelines
| Scenario | Recommendation |
| --- | --- |
| n < 10K | CPU (`parallel = TRUE`) |
| n 10K–100K | Try both; GPU wins for larger fractions |
| n > 100K | GPU backend recommended |
| `fraction = 0.5`, n ≥ 50K | GPU outperforms CPU-parallel |
| `fraction = 0.1`, n ≥ 250K | GPU crossover point |
At n = 1M (`fraction = 0.5`, 3 iterations), the GPU backend is approximately
**6.6×** faster than CPU-parallel.
---
## Fallback Behaviour
If `backend = "gpu"` is requested but GPU support is not installed, an
informative error is raised pointing to `install_gpu()`. No silent fallback to
CPU occurs.
```{r session-info}
sessionInfo()
```