Skip to content

feat: run CUDA tests in parallel via CTest GPU resource allocation#174

Open
chen2021673 wants to merge 1 commit into
masterfrom
cuda_test
Open

feat: run CUDA tests in parallel via CTest GPU resource allocation#174
chen2021673 wants to merge 1 commit into
masterfrom
cuda_test

Conversation

@chen2021673

@chen2021673 chen2021673 commented Jun 9, 2026

Copy link
Copy Markdown
Contributor

Summary

支持 CUDA 测试在多 GPU 环境下并行执行。

此前 CUDA 测试通过 ctest -L cuda -j1 串行运行,可以避免多个 CUDA 测试同时抢占 GPU,但无法利用多 GPU 机器上的空闲资源。本 PR 将带 cuda label 的测试改为按 test binary 粒度注册,并在 run_ctest 中按 GPU 对 CUDA tests 进行分组调度:每个 worker 绑定一张 GPU,通过 CUDA_VISIBLE_DEVICES 只暴露对应 GPU,然后串行执行该 worker 分配到的 CUDA 测试。

CPU 测试仍保持原有的 GoogleTest 自动发现和并行执行逻辑。

Motivation

当前测试流程中,CPU 测试可以并行执行,但 CUDA 测试固定串行:

ctest --output-on-failure -LE cuda -j$(nproc)
ctest --output-on-failure -L cuda -j1

这种方式虽然安全,但会导致多 GPU 机器利用率很低。即使机器上有多张 GPU,CUDA 测试也只能一个接一个运行。

本 PR 的目标是:

  • 保持单个 CUDA 测试进程只使用指定 GPU;
  • 避免多个 CUDA 测试无控制地同时看到全部 GPU;
  • 在多 GPU 机器上并行执行多个 CUDA test binary;
  • 保留 CPU 测试的 test case 级别自动发现能力。

Key Changes

CUDA test registration

更新 cmake/test_macros.cmake 中的测试注册逻辑。

对于带有 cuda label 的测试:

  • 不再通过 gtest_discover_tests 展开为单个 GoogleTest case;
  • 改为使用 add_test 按 test binary 粒度注册;
  • 如果传入 TEST_FILTER,继续通过 --gtest_filter 传递给测试 binary;
  • 设置对应的 LABELSTIMEOUT

非 CUDA 测试继续使用 gtest_discover_tests,保持原有的自动发现行为。

CTest runner

scripts/run_models_and_profile.bash 中新增 run_ctest 函数,统一执行 CTest 测试流程。

run_ctest 会:

  • 优先从 CTEST_CUDA_GPUS 读取用户指定的 GPU 列表;
  • 如果未指定,则通过 nvidia-smi --query-gpu=index 自动探测 GPU;
  • 如果没有探测到 GPU,则默认使用 GPU 0
  • 先并行执行非 CUDA 测试:
ctest --output-on-failure -LE cuda -j$(nproc)
  • 再通过以下命令列出 CUDA 测试:
ctest -N -L cuda
  • 根据可用 GPU 数量启动多个 worker;
  • 每个 worker 绑定一张 GPU,并用 round-robin 方式执行自己分配到的 CUDA tests:
CUDA_VISIBLE_DEVICES="$assigned_gpu" ctest --output-on-failure -R "^${test_name}$" -j1

这样可以让不同 CUDA test binary 分布到不同 GPU 上并行执行,同时保证单个 CUDA test 进程只看到自己绑定的 GPU。

Test config

更新 scripts/test_config.json

  • 删除原先硬编码的 CTEST_CMD
  • 保留 RUN_CTEST 作为是否执行 CTest 的布尔开关。

scripts/run_models_and_profile.bash 中不再从配置文件读取完整的 CTest shell 命令,而是在 RUN_CTEST=true 且当前不是 profile build 时调用 run_ctest

Expected Behavior

修改后:

  • CPU 测试仍通过 -LE cuda 排除 CUDA 测试并并行执行;
  • CUDA 测试不再固定整体 -j1 串行运行;
  • CUDA tests 会按 test binary 粒度被分配到多个 GPU worker;
  • 每个 CUDA test 进程通过 CUDA_VISIBLE_DEVICES 只看到指定 GPU;
  • 多 GPU 机器上可以并发运行多个 CUDA test binary;
  • 如果任一 worker 中的 CUDA 测试失败,run_ctest 会返回失败状态。

Test

单独运行ctest --output-on-failure 结果如下:

image

在运行脚本中,每个 CUDA binary 单独跑一次 ctest。所以每跑一个 test,CTest 都会输出一整段自己的总结:
image

GPU 测试加速:471.58 / 30.96 = 15.23x
节省时间:471.58 - 30.96 = 440.62 sec
约 7 分 21 秒,CUDA 测试耗时减少约 93.43%。

image image

@chen2021673 chen2021673 force-pushed the cuda_test branch 2 times, most recently from 6756795 to 2da0953 Compare June 10, 2026 03:00
Register CUDA tests at binary granularity and pin each to a GPU through
CTest RESOURCE_GROUPS, with a bash wrapper mapping CTEST_RESOURCE_GROUP_0_GPUS
to CUDA_VISIBLE_DEVICES. Add a run_ctest helper that generates the GPU
resource spec file (from CTEST_CUDA_GPUS or nvidia-smi) and runs CPU then
CUDA suites, replacing the hardcoded -j1 CUDA ctest command.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant