@@ -14,17 +14,14 @@ concurrency:
1414 cancel-in-progress : true
1515name : Test CUDA
1616jobs :
17- test_cuda :
18- name : Test Python and C++ on CUDA
17+ test_python :
18+ name : Test Python on CUDA
1919 runs-on : gpu
20- # The full CUDA suite (serial pytest ~3h43m + C++ + LAMMPS) exceeds the
21- # default 360-min job limit; the self-hosted GPU runner has no hard cap.
20+ # The serial Python test suite can take several hours on the GPU runner.
2221 timeout-minutes : 480
23- # Share ONE AOTInductor on-disk compile cache across every step: the two
24- # pytest lanes AND the C++ fixture builds (gen_*.py in test_cc_local.sh)
25- # all drive the same inductor backend on the same architectures, so the C++
26- # fixture compiles reuse the kernels the Python lane just built. actions/cache
27- # (below) persists it across runs so unchanged models never recompile.
22+ # Share ONE AOTInductor on-disk compile cache across the two pytest lanes;
23+ # actions/cache (below) persists it across runs so unchanged models never
24+ # recompile.
2825 env :
2926 TORCHINDUCTOR_CACHE_DIR : ${{ github.workspace }}/.inductor-cache
3027 # https://github.com/deepmodeling/deepmd-kit/pull/2884#issuecomment-1744216845
@@ -81,47 +78,32 @@ jobs:
8178 DP_ENABLE_NATIVE_OPTIMIZATION: 1
8279 DP_ENABLE_PYTORCH: 1
8380 - run : dp --version
84- - name : Run Python tests + C++ build (overlap CPU compile work with the GPU lane)
85- # Two lanes on one GPU box, sized so only TWO heavy workstreams ever run
86- # at once -- the shape that was green before the C++ prep was (wrongly)
87- # added as a THIRD concurrent stream (that 3-way overlap SIGFAULTed both
88- # Python lanes via TORCHINDUCTOR_CACHE_DIR contention; see #5882):
89- # Lane 1 (CPU compile stream): the .pt2-freezing tests (-m aoti_compile)
90- # -- CPU-bound, GPU ~98% idle while inductor/g++/ptxas run -- THEN the
91- # C++ build + gen_*.py .pt2 fixtures (also CPU-bound, GPU idle). They
92- # run SEQUENTIALLY in one lane, so the compile work never races the
93- # shared inductor cache and cc-prep reuses the kernels the aoti tests
94- # just built.
95- # Lane 2 (GPU stream): the GPU-bound tests (-m "not aoti_compile") -- the
96- # ~19k-test bulk and the wall-clock bottleneck. It does not freeze
97- # .pt2, so it only reads the inductor cache, never competing to write.
98- # The whole CPU stream is hidden under lane 2; ctest + LAMMPS run after
99- # BOTH lanes join.
81+ - name : Run Python tests (overlap CPU-bound aoti compiles with the GPU lane)
82+ # Two pytest lanes on one GPU box:
83+ # Lane 1 (CPU stream): the .pt2-freezing tests (-m aoti_compile) --
84+ # CPU-bound, GPU ~98% idle while inductor/g++/ptxas run.
85+ # Lane 2 (GPU stream): the GPU-bound remainder (-m "not aoti_compile")
86+ # -- the bulk of the suite and the wall-clock bottleneck. It does not
87+ # freeze .pt2, so it only reads the inductor cache, never competing
88+ # to write.
89+ # Wall-clock becomes max(lane 1, lane 2) instead of their sum; the whole
90+ # compile stream is hidden behind the GPU lane. (The C++ build + fixture
91+ # generation runs in the separate test_cc job.)
10092 run : |
10193 # Cap the compile lane's inductor threads to ~half the cores so lane 2
10294 # keeps CPU for its host-side GPU dispatch; nice the compile work too.
10395 nc=$(( $(nproc) / 2 )); [ "$nc" -lt 1 ] && nc=1
10496 # rc=0 + `|| rc=$?` so a lane's failure does not let the step's default
10597 # `set -e` skip the wall-clock echo (the timing we most want on failure).
106- # Lane 1: aoti_compile pytest, THEN the C++ build + fixture generation.
10798 ( ta=$(date +%s); rc=0
10899 TORCHINDUCTOR_COMPILE_THREADS=$nc nice -n 15 \
109100 python -m pytest source/tests -m "aoti_compile" \
110101 -p no:cacheprovider --junit-xml=junit-aoti.xml || rc=$?
111102 # pytest exit 5 == "no tests collected"; harmless for the compile lane.
112103 [ "$rc" = 5 ] && rc=0
113104 echo "[lane aoti_compile] wall=$(( $(date +%s) - ta ))s exit=$rc"
114- tc=$(date +%s); rc_cc=0
115- ( export LD_LIBRARY_PATH=$CUDA_PATH/lib64:/usr/lib/x86_64-linux-gnu/:$LD_LIBRARY_PATH
116- export OMP_NUM_THREADS=1 TF_INTRA_OP_PARALLELISM_THREADS=1 \
117- TF_INTER_OP_PARALLELISM_THREADS=1 \
118- CMAKE_GENERATOR=Ninja DP_VARIANT=cuda DP_USE_MPICH2=1
119- source/tests/infer/convert-models.sh
120- DP_CC_SKIP_CTEST=1 nice -n 19 source/install/test_cc_local.sh ) || rc_cc=$?
121- echo "[lane cc-prep] wall=$(( $(date +%s) - tc ))s exit=$rc_cc"
122- exit $(( rc != 0 || rc_cc != 0 )) ) &
105+ exit $rc ) &
123106 pid_a=$!
124- # Lane 2: the GPU-bound unit tests (the bulk).
125107 ( tb=$(date +%s); rc=0
126108 python -m pytest source/tests -m "not aoti_compile" \
127109 -p no:cacheprovider --junit-xml=junit-gpu.xml || rc=$?
@@ -130,7 +112,7 @@ jobs:
130112 pid_b=$!
131113 rc_a=0; wait $pid_a || rc_a=$?
132114 rc_b=0; wait $pid_b || rc_b=$?
133- echo "lane exit codes: aoti_compile+cc-prep =$rc_a gpu=$rc_b"
115+ echo "lane exit codes: aoti_compile=$rc_a gpu=$rc_b"
134116 exit $(( rc_a != 0 || rc_b != 0 ))
135117 env :
136118 NUM_WORKERS : 0
@@ -150,10 +132,71 @@ jobs:
150132 junit-aoti.xml
151133 junit-gpu.xml
152134 if-no-files-found : warn
153- - name : C++ tests (ctest; build + fixtures done in lane 1 above)
154- run : |
135+
136+ test_cc :
137+ name : Test C++ on CUDA
138+ runs-on : gpu
139+ # The gen_*.py fixture builds drive the same AOTInductor backend on the same
140+ # architectures as the Python lanes, so they reuse the kernels cached by
141+ # test_python / previous runs.
142+ env :
143+ TORCHINDUCTOR_CACHE_DIR : ${{ github.workspace }}/.inductor-cache
144+ if : github.repository_owner == 'deepmodeling' && (github.event_name == 'pull_request' && github.event.label && github.event.label.name == 'Test CUDA' || github.event_name == 'workflow_dispatch' || github.event_name == 'merge_group')
145+ steps :
146+ # Jobs run on separate runners, so the C++ job needs its own complete
147+ # CUDA toolchain and Python dependency installation.
148+ - uses : actions/checkout@v7
149+ - name : Cache AOTInductor compile artifacts
150+ # Restored AFTER checkout so checkout's git-clean can't wipe it. Both
151+ # CUDA jobs share the same key; if both try to save it, the second save
152+ # is skipped with a warning (caches are immutable), which is harmless.
153+ uses : actions/cache@v6
154+ with :
155+ path : ${{ github.workspace }}/.inductor-cache
156+ key : inductor-cuda-${{ github.sha }}
157+ restore-keys : |
158+ inductor-cuda-
159+ - uses : actions/setup-python@v6
160+ with :
161+ python-version : " 3.11"
162+ # cache: 'pip'
163+ - name : Install wget and unzip
164+ run : sudo apt-get update && sudo apt-get install -y wget unzip
165+ - uses : lukka/get-cmake@latest
166+ with :
167+ useLocalCache : true
168+ useCloudCache : false
169+ - run : |
170+ UBUNTU_VERSION=$(lsb_release -rs | tr -d '.')
171+ OS_NAME="ubuntu${UBUNTU_VERSION}"
172+ echo "Current OS: ${OS_NAME}"
173+
174+ wget https://developer.download.nvidia.com/compute/cuda/repos/${OS_NAME}/x86_64/cuda-keyring_1.1-1_all.deb \
175+ && sudo dpkg -i cuda-keyring_1.1-1_all.deb \
176+ && sudo apt-get update \
177+ && sudo apt-get -y install cuda-toolkit-12-9 cudnn9-cuda-12
178+ echo "CUDA_PATH=/usr/local/cuda-12.9" >> $GITHUB_ENV
179+ echo "/usr/local/cuda-12.9/bin" >> $GITHUB_PATH
180+ # if: false # skip as we use nvidia image
181+ - run : python -m pip install -U uv
182+ - run : source/install/uv_with_retry.sh pip install --system --group pin_tensorflow_gpu --group pin_pytorch_gpu --group pin_jax_gpu
183+ - run : |
184+ export PYTORCH_ROOT=$(python -c 'import torch;print(torch.__path__[0])')
185+ export TENSORFLOW_ROOT=$(python -c 'import importlib.util,pathlib;print(pathlib.Path(importlib.util.find_spec("tensorflow").origin).parent)')
186+ pip install --find-links "https://www.paddlepaddle.org.cn/packages/nightly/cu126/paddlepaddle-gpu/" --index-url https://pypi.org/simple --trusted-host www.paddlepaddle.org.cn --trusted-host paddlepaddle.org.cn "paddlepaddle-gpu==3.4.0.dev20260310"
187+ source/install/uv_with_retry.sh pip install --system -v -e .[gpu,test,lmp,cu12,torch,jax] mpi4py --reinstall-package deepmd-kit
188+ # See https://github.com/jax-ml/jax/issues/29042
189+ source/install/uv_with_retry.sh pip install --system -U 'nvidia-cublas-cu12>=12.9.0.13'
190+ env:
191+ DP_VARIANT: cuda
192+ DP_ENABLE_NATIVE_OPTIMIZATION: 1
193+ DP_ENABLE_PYTORCH: 1
194+ - run : dp --version
195+ - name : Convert models
196+ run : source/tests/infer/convert-models.sh
197+ - run : |
155198 export LD_LIBRARY_PATH=$CUDA_PATH/lib64:/usr/lib/x86_64-linux-gnu/:$LD_LIBRARY_PATH
156- DP_CC_SKIP_BUILD=1 source/install/test_cc_local.sh
199+ source/install/test_cc_local.sh
157200 env:
158201 OMP_NUM_THREADS: 1
159202 TF_INTRA_OP_PARALLELISM_THREADS: 1
@@ -177,12 +220,12 @@ jobs:
177220 CUDA_VISIBLE_DEVICES: 0
178221 pass :
179222 name : Pass testing on CUDA
180- needs : [test_cuda ]
223+ needs : [test_python, test_cc ]
181224 runs-on : ubuntu-slim
182225 if : always()
183226 steps :
184227 - name : Decide whether the needed jobs succeeded or failed
185228 uses : re-actors/alls-green@release/v1
186229 with :
187230 jobs : ${{ toJSON(needs) }}
188- allowed-skips : test_cuda
231+ allowed-skips : test_python, test_cc
0 commit comments