forked from NVIDIA/cosmos-framework
-
Notifications
You must be signed in to change notification settings - Fork 0
231 lines (200 loc) · 9.39 KB
/
Copy pathgpu-tests.yml
File metadata and controls
231 lines (200 loc) · 9.39 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
# SPDX-FileCopyrightText: Copyright (c) 2026 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
# SPDX-License-Identifier: OpenMDW-1.1
# Cosmos3-Nano GPU test suite on a self-hosted 8×H200 runner.
#
# A single ``pre-commit`` (lint) job runs first; the four GPU jobs all
# ``needs:`` it, so they wait on ONE pre-commit run and are skipped if lint
# fails — the single self-hosted runner is never spent on a lint-failing commit.
# The four GPU jobs then run (one at a time on the single runner):
# * training-smoke — Nano SFT pipeline (convert -> train 5 -> export -> t2i)
# * generator-regression — vision_sft_nano loss vs goldens (4-GPU subset)
# * inference-smoke — Nano multi-modality inference (t2vs + policy + forward_dynamics)
# * reasoner-regression — llava_ov_datapacker loss vs goldens (4-GPU subset)
#
# Requires:
# * a self-hosted runner labelled [self-hosted, gpu, h200] with 8 GPUs,
# NVIDIA drivers, and `uv` on PATH;
# * an `HF_TOKEN` repository secret (gated dataset/model downloads, incl. the
# streamed LLaVA-OneVision-Data dataset).
#
# Inputs/checkpoints download to examples/ + the HF cache and are reused across
# runs (the h100 goldens are reused on H200 — see _detect_arch).
name: GPU Tests
on:
push:
branches: [main]
pull_request:
branches: [main]
concurrency:
group: gpu-tests-${{ github.ref }}
cancel-in-progress: true
jobs:
# Single lint gate: runs once on ubuntu-latest; every GPU job below waits on it
# and is skipped if it fails.
pre-commit:
uses: ./.github/workflows/pre-commit.yml
training-smoke:
needs: pre-commit
runs-on: [self-hosted, gpu, h200]
timeout-minutes: 90
env:
HF_TOKEN: ${{ secrets.HF_TOKEN }}
HF_HUB_DISABLE_XET: "1"
steps:
- uses: actions/checkout@v6
- uses: astral-sh/setup-uv@v7
- name: Sync environment (cu128-train)
run: uv sync --all-extras --group=cu128-train
# Full SFT pipeline: download + convert Nano->DCP, train 5 steps (loss
# trend), export to HF safetensors, then a t2i generation from the export.
# MAX_GPUS defaults to 8. -s streams the live process log.
- name: Nano SFT pipeline smoke (convert -> train 5 -> export -> t2i, 8 GPU)
run: |
export LD_LIBRARY_PATH=
uv run --all-extras --group=cu128-train python -m pytest -v -s \
tests/nano_training_smoke_test.py --num-gpus=8 --levels=2 -o addopts=
# Clear the heavy artifacts (even on failure): examples/checkpoints (the
# Cosmos3-Nano DCP + Wan VAE, ~30 GB) and the pytest tmp dirs (the SFT
# checkpoint + logs). The small examples/data dataset and the HF cache are
# intentionally kept so subsequent runs reuse them.
- name: Clean up run outputs
if: always()
run: |
rm -rf examples/checkpoints || true
rm -rf "${TMPDIR:-/tmp}"/pytest-of-* /tmp/pytest-of-* || true
generator-regression:
needs: pre-commit
runs-on: [self-hosted, gpu, h200]
timeout-minutes: 60
env:
HF_TOKEN: ${{ secrets.HF_TOKEN }}
HF_HUB_DISABLE_XET: "1"
# Select the 4-GPU regression test variant (uses 4 of the 8 GPUs).
TEST_MAX_GPUS: "4"
steps:
- uses: actions/checkout@v6
- uses: astral-sh/setup-uv@v7
- name: Sync environment (cu128-train)
run: uv sync --all-extras --group=cu128-train
# Generator (vision_sft_nano) loss vs the h100 goldens. -s streams the live log.
- name: Generator regression (vision_sft_nano, 4-GPU subset)
run: |
export LD_LIBRARY_PATH=
uv run --all-extras --group=cu128-train python -m pytest -v -s \
tests/launch_regression_test.py -k vision_sft_nano \
--num-gpus=4 --levels=2 -o addopts=
# The h100_inputs fixture removes its DCP stage on teardown; clear the
# pytest tmp dirs too (logs + any run output). The HF cache is kept.
- name: Clean up run outputs
if: always()
run: |
rm -rf "${TMPDIR:-/tmp}"/pytest-of-* /tmp/pytest-of-* || true
inference-smoke:
needs: pre-commit
runs-on: [self-hosted, gpu, h200]
timeout-minutes: 60
env:
HF_TOKEN: ${{ secrets.HF_TOKEN }}
HF_HUB_DISABLE_XET: "1"
steps:
- uses: actions/checkout@v6
- uses: astral-sh/setup-uv@v7
- name: Sync environment (cu128-train)
run: uv sync --all-extras --group=cu128-train
# One inference call over t2vs (+sound), action policy, and forward_dynamics; checks each output.
# MAX_GPUS defaults to 8. -s streams the live process log.
- name: Nano inference smoke (t2vs + action policy + forward_dynamics, 8 GPU)
run: |
export LD_LIBRARY_PATH=
uv run --all-extras --group=cu128-train python -m pytest -v -s \
tests/nano_inference_smoke_test.py --num-gpus=8 --levels=2 -o addopts=
# Inference writes only the pytest tmp dir (the t2vs video + logs); the
# checkpoint download stays in the HF cache (kept). No examples/ artifacts.
- name: Clean up run outputs
if: always()
run: |
rm -rf "${TMPDIR:-/tmp}"/pytest-of-* /tmp/pytest-of-* || true
reasoner-regression:
needs: pre-commit
runs-on: [self-hosted, gpu, h200]
timeout-minutes: 60
env:
HF_TOKEN: ${{ secrets.HF_TOKEN }}
HF_HUB_DISABLE_XET: "1"
# Select the 4-GPU regression test variant (uses 4 of the 8 GPUs).
TEST_MAX_GPUS: "4"
steps:
- uses: actions/checkout@v6
- uses: astral-sh/setup-uv@v7
- name: Sync environment (cu128-train)
run: uv sync --all-extras --group=cu128-train
# Reasoner (llava_ov_datapacker) loss vs the h100 goldens. -s streams the live log.
- name: Reasoner regression (llava_ov_datapacker, 4-GPU subset)
run: |
export LD_LIBRARY_PATH=
uv run --all-extras --group=cu128-train python -m pytest -v -s \
tests/launch_regression_test.py -k llava_ov_datapacker \
--num-gpus=4 --levels=2 -o addopts=
# The h100_inputs fixture removes its DCP stage on teardown; clear the
# pytest tmp dirs too (logs + any run output). The HF cache is kept.
- name: Clean up run outputs
if: always()
run: |
rm -rf "${TMPDIR:-/tmp}"/pytest-of-* /tmp/pytest-of-* || true
# Co-located unit tests: every *_test.py under cosmos_framework/ (CPU and GPU
# together) in one pytest invocation, plus two torchrun steps for the
# distributed tests that hardcode their world size. Runs parallel to the four
# jobs above (all gated on the single pre-commit lint).
unittest:
needs: pre-commit
runs-on: [self-hosted, gpu, h200]
# 60 (not 30) so the first cold-cache run can download the Cosmos3-Nano
# checkpoint for scripts/_test's convert->export->inference pipeline; steady
# state (warm HF cache) is a few minutes.
timeout-minutes: 60
env:
HF_TOKEN: ${{ secrets.HF_TOKEN }}
HF_HUB_DISABLE_XET: "1"
steps:
- uses: actions/checkout@v6
- uses: astral-sh/setup-uv@v7
- name: Sync environment (cu128-train)
run: uv sync --all-extras --group=cu128-train
# Run the whole co-located suite (CPU + GPU). Tests that load internal
# pretrained weights from S3 skip themselves when credentials/pretrained.secret
# is absent (via RunIf / pytest.skip guards), so this is green without
# internal credentials; provide the credential file on the runner to
# exercise them. New tests are picked up automatically (no markers/lists).
- name: Unit tests
run: |
export LD_LIBRARY_PATH=
uv run --all-extras --group=cu128-train python -m pytest -v -s \
cosmos_framework/ -o addopts=
# The cfgp_ar / context_parallel tests call dist.init_process_group and
# skip under plain pytest (world_size 1); they must be launched with
# torchrun. They hardcode their world size via ParallelDims, so each file
# needs the matching --nproc_per_node and they cannot share one launch:
# * cfgp_ar -> cfgp=2, dp_shard=1 => world_size must be 2
# * context_parallel -> cp=4 (and cp=world_size) => world_size must be 4
# Over-provisioning (e.g. 8) makes ParallelDims' product != world_size and
# fails, so these sizes are fixed, not "the more GPUs the better".
- name: Distributed unit tests - cfgp_ar (torchrun, 2 ranks)
run: |
export LD_LIBRARY_PATH=
uv run --all-extras --group=cu128-train torchrun --nproc_per_node=2 -m pytest -v \
cosmos_framework/model/vfm/mot/cfgp_ar_test.py -o addopts=
- name: Distributed unit tests - context_parallel (torchrun, 4 ranks)
run: |
export LD_LIBRARY_PATH=
uv run --all-extras --group=cu128-train torchrun --nproc_per_node=4 -m pytest -v \
cosmos_framework/model/vfm/mot/context_parallel_test.py -o addopts=
# Clear everything the suite writes into the working tree (all gitignored
# scratch): pytest tmp dirs (DCP checkpoint, logs), the script-test
# `outputs/` dir, any `examples/checkpoints`, and the `schemas/` dir from
# export_schemas_test. The HF cache lives outside the tree and is kept for
# reuse across runs. Runs on success or failure.
- name: Clean up run outputs
if: always()
run: |
rm -rf "${TMPDIR:-/tmp}"/pytest-of-* /tmp/pytest-of-* \
outputs examples/checkpoints schemas || true