尧图网站设计 尧图网站设计YAOTU DESIGN
ARTICLE DETAIL

资讯详情

深耕网站设计与一线实操的经验洞察。

XGBoost 单元测试指南:Python、C++、JVM 与 R 测试体系、本地运行方法及 Sanitizer 构建配置

XGBoost 单元测试指南:Python、C++、JVM 与 R 测试体系、本地运行方法及 Sanitizer 构建配置 XGBoost 单元测试指南Python、C、JVM 与 R 测试体系、本地运行方法及 Sanitizer 构建配置【免费下载链接】xgboostScalable, Portable and Distributed Gradient Boosting (GBDT, GBRT or GBM) Library, for Python, R, Java, Scala, C and more. Runs on single machine, Hadoop, Spark, Dask, Flink and DataFlow项目地址: https://gitcode.com/gh_mirrors/xg/xgboostXGBoost 仓库维护着覆盖 Python 包、C 核心、JVM 包和 R 包的完整单元测试体系这是其跨语言实现同一核心通过 C API 暴露给多种前端能够保持稳定正确性的基础。本篇基于仓库文档doc/contrib/unit_tests.rst完整展开你将了解各语言测试的目录约定与框架选型pytest、Google Test、JUnit/Scalatest、testthat、在本机编译运行各类单元测试的具体命令以及如何使用 CMake 选项开启 AddressSanitizer 等 sanitizer 来捕获内存错误与数据竞争并结合 CMake 配置与测试源码核实每个命令背后的实际实现。测试体系总览目录结构与框架对应关系从仓库结构看所有测试统一集中在tests/目录下按语言和场景拆分各目录的定位在 tests/README.md 中有明确说明目录测试对象框架tests/python/Python 包功能、API、CLIpytesttests/python-gpu/GPUCUDA路径pytesttests/test_distributed/Dask、Spark 等分布式框架pytesttests/cpp/C 核心库Google Testjvm-packages/xgboost4j/src/test/XGBoost4J 核心JUnit / Scalatestjvm-packages/xgboost4j-spark/src/test/XGBoost4J-SparkJUnit / ScalatestR-package/tests/testthatR 包testthattests/python/下已有约 40 个测试文件按功能模块命名如 test_basic.py、test_early_stopping.py、test_ranking.py、test_survival.py 以及针对第三方库兼容性的 test_with_pandas.py、test_with_arrow.py 等可作为新测试的命名与组织参考。pytest 的全局配置位于 tests/pytest.ini定义了两个测试标记marker[pytest] markers mgpu: Mark a test that requires multiple GPUs to run. ci: Mark a test that runs only on CI.可以推断mgpu标记用于筛选需要多 GPU 环境的用例ci标记用于只应在 CI 环境运行的用例本地运行可用pytest -m not mgpu之类的方式过滤。此外tests/目录下的 CI 依赖环境定义在 ops/conda_env/ 中如cpp_test.yml、python_lint.yml为各测试套件声明了运行所需的包版本。新增单元测试Python 包pytest新增 Python 测试文件应放入对应目录tests/python/常规 Python 包测试tests/python-gpu/测试 GPU 代码时使用tests/test_distributed/涉及 Dask、PySpark 等分布式框架时使用。测试编写遵循标准 pytest 规范。从 tests/README.md 可以看到部分 marker 还会由conftest.py动态生成涉及条件性测试用例时建议参考现有test_*.py文件中的pytest.mark用法。CGoogle TestC 核心测试放在 tests/cpp/ 目录按src/下的模块对应组织common/、data/、gbm/、metric/、objective/、tree/、collective/等子目录例如tests/cpp/test_learner.cc、tests/cpp/test_cache.cc与src/learner.cc、src/common/cache_manager.cc等实现一一对应。测试的入口是 tests/cpp/test_main.cc其实际内容为int main(int argc, char** argv) { xgboost::Args args{{verbosity, 2}}; xgboost::ConsoleLogger::Configure(args); testing::InitGoogleTest(argc, argv); testing::FLAGS_gtest_death_test_style threadsafe; auto rmm_alloc xgboost::SetUpRMMResourceForCppTests(argc, argv); return RUN_ALL_TESTS(); }可以观察到两个关键细节一是 XGBoost 的 death test 被设置为threadsafe风格因为测试中大量存在多线程OpenMP场景二是入口处通过SetUpRMMResourceForCppTests初始化了 RMM 内存分配器资源说明 C 测试对 GPU 内存管理路径也有覆盖仅在启用 CUDA 时相关。JVM 包JUnit / ScalatestJVM 包XGBoost4J / XGBoost4J-Spark采用 Maven 标准目录布局测试位于jvm-packages/xgboost4j/src/test/其下按语言再分为java/与scala/子目录jvm-packages/xgboost4j-spark/src/test/同样包含java/、scala/及resources/。Java 代码使用 JUnit 5 编写测试Scala 代码使用 Scalatest 编写测试具体写法遵循各自官方教程。R 包testthatR 包测试放在 R-package/tests/testthat 目录共 21 个测试文件如test_that_*系列另在R-package/tests/helper_scripts/提供辅助脚本。测试套件由 R-package/tests/testthat.R 驱动内容如下library(testthat) library(xgboost) library(Matrix) RhpcBLASctl::omp_set_num_threads(1) data.table::setDTthreads(1) test_check(xgboost, reporter ProgressReporter)从这段入口脚本可以看到R 包测试在启动时会把 OpenMP 线程数固定为 1通过RhpcBLASctl与data.table两套机制以规避多线程带来的测试结果抖动——这是 R 包与底层 BLAS/OpenMP 交互时的一个典型稳定性手段。本地运行单元测试R 包在项目根目录执行python ./ops/script/test_r_package.py --taskcheck该脚本ops/script/test_r_package.py会构建并检查 XGBoost R 包。如果只想在已安装 XGBoost 的前提下运行测试可以cd R-package/tests/ Rscript testthat.RJVM 包JVM 包统一使用 Maven 运行测试在jvm-packages/相关模块下执行mvn testMaven 会按标准布局自动发现并执行src/test/java与src/test/scala中的 JUnit / Scalatest 用例。Python 包pytest前置步骤安装 pytestpip3 install pytest按构建文档参见doc/install.rst及仓库根目录 CMake 配置编译好 XGBoost 共享库。然后在项目根目录执行# 告诉 Python 去哪里找 xgboost 模块 export PYTHONPATH./python-package pytest -v -s --fulltrace tests/python三个 flag 的作用-v输出每个用例的结果-s关闭输出捕获以便查看训练日志--fulltrace在失败时打印完整堆栈而非裁剪后的片段。测试 CUDA 路径需以 CUDA 启用状态编译 XGBoostexport PYTHONPATH./python-package pytest -v -s --fulltrace tests/python-gpu测试 Dask、PySpark 等分布式框架export PYTHONPATH./python-package pytest -v -s --fulltrace tests/test_distributedCGoogle Test通过 CMake 开关启用 C 测试。GOOGLE_TEST、USE_DMLC_GTEST等选项定义在根 CMakeLists.txtoption(GOOGLE_TEST Build google tests OFF) option(USE_DMLC_GTEST Use google tests bundled with dmlc-core submodule OFF)GOOGLE_TESTON构建测试目标。开启后根 CMakeLists.txt 会创建可执行文件testxgboost链接objxgboost目标引入tests/cpp子目录的所有测试源文件并注册一个名为TestXGBoostLib的 CTest 测试USE_DMLC_GTESTON使用 dmlc-core submodule 内自带的 Google Test而不依赖系统安装文档要求 Google Test 版本不低于 1.8.1USE_CUDA、USE_NCCL等与 sanitizer 无关的编译开关可按需开启。完整的构建与运行流程cmake -B build -S . -GNinja -DGOOGLE_TESTON -DUSE_DMLC_GTESTON -DUSE_CUDAON -DUSE_NCCLON cmake --build build cd ./build ./testxgboost除了直接运行testxgboost也可以借助 ctest 获得更灵活的控制例如只跑某个测试ctest --verbose在 Windows 上使用 Visual Studio 调试器定位问题时可以把 gtest 过滤 flag 追加到 tests/cpp/test_main.cc 中::testing::GTEST_FLAG(filter) Suite.Test; ::testing::GTEST_FLAG(repeat) 10;其中filter只运行指定测试用例repeat用于重复执行以暴露偶发性flaky问题。Sanitizers检测内存错误与数据竞争Sanitizer 工具链默认随 GCC 与 Clang/LLVM 分发GCC 4.8 或 LLVM 3.1 即可启用但部分发行版会将其单独打包。XGBoost 支持的 sanitizer 及其对应运行时库Sanitizer用途运行时库Address sanitizer (ASan)内存越界、use-after-freelibasanUndefined sanitizer (UBSan)未定义行为libubsanLeak sanitizer (LSan)内存泄漏liblsanThread sanitizer (TSan)数据竞争libtsanMemory sanitizer 是 LLVM 独有因此不在 XGBoost 支持范围内。较新的编译器如 gcc-9在指定 sanitizer 编译 flag 时能自动链接运行时库。构建带 Sanitizer 的 XGBoost对应选项定义在根 CMakeLists.txtoption(USE_SANITIZER Use santizer flags OFF) option(SANITIZER_PATH Path to sanitizes.) set(ENABLED_SANITIZERS address leak CACHE STRING Semicolon separated list of sanitizer names. E.g address;leak. Supported sanitizers are address, leak, undefined and thread.)开启USE_SANITIZER时默认启用address leak两个 sanitizer可以通过分号分隔的列表ENABLED_SANITIZERS覆盖默认值cmake -DUSE_SANITIZERON -DENABLED_SANITIZERSaddress;undefined /path/to/xgboost如果 CMake 在常规系统路径找不到 sanitizer 运行时可以显式指定SANITIZER_PATHcmake -DUSE_SANITIZERON -DENABLED_SANITIZERSaddress;undefined \ -DSANITIZER_PATH/path/to/sanitizers /path/to/xgboost从源码实现看实际的编译 flag 拼装逻辑在 cmake/Sanitizer.cmake 的enable_sanitizers宏中每个 sanitizer 被转换为-fsanitizename编译选项UBSan 额外加上-fno-sanitize-recoverundefined使未定义行为直接终止而非仅打印警告并通过find_package(ASan/TSan/LSan/UBSan)定位运行时库。该宏还实现了文档所述的兼容性检查遍历列表中每一项一旦发现thread与其他 sanitizer 混合会直接FATAL_ERROR报错——即thread sanitizer 与 address/leak/undefined 互斥这一约束在配置阶段就被强制。与 CUDA 配合使用 Address Sanitizer在 CUDA 环境下运行 ASan 构建的 XGBoost 会因 shadow memory 分配冲突而报内存错误。正确做法是通过ASAN_OPTIONS环境变量关闭 shadow gap 保护ASAN_OPTIONSprotect_shadow_gap0 ${BUILD_DIR}/testxgboost其他运行时选项默认情况下 UBSan 不打印调用栈可以通过环境变量启用UBSAN_OPTIONSprint_stacktrace1 ${BUILD_DIR}/testxgboost更多 flag 的语义可参考 GCC/LLVM 官方 sanitizer 文档。小结XGBoost 的测试体系遵循目录与语言框架一一对应的清晰约定新增测试时先按功能归属选择tests/python、tests/cpp、jvm-packages/*/src/test或R-package/tests/testthat之一再按文档给出的一行命令本地验证。C 侧通过GOOGLE_TEST选项把 Google Test 用例编译为testxgboost可执行文件并注册到 ctestPython 侧依靠PYTHONPATH加 pytest 标记体系控制用例集合而USE_SANITIZER选项则提供了从构建阶段引入 ASan/UBSan/TSan 检测内存错误与数据竞争的标准路径其中 thread sanitizer 的互斥约束在 cmake/Sanitizer.cmake 中由 CMake 层面强制执行。掌握上述目录结构、命令与配置项即可在本地完整地复现 XGBoost 各语言前端的单元测试与内存安全验证流程。【免费下载链接】xgboostScalable, Portable and Distributed Gradient Boosting (GBDT, GBRT or GBM) Library, for Python, R, Java, Scala, C and more. Runs on single machine, Hadoop, Spark, Dask, Flink and DataFlow项目地址: https://gitcode.com/gh_mirrors/xg/xgboost创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表