88 workflow_dispatch :
99
1010concurrency :
11- # PRs: group by branch (new push cancels old). Push to master: unique per SHA (never cancelled).
1211 group : ${{ github.workflow }}-${{ github.event_name == 'push' && github.sha || github.ref }}
1312 cancel-in-progress : ${{ github.event_name != 'push' }}
1413
3130
3231 include :
3332 # NVHPC compiler matrix: cpu (build+test), gpu (build-only, acc then omp)
34- # Every release from 23.11 through 26.3 (current)
3533 - { nvhpc: '23.11', target: cpu }
3634 - { nvhpc: '23.11', target: gpu }
3735 - { nvhpc: '24.7', target: cpu }
@@ -44,35 +42,81 @@ jobs:
4442 fail-fast : false
4543 continue-on-error : true
4644 runs-on : ${{ matrix.nvhpc && 'ubuntu-22.04' || format('{0}-latest', matrix.os) }}
47- container :
48- image : ${{ matrix.nvhpc && format('nvcr.io/nvidia/nvhpc:{0}-devel-cuda_multi-ubuntu22.04', matrix.nvhpc) || '' }}
49- options : ${{ matrix.nvhpc && '--security-opt seccomp=unconfined' || '' }}
5045 env :
51- CC : ${{ matrix.nvhpc && 'nvc' || '' }}
52- CXX : ${{ matrix.nvhpc && 'nvc++' || '' }}
53- FC : ${{ matrix.nvhpc && 'nvfortran' || '' }}
54- OMPI_ALLOW_RUN_AS_ROOT : ${{ matrix.nvhpc && '1' || '' }}
55- OMPI_ALLOW_RUN_AS_ROOT_CONFIRM : ${{ matrix.nvhpc && '1' || '' }}
56- PMIX_MCA_gds : ${{ matrix.nvhpc && 'hash' || '' }}
57- OMPI_MCA_hwloc_base_binding_policy : ${{ matrix.nvhpc && 'none' || '' }}
58- FFLAGS : ${{ matrix.nvhpc && '-tp=px -Kieee -noswitcherror' || '' }}
59- CFLAGS : ${{ matrix.nvhpc && '-tp=px' || '' }}
60- CXXFLAGS : ${{ matrix.nvhpc && '-tp=px' || '' }}
46+ NVHPC_IMAGE : ${{ matrix.nvhpc && format('nvcr.io/nvidia/nvhpc:{0}-devel-cuda_multi-ubuntu22.04', matrix.nvhpc) || '' }}
6147
6248 steps :
63- - name : Git safe directory
49+ # ── NVHPC: free disk before pulling the ~25-30 GB cuda_multi image ──
50+ - name : Free disk space
6451 if : matrix.nvhpc
65- run : git config --global --add safe.directory /__w/figr/figr
52+ run : |
53+ echo "=== Disk before cleanup ==="
54+ df -h /
55+ sudo rm -rf /usr/share/dotnet /usr/local/lib/android \
56+ /opt/ghc /usr/local/share/boost /opt/hostedtoolcache \
57+ /usr/local/graalvm /usr/local/.ghcup \
58+ /usr/local/share/chromium /usr/local/lib/node_modules
59+ sudo docker image prune -af
60+ sudo apt-get clean
61+ echo "=== Disk after cleanup ==="
62+ df -h /
6663
6764 - name : Clone
6865 uses : actions/checkout@v4
6966
70- - name : Fetch master for coverage diff
67+ - name : Fetch main for coverage diff
7168 run : |
72- git fetch origin master:master --depth=1
69+ git fetch origin main:main --depth=1
7370 git fetch --deepen=200
7471 continue-on-error : true
7572
73+ # ── NVHPC: pull image and start a long-lived container ──────────────
74+ - name : Pull NVHPC container
75+ if : matrix.nvhpc
76+ run : docker pull "$NVHPC_IMAGE"
77+
78+ - name : Start NVHPC container
79+ if : matrix.nvhpc
80+ run : |
81+ docker run -d --name nvhpc \
82+ --security-opt seccomp=unconfined \
83+ -v "${{ github.workspace }}:/workspace" \
84+ -w /workspace \
85+ -e CC=nvc \
86+ -e CXX=nvc++ \
87+ -e FC=nvfortran \
88+ -e OMPI_ALLOW_RUN_AS_ROOT=1 \
89+ -e OMPI_ALLOW_RUN_AS_ROOT_CONFIRM=1 \
90+ -e PMIX_MCA_gds=hash \
91+ -e OMPI_MCA_hwloc_base_binding_policy=none \
92+ -e "FFLAGS=-tp=px -Kieee -noswitcherror" \
93+ -e CFLAGS=-tp=px \
94+ -e CXXFLAGS=-tp=px \
95+ "$NVHPC_IMAGE" sleep infinity
96+
97+ - name : Setup NVHPC
98+ if : matrix.nvhpc
99+ run : |
100+ docker exec nvhpc bash -c '
101+ set -e
102+ apt-get update -y
103+ apt-get install -y cmake python3 python3-venv python3-pip \
104+ libfftw3-dev libhdf5-dev hdf5-tools git
105+ git config --global --add safe.directory /workspace
106+
107+ HPCX_DIR=$(dirname "$(find /opt/nvidia/hpc_sdk -path "*/hpcx/hpcx-*/ompi/bin/mpirun" | head -1)")/../..
108+ MPI_LIB=$(mpifort --showme:link | grep -oP "(?<=-L)\S+" | head -1)
109+
110+ cat > /etc/nvhpc-env.sh <<EOF
111+ export LD_LIBRARY_PATH=${MPI_LIB}:${HPCX_DIR}/ucx/lib:${HPCX_DIR}/ucc/lib:\$LD_LIBRARY_PATH
112+ export OMPI_MCA_rmaps_base_oversubscribe=1
113+ EOF
114+
115+ echo "=== NVHPC Environment ==="
116+ nvfortran --version
117+ '
118+
119+ # ── Standard (non-NVHPC) setup ─────────────────────────────────────
76120 - name : Setup MacOS
77121 if : matrix.os == 'macos' && !matrix.nvhpc
78122 run : |
@@ -109,30 +153,7 @@ jobs:
109153 echo "MPICC=mpiicx" >> $GITHUB_ENV
110154 echo "MPICXX=mpiicpx" >> $GITHUB_ENV
111155
112- # --- NVHPC container setup ---
113- - name : Setup NVHPC
114- if : matrix.nvhpc
115- run : |
116- apt-get update -y
117- apt-get install -y cmake python3 python3-venv python3-pip \
118- libfftw3-dev libhdf5-dev hdf5-tools git
119- # Set up NVHPC HPC-X MPI runtime paths
120- HPCX_DIR=$(dirname "$(find /opt/nvidia/hpc_sdk -path "*/hpcx/hpcx-*/ompi/bin/mpirun" | head -1)")/../..
121- MPI_LIB=$(mpifort --showme:link | grep -oP '(?<=-L)\S+' | head -1)
122- echo "LD_LIBRARY_PATH=${MPI_LIB}:${HPCX_DIR}/ucx/lib:${HPCX_DIR}/ucc/lib:${LD_LIBRARY_PATH}" >> $GITHUB_ENV
123- # Container MPI fixes: PMIx shared-memory, hwloc binding
124- echo "PMIX_MCA_gds=hash" >> $GITHUB_ENV
125- echo "OMPI_MCA_hwloc_base_binding_policy=none" >> $GITHUB_ENV
126- echo "OMPI_MCA_rmaps_base_oversubscribe=1" >> $GITHUB_ENV
127- # Debug: confirm compiler flags are set
128- echo "=== NVHPC Environment ==="
129- echo "FFLAGS=$FFLAGS"
130- echo "CFLAGS=$CFLAGS"
131- echo "CXXFLAGS=$CXXFLAGS"
132- nvfortran --version
133- cat /proc/cpuinfo | grep "model name" | head -1
134-
135- # --- Standard build + test ---
156+ # ── Standard build + test ───────────────────────────────────────────
136157 - name : Build
137158 if : ' !matrix.nvhpc'
138159 run : /bin/bash figr.sh test -v --dry-run -j $(nproc) --${{ matrix.debug }} $PRECISION --test-all
@@ -147,19 +168,34 @@ jobs:
147168 TEST_PCT : ${{ matrix.debug == 'reldebug' && '-% 20' || '' }}
148169 ONLY_CHANGES : ${{ github.event_name == 'pull_request' && '--only-changes' || '' }}
149170
150- # --- NVHPC build + test ---
171+ # ── NVHPC build + test (via docker exec into long-lived container) ──
151172 - name : Build (NVHPC)
152173 if : matrix.nvhpc && matrix.target == 'cpu'
153- run : /bin/bash figr.sh test -v --dry-run -j $(nproc) --test-all
174+ run : |
175+ docker exec nvhpc bash -c '
176+ source /etc/nvhpc-env.sh
177+ /bin/bash figr.sh test -v --dry-run -j $(nproc) --test-all
178+ '
154179
155180 - name : Build (NVHPC GPU)
156181 if : matrix.nvhpc && matrix.target == 'gpu'
157- run : |
158- /bin/bash figr.sh test -v --dry-run -j 2 --test-all --gpu acc
159- /bin/bash figr.sh test -v --dry-run -j 2 --test-all --gpu mp
182+ run : |
183+ docker exec nvhpc bash -c '
184+ source /etc/nvhpc-env.sh
185+ /bin/bash figr.sh test -v --dry-run -j 2 --test-all --gpu acc
186+ /bin/bash figr.sh test -v --dry-run -j 2 --test-all --gpu mp
187+ '
160188
161189 - name : Test (NVHPC)
162190 if : matrix.nvhpc && matrix.target == 'cpu'
163- run : |
164- ulimit -s unlimited || ulimit -s 65536 || true
165- /bin/bash figr.sh test -v --max-attempts 3 -j $(nproc) --test-all
191+ run : |
192+ docker exec nvhpc bash -c '
193+ source /etc/nvhpc-env.sh
194+ ulimit -s unlimited || ulimit -s 65536 || true
195+ /bin/bash figr.sh test -v --max-attempts 3 -j $(nproc) --test-all
196+ '
197+
198+ # ── Cleanup ─────────────────────────────────────────────────────────
199+ - name : Stop NVHPC container
200+ if : always() && matrix.nvhpc
201+ run : docker rm -f nvhpc || true
0 commit comments