Assists with converting a non-aggregating Apache Spark UDF to a native CUDA RapidsUDF using JNI and libcudf. This is step 2 of 3 in the UDF conversion workflow (udf-gen-test -> udf-convert-to-cuda -> udf-benchmark). Use this skill when you have a CPU UDF with a unit test and need to convert it to a native CUDA implementation. Prefer udf-convert-to-cudf unless a CUDA implementation is necessary for performance or correctness, or if requested by the user.
npx skills add https://github.com/NVIDIA/cudf-spark --skill udf-convert-to-cuda
cuda-native-udf Maven profileBefore making any edits, create a visible TODO checklist for every workflow step in this skill and keep it updated. Do not produce a final answer until every required checklist item is marked complete.
udf-gen-test) with a passing unit testgit, and unzipDerive <CamelName> and <snake_name> from the UDF class name.
> Note: Commands require access to /tmp (Spark temp storage) and /dev (GPU device). If commands fail due to sandbox restrictions, re-run them unsandboxed.
Copy this skill's CUDA templates into the existing project:
cp -r templates/cuda/* <project_root>/<CamelName>/
chmod +x <project_root>/<CamelName>/native/scripts/extract-cudf-libs.sh
The udf-gen-test Maven template already contains an inactive cuda-native-udf profile. The native profile is activated only when you build with -Pcuda-native-udf.
Read NATIVE_BUILD_ENV.md before changing build configuration.
Read examples/ for native RapidsUDF examples.
Use src/main/java/com/udf/PlaceholderUDFNameNativeRapidsUDF.java as a starting point:
<CamelName>NativeRapidsUDF.java.<CamelName>NativeRapidsUDF.evaluateColumnar to validate column count/types and call the native method.cosineSimilarityNative.The project joint-compiles Java, so keep this Java wrapper under src/main/java/com/udf/ and register it from the Scala test. JNI can be used from Scala, but the Java wrapper keeps native symbol names and examples simpler.
If the Java wrapper's CPU fallback needs to call a Scala object, direct references can fail before scala-maven-plugin compiles the Scala classes; use reflection in the row-by-row fallback only, and keep evaluateColumnar on the normal JNI path.
Read JNI_CUDA_GUIDE.md for the evaluateColumnar contract, type mapping, pointer ownership, NativeDepsLoader, and native memory rules.
Note: memory allocations must use the active RMM resource; avoid direct usage of ad hoc CUDA or Thrust allocators.
Rename and edit:
native/src/main/cpp/src/PlaceholderUDFNameJni.cppnative/src/main/cpp/src/placeholder_udf_name.cunative/src/main/cpp/src/placeholder_udf_name.hppUpdate native/src/main/cpp/CMakeLists.txt SOURCE_FILES to match the renamed files. If libcudf ABI/version compatibility is unclear, defer to the user.
Read JNI_CUDA_GUIDE.md before writing kernels.
Verify cuDF header names before choosing includes or APIs. After dependency extraction, the active header tree will be cloned under target/cudf-repo/cpp/include.
copyToHost() or native methods that copy inputs from GPU to CPU. This defeats the purpose of GPU accelerationThe native Maven profile uses the RAPIDS dependency already declared in pom.xml.
mvn package -Pcuda-native-udf -DskipTests
To use the Docker build environment:
docker build -t cuda-udf-build .
mkdir -p "$HOME/.m2"
docker run --rm --gpus all \
--user "$(id -u):$(id -g)" \
-e HOME=/workspace \
-v "$PWD":/workspace \
-v "$HOME/.m2":/workspace/.m2 \
-w /workspace \
cuda-udf-build \
-c "mvn -B -Dmaven.repo.local=/workspace/.m2/repository package -Pcuda-native-udf -DskipTests -Dnative.build.path=/workspace/target/native-build-docker"
If the build fails while resolving cuDF headers or RAPIDS CMake, check network access and the generated cudf.git.branch / rapids.cmake.branch properties. These properties may contain either a branch or a tag.
Fill in the target-specific TODOs in src/test/scala/com/udf/CudfComparisonTest.scala:
<CamelName>NativeRapidsUDF as the GPU implementationRun:
mvn test -Dsuites=com.udf.CudfComparisonTest -Pcuda-native-udf
To run the tests inside the Docker build environment:
docker run --rm --gpus all \
--user "$(id -u):$(id -g)" \
-e HOME=/workspace \
-v "$PWD":/workspace \
-v "$HOME/.m2":/workspace/.m2 \
-v /etc/passwd:/etc/passwd:ro \
-v /etc/group:/etc/group:ro \
-w /workspace \
cuda-udf-build \
-c "mvn -B -Dmaven.repo.local=/workspace/.m2/repository test -Dsuites=com.udf.CudfComparisonTest -Pcuda-native-udf -Dnative.build.path=/workspace/target/native-build-docker -DskipCudfExtraction=true"
If tests fail, iterate on the Java bridge or native implementation.
Treat the unit test as the CPU behavior specification. Do not weaken or remove test cases silently.
TODO/NOTE in the implementation explaining the mismatch.If the user explicitly asked for the judge, a judge subagent, or a review agent, treat that as an explicit request for delegation: you MUST launch a separate subagent with model: inherit and instruct it to use the udf-judge-conversion skill. Ask it to review the UnitTest, CudfComparisonTest, Java bridge, and JNI/CUDA sources.
If the user did not request a judge/review agent, mark this step as skipped and continue to Step 7. If a required judge subagent is blocked by tool policy, stop and tell the user that explicit permission/instruction is needed.
If you run the judge, wait for it to complete and review its report. If the judge finds any issues, 1) fix the issues, 2) re-run the tests, and 3) re-run the judge subagent.
Review your own work to ensure:
copyToHost() or row-by-row GPU-to-CPU copying is used for computationTableDebug.get().debug(...)) remain in final outputUpon successful completion:
src/main/java/com/udf/<CamelName>NativeRapidsUDF.javanative/src/main/cpp/src/These outputs are required for Step 3: Benchmark.
Toolkit for interacting with and testing local web applications using Playwright. Supports verifying frontend functionality, debugging UI behavior, capturing browser screenshots, and viewing browser logs.
Use when implementation is complete, all tests pass, and you need to decide how to integrate the work - guides completion of development work by presenting structured options for merge, PR, or cleanup
Use when implementing any feature or bugfix, before writing implementation code
Use when encountering any bug, test failure, or unexpected behavior, before proposing fixes
Use when about to claim work is complete, fixed, or passing, before committing or creating PRs - requires running verification commands and confirming output before making any success claims; evidence before assertions always
Expert guidance for systematic backtesting of trading strategies. Use when developing, testing, stress-testing, or validating quantitative trading strategies. Covers "beating ideas to death" methodology, parameter robustness testing, slippage modeling, bias prevention, and interpreting backtest results. Applicable when user asks about backtesting, strategy validation, robustness testing, avoiding overfitting, or systematic trading development.
Cloud laboratory platform for automated protein testing and validation. Use when designing proteins and needing experimental validation including binding assays, expression testing, thermostability measurements, enzyme activity assays, or protein sequence optimization. Also use for submitting experiments via API, tracking experiment status, downloading results, optimizing protein sequences for better expression using computational tools (NetSolP, SoluProt, SolubleMPNN, ESM), or managing protein design workflows with wet-lab validation.
This skill should be used for time series machine learning tasks including classification, regression, clustering, forecasting, anomaly detection, segmentation, and similarity search. Use when working with temporal data, sequential patterns, or time-indexed observations requiring specialized algorithms beyond standard ML approaches. Particularly suited for univariate and multivariate time series analysis with scikit-learn compatible APIs.
Take nvidia/udf-convert-to-cuda from the repository into ~/.claude/skills for personal
use, or into .claude/skills inside a project.
The agent identifies a skill by the name field in its header. Two skills with the
same name cannot sit side by side — one of them will be ignored.
The instructions reference docker.
Without those the skill loads but fails at the first command.