skills/optimize-for-gpu/references/decision_framework.md
Each RAPIDS/GPU library, the CPU library it replaces, what it is good at, and when it is the wrong choice — CuPy, Numba CUDA, Warp, cuDF, cuML, cuGraph, KvikIO, cuxfilter, cuCIM, cuVS, cuSpatial, and RAFT — plus guidance on combining them.
Choose the right tool based on what the user's code actually does. Read the appropriate reference file(s) before writing any GPU code.
First decide whether a port is justified: establish an end-to-end baseline, estimate peak device memory including temporaries, and identify transfer and fallback boundaries. Prefer an accelerator or backend mode before a native rewrite, and prefer a maintained library operation before a custom kernel. Validate output semantics and use synchronized GPU timing on representative data.
Read: references/cupy.md
Use CuPy when the user's code is primarily:
CuPy wraps NVIDIA's optimized libraries (cuBLAS, cuFFT, cuSOLVER, cuSPARSE, cuRAND) so standard operations are already tuned. Most NumPy code works by changing import numpy as np to import cupy as cp.
Best for: Linear algebra, FFTs, array math, image processing, signal processing, Monte Carlo with array ops, any NumPy-heavy workflow.
Read: references/numba.md
Use this path when the user needs:
For new projects, evaluate Numba-CUDA-MLIR, where NVIDIA is doing new feature development.
Use the established numba-cuda package for existing numba.cuda code, compatibility, or features
not yet available in the MLIR implementation; it is in maintenance mode through the CUDA 13
lifetime. Do not invest in custom kernels until profiling rules out CuPy or another tuned library.
Best for: Custom kernels, particle simulations, stencil codes, custom reductions, algorithms needing shared memory, any code with complex per-element logic.
Read: references/warp.md
Use Warp when the user's code is primarily:
Warp JIT-compiles @wp.kernel Python functions to CUDA, with built-in types for spatial computing
(vec3, mat33, quat, transform) and primitives for geometry queries (Mesh, Volume, HashGrid, BVH).
Warp can generate adjoint kernels for differentiable programs. The higher-level warp.sim module
was removed in Warp 1.10; use the separate Newton engine for maintained high-level rigid-body,
robotics, and simulation-environment APIs, and use Warp for custom kernels and domain primitives.
Best for: Physics simulation, mesh ray casting, particle systems, differentiable rendering, robotics kinematics, SDF operations, any workload combining spatial data structures with GPU compute.
Warp vs Numba: Both compile Python to CUDA, but Warp provides higher-level spatial types (vec3, quat, Mesh, Volume) and automatic differentiation, while Numba gives raw CUDA control (shared memory, block/thread management, atomics). Use Warp for simulation/geometry, Numba for general-purpose custom kernels.
Read: references/cudf.md
Use cuDF when the user's code is primarily:
cuDF's cudf.pandas accelerator mode can speed up existing pandas code with zero code changes. For maximum performance, use the native cuDF API.
Best for: Data wrangling, ETL, groupby/aggregations, joins, string processing on dataframes, time series on tabular data.
Read: references/cuml.md
Use cuML when the user's code is primarily:
Start with cuML's cuml.accel accelerator mode when compatibility permits. Move to the native
cuML API for unsupported estimators, explicit output control, or a measured performance reason.
Benchmark the user's estimator, dimensions, and end-to-end pipeline rather than relying on headline
speedup ranges.
Best for: Classification, regression, clustering, dimensionality reduction, preprocessing pipelines, model inference, any scikit-learn-heavy workflow.
Read: references/cugraph.md
Use cuGraph when the user's code is primarily:
Start with the nx-cugraph backend and inspect fallback behavior. Move to the native cuGraph API
with cuDF edge lists for unsupported operations or a measured performance reason. Include graph
construction and host-device conversion in end-to-end benchmarks.
Best for: PageRank, betweenness centrality, community detection (Louvain, Leiden), BFS/SSSP, connected components, link prediction, graph neural network sampling, any NetworkX-heavy workflow.
Read: references/kvikio.md
Use KvikIO when the user's code is primarily:
KvikIO provides Python bindings to NVIDIA cuFile, enabling GPUDirect Storage (GDS) — data flows directly between NVMe storage and GPU memory, bypassing CPU memory entirely. When GDS isn't available, it falls back to POSIX IO transparently. It handles both host and device data seamlessly.
Best for: Loading binary data to GPU, saving GPU arrays to disk, reading from S3/HTTP directly to GPU, Zarr arrays on GPU, replacing numpy.fromfile() → cupy patterns, any IO-heavy GPU pipeline where data staging through CPU memory is a bottleneck.
Note: For tabular formats (CSV, Parquet, JSON), use cuDF's built-in readers instead — they're optimized for those formats. KvikIO is for raw binary data and remote file access.
Read: references/cuxfilter.md
Project status: sunset. RAPIDS 26.06 was cuxfilter's final release (RSN 60). Reach for cuxfilter only when the user already uses it or explicitly requests it. For new dashboards, prefer cuDF for GPU data prep combined with HoloViews/hvPlot/Datashader linked selections, served with Panel, Plotly Dash, Streamlit, or Bokeh.
Maintain cuxfilter when an existing application needs:
cuxfilter leverages cuDF for all data operations on the GPU — filtering, groupby, and aggregation happen entirely on the GPU, with only rendering results sent to the browser. It integrates Bokeh, Datashader (for millions of points), Deck.gl (for maps), and Panel widgets.
Best for: Existing 26.06 applications that cannot yet migrate. Do not start a new dependency on an unmaintained dashboard framework.
Read: references/cucim.md
Use cuCIM when the user's code is primarily:
cuCIM's cucim.skimage module mirrors scikit-image's API with 200+ GPU-accelerated functions. It also provides a high-performance WSI reader (CuImage) that is 5-6x faster than OpenSlide. All functions work on CuPy arrays — zero-copy, all on GPU.
Best for: Filtering (Gaussian, Sobel, Frangi), morphology, thresholding, connected component labeling, region properties, color space conversion, image registration, denoising, whole-slide image processing, DL preprocessing pipelines.
Read: references/cuvs.md
Use cuVS when the user's code is primarily:
cuVS provides GPU-accelerated ANN index types (CAGRA, IVF-Flat, IVF-PQ, brute force) plus HNSW for CPU serving from GPU-built indexes. It powers the GPU backends of Faiss, Milvus, and Lucene. Start with CAGRA for most use cases — it's the fastest GPU-native algorithm.
Best for: Embedding search, RAG retrieval, recommender systems, image/text/audio similarity search, k-NN graph construction, any nearest-neighbor workload on 10K+ vectors.
Read: references/cuspatial.md
Project status: archived. The cuSpatial repository has been read-only since July 2025; the final release is 25.04, which pins cudf-cu12==25.4.* and therefore conflicts with current RAPIDS releases in the same environment. No official successor exists. Recommend it only in a dedicated legacy environment; otherwise keep geometry operations on GeoPandas/Shapely (CPU) and accelerate the tabular parts of the workflow with cuDF.
Maintain cuSpatial when an isolated 25.04 environment already uses:
cuSpatial provides GPU-accelerated GeoSeries and GeoDataFrame types compatible with GeoPandas, plus spatial join, distance, and trajectory functions. Convert from GeoPandas with cuspatial.from_geopandas().
Best for: Existing pipelines pinned to the 25.04 stack. Do not present it as a current GeoPandas replacement or combine it with current RAPIDS packages.
Read: references/raft.md
Use RAFT when the user needs:
scipy.sparse.linalg.eigsh replacement)device_ndarray)raft-dask)RAFT provides the foundational primitives that cuML and cuGraph are built on. Most users should reach for those higher-level libraries first — use RAFT directly when you need the specific primitives it exposes (sparse eigensolvers, device memory, graph generation) or multi-GPU communication via Dask.
Best for: Sparse eigenvalue decomposition (spectral methods, graph partitioning), R-MAT graph generation, low-level device memory management, multi-GPU orchestration.
Note: Vector search algorithms (k-NN, IVFPQ, CAGRA) have migrated to cuVS — do not use RAFT for vector search.
Many real workloads benefit from using multiple libraries together. They interoperate via the CUDA Array Interface — zero-copy data sharing between CuPy, Numba, Warp, cuDF, cuML, cuGraph, cuVS, cuCIM, cuSpatial, KvikIO, PyTorch, JAX, and other GPU libraries.
Common combinations: