| Title: | Explicit CPU, CUDA, and Metal Distances for Projected Points |
|---|---|
| Description: | Computes dense Euclidean distance matrices and sparse within-radius point matches for Cartesian two-column coordinates and projected 'sf' POINT geometries. A portable double-precision CPU backend is always available; optional NVIDIA CUDA and Apple Metal backends must be requested explicitly at build time and at each call. |
| Authors: | Egor Kotov [aut, cre, cph] |
| Maintainer: | Egor Kotov <kotov.egor@gmail.com> |
| License: | MIT + file LICENSE |
| Version: | 0.1.0 |
| Built: | 2026-09-27 16:08:12 UTC |
| Source: | https://github.com/e-kotov/sfgpu |
Reports whether each backend was compiled into the installed package and
whether it is available at runtime. A CPU-only build does not link to GPU
runtimes. This function reports capability; it does not select a backend for
sfgpu_distance().
sfgpu_backends()sfgpu_backends()
A named list with entries cpu, cuda, and metal. Each entry is a list
containing logical scalar fields compiled and available, and
character scalar fields device and reason. The character fields
are NA_character_ when not applicable. available reports runtime
availability; a GPU build can be compiled but have no usable device.
sfgpu_distance
Computes Cartesian Euclidean distances between two coordinate collections.
Matrix coordinates use common caller-selected units and carry no CRS
interpretation. Spatial inputs must both be spatial objects (either sf
or sfc), with equal known projected CRSs and only nonempty XY point geometries. The
function does not transform coordinates or drop extra dimensions. Empty
collections are valid. Geographic or unknown CRSs, mismatched CRSs, mixed
input kinds, missing or non-finite coordinates, extra dimensions, unsupported
geometry types, and empty individual points are errors.
Results are binary64 doubles. CPU and CUDA use double-precision hypot-style
arithmetic. Metal uses exact scaled-integer encoding and wide integer distance
arithmetic. Pairs that cannot be encoded exactly, approach a rounding boundary,
or have a result exponent outside [-900, 900] are corrected using CPU hypot.
The corrected fraction depends on the input and tile size and can reach 100%.
A missing Metal device or command failure still errors. The
max_output_bytes limit applies to result payload only; tiling bounds
execution buffers but does not make the returned matrix out-of-core.
sfgpu_distance( x, y = x, backend = c("cpu", "cuda", "metal"), max_output_bytes = 2^53, tile_bytes = 64 * 1024^2 )sfgpu_distance( x, y = x, backend = c("cpu", "cuda", "metal"), max_output_bytes = 2^53, tile_bytes = 64 * 1024^2 )
x |
A numeric two-column matrix of Cartesian coordinates, or an
|
y |
A two-column numeric matrix or spatial input matching the input
category of |
backend |
Backend to use: |
max_output_bytes |
Inclusive cap on the dense double result payload in
bytes. The default is |
tile_bytes |
Inclusive byte budget for both coordinate input tiles and the output tile. The default is 64 MiB; at least 40 bytes are needed for one pair. |
The default installation is CPU-only. CUDA and Metal are optional build
features. Use sfgpu_backends() to inspect whether each backend is
compiled and available at runtime. A GPU-enabled build may still have no usable
device.
A numeric matrix with nrow(x) rows and nrow(y) columns. Input
matrix dimnames are propagated. For spatial inputs, the result is a distance
matrix carrying units appropriate to the CRS. If y is omitted, all
pairwise distances within x are returned.
sf::st_distance, sfgpu_backends
x <- rbind(c(0, 0), c(3, 4)) y <- rbind(c(0, 0), c(5, 4)) sfgpu_distance(x, y) sfgpu_distance(x) if (sfgpu_backends()$cuda$available) { sfgpu_distance(x, y, backend = "cuda") }x <- rbind(c(0, 0), c(3, 4)) y <- rbind(c(0, 0), c(5, 4)) sfgpu_distance(x, y) sfgpu_distance(x) if (sfgpu_backends()$cuda$available) { sfgpu_distance(x, y, backend = "cuda") }
On Windows, standard binary builds of sfgpu (such as those from R-universe)
are built without NVIDIA CUDA support because standard Rtools uses MinGW GCC,
whereas CUDA requires MSVC. sfgpu_install_cuda() downloads the pre-compiled
companion DLL from GitHub Releases into the user data directory, verifies its
SHA-256 checksum against the package manifest, and dynamically loads it.
On Linux, CUDA acceleration is enabled at install time via R CMD INSTALL --configure-args=--enable-cuda ..
On macOS, Apple Metal acceleration is compiled automatically on Apple Silicon.
sfgpu_install_cuda(force = FALSE, quiet = FALSE) install_cuda(force = FALSE, quiet = FALSE)sfgpu_install_cuda(force = FALSE, quiet = FALSE) install_cuda(force = FALSE, quiet = FALSE)
force |
Logical; if |
quiet |
Logical; if |
Invisibly returns the destination file path of the installed DLL.
sfgpu_backends
Finds all pairs of points at Euclidean distance less than or equal to the
specified radius. Matrix inputs use common caller-selected coordinate units.
Spatial inputs must both be sf or sfc, have the same known
projected CRS, and contain only nonempty XY points. The function does not
transform coordinates. Empty collections are valid. Geographic or unknown
CRSs, mismatched CRSs, mixed input kinds, missing or non-finite coordinates,
extra dimensions, unsupported geometry types, and empty individual points are
errors. The function returns sparse indices and does not allocate the full
pairwise distance matrix. An output cap failure errors without returning a
partial result.
sfgpu_within_distance( x, y = x, dist, backend = c("cpu", "cuda", "metal"), max_output_bytes = 2^53, tile_bytes = 64 * 1024^2 )sfgpu_within_distance( x, y = x, dist, backend = c("cpu", "cuda", "metal"), max_output_bytes = 2^53, tile_bytes = 64 * 1024^2 )
x |
A numeric two-column matrix of Cartesian coordinates, or an
|
y |
A two-column numeric matrix or spatial input matching the input
category of |
dist |
One finite, non-negative numeric radius. Numeric values use
coordinate units for matrices and CRS units for spatial inputs. Spatial
inputs also accept one |
backend |
Backend to use: |
max_output_bytes |
Inclusive cap on the output accounting: eight bytes
per |
tile_bytes |
Inclusive budget for the GPU execution tile, including inputs, output, and scratch. The default is 64 MiB; at least 49 bytes are needed for one candidate pair. |
The default installation is CPU-only. CUDA and Metal are optional build
features. Use sfgpu_backends() to inspect whether each backend is
compiled and available at runtime. Distances are inclusive at the radius
boundary. A zero radius includes all coordinate duplicates, including the
point at the same row position when y is omitted.
The output byte accounting includes eight bytes per list slot and four bytes
per returned integer index, but excludes R object headers and temporary
collection workspace. It is not a cap on total process memory. For spatial
inputs, a numeric radius is interpreted in CRS units; a scalar units
radius is converted to CRS units. For matrix inputs, a units radius is
invalid.
Membership is decided on the represented binary64 coordinates by the inclusive
CPU double-precision predicate hypot(dx, dy) <= dist. When the sorted
y index and bounded query/task/output workspace fit tile_bytes,
CUDA and Metal sort the points on the host, retain original indices, transfer
the index to the device, binary-search x-coordinate ranges, filter by y
coordinate, and compact candidates before the host applies that final
predicate. Metal stores ordered binary64 keys. If the index workspace does not
fit, either GPU uses its bounded tiled rectangle scan; a 49-byte tile selects
this path. CUDA compacts at most 1,048,576 candidates per wave and Metal at most
65,536 per command. The CPU backend sorts and indexes the y points by x
coordinate to prune candidates before applying the same predicate. A tiled GPU
scan can examine nrow(x) * nrow(y) pairs, though no backend creates the
dense distance matrix. CUDA, Metal, and CPU have workload-dependent costs; no
speed advantage is guaranteed, and CPU remains the default.
A list with one integer vector per row of x. Each vector contains the
increasing, one-based indices of rows in y whose Euclidean distance is
less than or equal to dist. Equal-coordinate duplicates are included.
The list is named with the row names of x, when present.
sfgpu_distance, sf::st_is_within_distance,
sfgpu_backends
x <- rbind(c(0, 0), c(3, 4)) y <- rbind(c(0, 0), c(5, 4)) sfgpu_within_distance(x, y, dist = 2) sfgpu_within_distance(x, dist = 0) if (sfgpu_backends()$cuda$available) { sfgpu_within_distance(x, y, dist = 5, backend = "cuda") }x <- rbind(c(0, 0), c(3, 4)) y <- rbind(c(0, 0), c(5, 4)) sfgpu_within_distance(x, y, dist = 2) sfgpu_within_distance(x, dist = 0) if (sfgpu_backends()$cuda$available) { sfgpu_within_distance(x, y, dist = 5, backend = "cuda") }