恒美微站
首页
关于我们
建站服务
主题模板
案例展示
资讯中心
联系我们
cuDF Java API 实战指南:Fat JAR 依赖管理、源码构建与多 GPU 行为解析
首页
资讯中心
/
cuDF Java API 实战指南:Fat JAR 依赖管理、源码构建与多 GPU 行为解析
cuDF Java API 实战指南:Fat JAR 依赖管理、源码构建与多 GPU 行为解析
发布时间:2026/9/25 3:54:41
数据分析数据工程机器学习【免费下载链接】cudfcuDF - GPU DataFrame Library项目地址https://gitcode.com/gh_mirrors/cu/cudf点击查看免费下载本文基于 cuDF 仓库 java/README.md 及其配套构建脚本、Maven 配置与 JNI 源码系统讲解 cuDF Java 绑定ai.rapids:cudf的依赖引入方式、classifier 命名规则、从源码构建 fat JAR 的完整流程含 Docker CI 构建、静态 libcudf 打包、PTDS 与 GDS 可选项并结合 CudaJni.cpp 等源码剖析 Java 进程在多 GPU 环境下的自动设备切换机制帮助你在 JVM 中稳定、可复现地跑起 GPU 数据处理。项目定位面向 JVM 的 GPU DataFrame 绑定cuDF 仓库的java/子目录提供 cuDF 的 Java 绑定其目标是让你在 Java 进程中直接处理 GPU 上的大规模数据。java/README.md 开宗明义这是一个正在进行中的项目在 1.0 发布之前部分 API 仍可能变化。这一点同样写进了 pom.xml 的项目描述cudfjniApache-2.0 许可。从工程结构看Java 绑定由三层组成纯 Java API 层位于 java/src/main/java/ai/rapids/cudf/核心类包括Table、ColumnVector、Scalar、Rmm内存管理器、CudaCUDA 运行时封装、各 IO 选项类CSVOptions、ParquetWriterOptions、ORCOptions等JNI 原生层位于 java/src/main/native/src/如CudaJni.cpp、RmmJni.cpp、ColumnVectorJni.cpp、TableJni.cpp构建后产出libcudfjni.soMaven 构建层java/pom.xml 在validate阶段用maven-antrun-plugin驱动 CMake 编译原生代码再用maven-resources-plugin把原生库打进 JAR形成一个自包含的fat JAR。多 GPU 系统下的行为单 GPU 约束与自动设备切换这是 java/README.md 中最值得注意的运行时约定cuDF 项目当前是每进程单 GPU的工作模型。CUDA 运行时会把默认 GPU 分配给每个新线程而 Java 进程天然是多线程环境——如果你在多线程环境中试图让 cuDF 使用非默认 GPU可能遇到资源泄漏、非法状态、崩溃和性能劣化等难以调试的问题。为规避这一问题Java cuDF API 会记住用于初始化 Rapids Memory ManagerRMM的设备并在需要时自动把线程的活跃设备设置为该设备cudf 调用完成后不会把设备设置还原。这与大多数 CUDA 库的行为不同如果你试图在同一个线程中混用这些库可能出现意想不到的行为。源码实现印证了这套机制。在 CudaJni.cpp 中namespace { /** The CUDA device that should be used by all threads using cudf */ int Cudf_device{cudaInvalidDeviceId}; thread_local int Thread_device cudaInvalidDeviceId; } namespace cudf { namespace jni { /** Set the device to use for cudf */ void set_cudf_device(int device) { Cudf_device device; } /** * If a cudf device has been specified then this ensures the calling thread * is using the same device. */ void auto_set_device(JNIEnv* env) { if (Cudf_device ! cudaInvalidDeviceId) { if (Thread_device ! Cudf_device) { cudaError_t cuda_status cudaSetDevice(Cudf_device); jni_cuda_check(env, cuda_status); Thread_device Cudf_device; } } }即一个进程级全局Cudf_device记录 RMM 初始化时选定的设备每个 JNI 入口在调用前先执行auto_set_device若当前线程的设备与其不一致就切换过去并用thread_local缓存避免重复调用cudaSetDevice。两个关键约束也能从源码中直接读出RMM 初始化后锁定设备。CudaJni.cpp#L143-L154 中setDevice的 JNI 实现一旦Cudf_device已被设定即 RMM 已初始化且你试图设置不同设备会直接抛出CudfException: Cannot change device after RMM init。设备锁定时机在 RMM 初始化。RmmJni.cpp#L913-L929 中Rmm.initDefaultCudaDevice先执行cudaFree(0)完成上下文初始化再通过cudaGetDevice取回当前设备并调用set_cudf_device(device_id)对应的cleanupDefaultCudaDevice会把Cudf_device重置为cudaInvalidDeviceId。Java 侧的对应入口是 Cuda.javaCuda.setDevice(int)的 Javadoc 明确提醒了CUDA_VISIBLE_DEVICES的语义——若你设置了CUDA_SET_VISIBLE_DEVICES1,0即仓库文档示例中的写法调用setDevice(0)实际拿到的是物理设备 1。因此先Cuda.setDevice再Rmm.initialize是选定目标 GPU 的唯一可靠顺序。Maven 依赖fat JAR 与 classifier 约定java/README.md 对依赖的说明是cuDF Java 是一个fat JAR二进制依赖libcudf.so、libcudfjni.so等直接打包在 JAR 内因此 JAR 只能在其编译目标的平台上运行。官方发布时 JAR 上不带 classifier且应能在大多数现代 CUDA 驱动上运行某些构建形态如从源码构建则可能出现带 classifier 的 JAR。基础依赖声明dependency groupIdai.rapids/groupId artifactIdcudf/artifactId version${cudf.version}/version /dependency带 CUDA 版本的 classifier 示例CUDA 12dependency groupIdai.rapids/groupId artifactIdcudf/artifactId classifiercuda12/classifier version${cudf.version}/version /dependencyclassifier 并非手工指定而是构建时自动推导的。pom.xml 中一段 Groovy 脚本在validate阶段解析nvcc --version的主版本号生成cudamajor若os.arch为aarch64/arm64则追加-arm64后缀最终通过maven-jar-plugin的classifier${cuda.classifier}/classifier写进 JAR。也就是说构建主机产物 classifierx86_64 CUDA 12.xcuda12x86_64 CUDA 13.xcuda13aarch64 CUDA 12.xcuda12-arm64aarch64 CUDA 13.xcuda13-arm64与 java/ci/README.md 的说明完全一致。fat JAR 里的原生库是怎么加载的JVM 无法直接从 JAR 中dlopen原生库cuDF 用 NativeDepsLoader.java 解决按${os.arch}/${os.name}/路径在类路径中定位libcudf.so、libcudfjni.so等资源解压到临时文件后System.load并按依赖阶段顺序加载。加载顺序定义在 NativeDepsLoader.java#L93-L103private static final String[][] loadOrder new String[][]{ new String[]{nvcomp}, // 可选静态 libcudf 构建已内嵌 nvcomp 时会跳过 new String[]{cudf}, new String[]{cudfjni} };几个对运维和部署有价值的系统属性均可从源码确认-Dai.rapids.cudf.lib-native-dirpath跳过 JAR 解压直接从该目录加载预解包的.so文件文件必须齐全加载前会做前置校验见 NativeDepsLoader.java#L63-L71 与validateLibNativeDir-Dai.rapids.cudf.preserve-dependenciestrue加载后不立即删除解压出的临时文件仍会在 JVM 退出时清理-Dai.rapids.cudf.lib-log-load-timingtrue以 INFO 级别输出每个库的解压/加载耗时与汇总便于排查启动慢问题。打包侧对应地pom.xml#L805-L856 的copy-native-libs执行项把libcudfjni.so、libcufilejni.soGDS 构建才有、libnvcomp.so以及libcudf.so复制到${project.build.outputDirectory}/${os.arch}/${os.name}/下正好与加载器的查找路径对齐。从源码构建第 1 步构建 libcudf按照 java/README.md 的说明先构建 libcudf并确认 JDK 已安装可用。给 libcudf 的 CMake 构建追加以下选项-DCUDF_LARGE_STRINGS_DISABLEDON -DCUDF_USE_ARROW_STATICON -DCUDF_ENABLE_ARROW_S3OFF这两个选项的作用禁用大字符串支持对应上游 issue NVIDIA/cudf#16215 的场景将 Arrow 静态链接进 libcudf从而把 Arrow 从运行时依赖中移除让 fat JAR 的运行时依赖更干净。第 2 步用 Maven 构建 Java 绑定在java/目录下执行mvn clean install构建机上有兼容 GPU 时测试会直接跑没有 GPU 则会看到大量 skipped 的测试。mvn背后做的事情可以从 pom.xml 的 antrun 配置看出validate阶段在target/cmake-build里对src/main/native执行 CMake 并传入了几个关键开关属性定义见 pom.xml#L199-L219默认值均为OFFMaven 属性传给 CMake 的参数默认作用CUDF_USE_PER_THREAD_DEFAULT_STREAM-DCUDF_USE_PER_THREAD_DEFAULT_STREAMOFF启用 PTDS 编译USE_GDS-DUSE_GDSOFF启用 GPUDirect StorageCuFile支持CUDF_JNI_LIBCUDF_STATIC-DCUDF_JNI_LIBCUDF_STATICOFF链接静态 libcudfCMAKE_CUDA_ARCHITECTURES同名参数RAPIDSCUDA 架构集合CUDF_CPP_BUILD_DIR环境变量传入空指向已构建的 libcudf使用 Java CI Docker 镜像构建java/README.md 提示如果不想只得到一个只能在构建机环境里跑的 JAR推荐用 CI 的 Docker 环境构建可得到接近官方发布、能在大多数现代 Linux 系统上运行的产物。当前的标准流程在 java/ci/README.md 中全部脚本都在 java/ci/ 下本地与 CI 走同一套脚本GitHub Actions 只是薄封装。前置条件可运行docker的机器以及能拉取rapidsai/ci-wheel:rapids-cudaver-rockylinux8-py3.11镜像的网络。构建不需要本地 GPU。Step 1 —— 构建静态 libcudf 安装树产出lib/libcudf.a及其静态依赖./java/ci/build_static_libcudf.sh --output-dir /tmp/libcudf-cuda12 --cuda-version 12.9.2Step 2 —— 构建某个 classifier 的 cuDF Java JAR./java/ci/build_cudf_java_jar.sh \ --libcudf-dir /tmp/libcudf-cuda12 \ --output-dir /tmp/jars \ --cuda-version 12.9.2该步骤会编译 JNI 层并输出 classifier JAR如cudf-26.12.0-SNAPSHOT-cuda12.jar、共享的 sources/javadoc JAR 与 POM落到--output-dir下以 classifier 命名的子目录中。需要 ARM classifier 必须有真正的aarch64主机不同 classifier 的 SNAPSHOT 并发构建是安全的但 release 构建会改写共享的 java/pom.xml不可并发。Step 3 —— 组装 Maven 仓库布局./java/ci/assemble_maven_repo.sh \ --jars-dir /tmp/jars \ --output-dir /tmp/maven-repo它会遍历--jars-dir下每个子目录子目录名即 classifier收集各 classifier JAR、共享的 sources/javadoc JAR 与 POM并以cuda12classifier 的副本作为不带 classifier 的主 JAR最终产出/tmp/maven-repo/ai/rapids/cudf/CUDF_VERSION-SNAPSHOT/ cudf-CUDF_VERSION-SNAPSHOT.jar cudf-CUDF_VERSION-SNAPSHOT-cuda12.jar cudf-CUDF_VERSION-SNAPSHOT-cuda13.jar cudf-CUDF_VERSION-SNAPSHOT-sources.jar cudf-CUDF_VERSION-SNAPSHOT-javadoc.jar cudf-CUDF_VERSION-SNAPSHOT.pom本地一键演练两个 CUDA 版本的全流程x86_64架构./java/ci/test_java_build_local.sh --work-dir /tmp/java-build-testRelease 与 SNAPSHOT 版本号CI 中GITHUB_REFrefs/tags/vYY.MM.PP的 tag 构建产出 release 版本号的 JAR其余一律是-SNAPSHOT。本地排练 release 路径GITHUB_REFrefs/tags/vYY.MM.PP ./java/ci/test_java_build_local.sh对打包 JAR 跑测试普通的cd java mvn test验证的是本地源码树而非发布产物要对打包好的 classifier JAR 跑同一套测试外加PackagedJarOriginCheck用需要 Docker GPU./java/ci/test_packaged_java_local.sh --work-dir /tmp/java-build-testci/README.md 中保留了一段基于 Dockerfile.rocky 的旧构建流程docker buildnvidia-docker runsource java/ci/env.sh已被上述自包含脚本取代仅作历史参考。以 libcudf 静态归档方式构建当静态链接 CUDA 运行时时推荐把 cuDF 构建成归档而非共享库这样 Java 绑定最终只依赖一个使用 CUDA 运行时的共享库。做法java/README.md构建 libcudf 时追加-DBUILD_SHARED_LIBSOFF用 Maven 构建 Java 绑定时追加-DCUDF_JNI_LIBCUDF_STATICON。对应 Maven 属性即上表中的CUDF_JNI_LIBCUDF_STATICpom.xml#L212 默认OFF经 antrun 透传给 CMake。CI 的 build_static_libcudf.sh 产出的正是这种静态安装树Step 2 中 JNI 层即基于它编译。可选编译特性一Per-thread Default StreamPTDSjava/README.md 说明 JNI 层可以以per-thread default stream模式编译每个主机线程拥有自己的默认 CUDA 流从而可能提升不同线程之间数据拷贝与计算的重叠度。由于 PTDS 是按编译单元生效的选项必须在整个代码库中一致开启因此需要两处同时配置先构建 cuDF C 库cd src/cudf/cpp/build cmake .. -DCMAKE_INSTALL_PREFIX$CONDA_PREFIX -DCUDF_USE_PER_THREAD_DEFAULT_STREAMON make -jnproc make install再构建 JARcd src/cudf/java mvn clean install -DCUDF_USE_PER_THREAD_DEFAULT_STREAMON注意src/cudf/cpp是仓库拆分前的旧目录布局在当前 monorepo 中对应目录为 cpp/ 与 java/命令语义不变路径需按实际布局调整。Maven 侧该开关就是 pom.xml 的CUDF_USE_PER_THREAD_DEFAULT_STREAM属性经 antrun 以-DCUDF_USE_PER_THREAD_DEFAULT_STREAM${CUDF_USE_PER_THREAD_DEFAULT_STREAM}传给原生 CMake 构建与文档要求C 侧与 JNI 侧同时开启相互印证。可选编译特性二GPUDirect StorageGDSJNI 层也可以开启GPUDirect Storage支持让 GPU 设备缓冲与受支持的存储系统之间直接拷贝绕过主机内存中转。前提是系统已安装 GDS 软件栈安装与排错以 NVIDIA GDS 官方文档为准。开启方式cd src/cudf/java mvn clean install -DUSE_GDSON对应关系同样可以在构建配置中找到Maven 属性USE_GDSpom.xml#L210默认OFF透传为-DUSE_GDS${USE_GDS}启用后原生构建会额外产出libcufilejni.so并被copy-native-libs打进 JAR见 pom.xml#L838-L844测试侧有专门的 CuFileTest.java且 pom.xml 中定义了no-cufile-testsprofile当USE_GDS不为ON时自动排除CuFileTest等用例避免在无 GDS 环境下误报失败。Java API 层则提供了CuFile、CuFileBuffer、CuFileDriver、CuFileReadHandle等类位于 java/src/main/java/ai/rapids/cudf/来操作这些句柄。测试组织方式了解构建行为时有帮助pom.xml 将测试拆成多个 surefire execution理解这对排查为什么我的测试没跑/跳过了很有帮助default-testsprofile 依次执行主测试集、non-empty-null-test带-da:ai.rapids.cudf.AssertEmptyNulls的断言开关、fatal-cuda-testreuseForksfalse独立 JVM 跑CudaFatalTest和native-deps-loader-test独立 fork 的 JVM 跑NativeDepsLoaderTest因为该测试会改动系统属性并断言 JVM 初始状态packaged-jar-testsprofile 通过-Dcudf.jar.pathclassifier.jar把打包 JAR 挂上 classpath、跳过 CMake 与主源码编译直接对发布形态跑测试并强制执行PackagedJarOriginCheck。这解释了 java/ci/README.md 中plainmvn test不等于验证了 classifier JAR的说法。小结与使用建议依赖优先使用官方 Maven Central 的ai.rapids:cudf无 classifier从源码或 CI 脚本构建的产物带cudaNN[-arm64]classifier只能用于匹配的 CUDA 主版本与 CPU 架构。多 GPU 机器记住每进程单 GPU RMM 初始化锁定设备两条规则先Cuda.setDevice再Rmm.initialize不要用同一条线程混用其他自行切换设备的 CUDA 库。构建本地快速验证用mvn clean installlibcudf 记得加-DCUDF_LARGE_STRINGS_DISABLEDON -DCUDF_USE_ARROW_STATICON -DCUDF_ENABLE_ARROW_S3OFF要产出可分发的 JAR 用 java/ci/ 的三步脚本需要静态链接 CUDA 运行时则走-DBUILD_SHARED_LIBSOFF-DCUDF_JNI_LIBCUDF_STATICON组合。进阶选项PTDS 与 GDS 均为按编译单元生效的开关必须 C 库与 JNI 层一致开启GDS 还需要系统级软件栈支持。部署排障遇到原生库加载问题先用-Dai.rapids.cudf.lib-log-load-timingtrue看加载耗时或-Dai.rapids.cudf.lib-native-dirdir直接指向预解包目录-Dai.rapids.cudf.preserve-dependenciestrue可保留临时文件便于检查。以上所有行为均以当前仓库26.12.0-SNAPSHOT开发线的实际源码与构建脚本为准由于 Java API 在 1.0 前仍可能调整跨版本升级时建议对照 java/README.md 与 java/ci/README.md 重新核对选项名称。赞分享数据分析数据工程机器学习【免费下载链接】cudfcuDF - GPU DataFrame Library项目地址https://gitcode.com/gh_mirrors/cu/cudf点击查看免费下载相关推荐Flink 项目 Maven 配置实战指南依赖管理、构建打包与 fat JAR 制作Flink 项目 Maven 配置实战指南依赖管理、构建打包与 fat JAR 制作 本篇指南面向准备用 Maven 搭建 Apache Flink 作业项目大数据流处理批处理数据工程MXNet Java 环境搭建指南Maven 依赖、源码构建与推理 API 实战MXNet Java 环境搭建指南Maven 依赖、源码构建与推理 API 实战 MXNet 官方为 Java 语言提供了完整的推理Inference支持深度学习机器学习人工智能FoundationDB Java 绑定构建指南JDK 探测、Fat Jar 与多平台打包实战FoundationDB Java 绑定构建指南JDK 探测、Fat Jar 与多平台打包实战 FoundationDB 是一个面向大规模结构化数据场景的分布分布式数据库KV存储数据库后端上一篇MiroFish开源贡献指南如何参与群体智能引擎的开发与改进下一篇mRemoteNG远程连接管理工具提升工作效率的终极解决方案创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考