forked from NVIDIA/cuda-quantum
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathvalidate_container.sh
More file actions
412 lines (371 loc) · 15.3 KB
/
validate_container.sh
File metadata and controls
412 lines (371 loc) · 15.3 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
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
#!/bin/bash
# ============================================================================ #
# Copyright (c) 2022 - 2025 NVIDIA Corporation & Affiliates. #
# All rights reserved. #
# #
# This source code and the accompanying materials are made available under #
# the terms of the Apache License 2.0 which accompanies this distribution. #
# ============================================================================ #
# Usage:
# Launch the NVIDIA CUDA-Q Docker container,
# and run this script from the home directory.
# Check the logged output.
passed=0
failed=0
skipped=0
samples=0
if [ -x "$(command -v nvidia-smi)" ] && [ "$(nvidia-smi | egrep -o "CUDA Version: ([0-9]{1,}\.)+[0-9]{1,}")" != "" ];
then gpu_available=true
else gpu_available=false
fi
if $gpu_available;
then echo "GPU detected." && nvidia-smi
else echo "No GPU detected."
fi
if [ -x "$(command -v ssh -V)" ];
then ssh_available=true
else ssh_available=false
fi
if $ssh_available;
then echo "SSH Client detected."
else echo "No SSH Client detected."
fi
if [ -x "$(command -v mpiexec --version)" ];
then mpi_available=true
else mpi_available=false
fi
if $mpi_available;
then echo "MPI detected."
else echo "No MPI detected."
fi
export UCX_LOG_LEVEL=warning
requested_backends=`\
for target in $@; \
do echo "$target"; \
done`
installed_backends=`\
echo "default"
for file in $(ls $CUDA_QUANTUM_PATH/targets/*.yml); \
do basename $file | cut -d "." -f 1; \
done`
# remote_rest targets are automatically filtered,
# so is execution on the photonics backend and the stim backend
# This will test all NVIDIA-derivative targets in the legacy mode,
# i.e., nvidia-fp64, nvidia-mgpu, nvidia-mqpu, etc., are treated as standalone targets.
available_backends=`\
echo "default"
for file in $(ls $CUDA_QUANTUM_PATH/targets/*.yml); \
do
if grep -q "library-mode-execution-manager: photonics" $file ; then
continue
fi
# Skip optimization test targets
if [[ $file == *"opt-test.yml" ]]; then
continue
fi
if grep -q "nvqir-simulation-backend: stim" $file ; then
continue
fi
platform=$(cat $file | grep "platform-qpu:")
qpu=${platform##* }
requirements=$(cat $file | grep "gpu-requirements:")
gpus=${requirements##* }
if [ "${qpu}" != "remote_rest" ] && [ "${qpu}" != "NvcfSimulatorQPU" ] \
&& [ "${qpu}" != "fermioniq" ] && [ "${qpu}" != "orca" ] \
&& [ "${qpu}" != "pasqal" ] && [ "${qpu}" != "quera" ] \
&& ($gpu_available || [ -z "$gpus" ] || [ "${gpus,,}" == "false" ]); then \
basename $file | cut -d "." -f 1; \
fi; \
done`
missing_backend=false
if [ $# -eq 0 ]
then
requested_backends="$available_backends"
else
for t in $requested_backends
do
echo $available_backends | grep -w -q $t
if [ ! $? -eq 0 ];
then
echo "No backend configuration found for $t."
missing_backend=true
fi
done
fi
echo
echo "Installed backends:"
echo "$installed_backends"
echo
echo "Available backends:"
echo "$available_backends"
echo
echo "Testing backends:"
echo "$requested_backends"
echo
if $missing_backend || [ "$available_backends" == "" ];
then
echo "Abort due to missing backend configuration."
exit 1
fi
# Long-running tests
tensornet_backend_skipped_tests=(\
examples/cpp/other/builder/vqe_h2_builder.cpp \
examples/cpp/other/builder/qaoa_maxcut_builder.cpp \
applications/cpp/vqe_h2.cpp \
applications/cpp/qaoa_maxcut.cpp \
examples/cpp/other/builder/builder.cpp \
applications/cpp/amplitude_estimation.cpp)
echo "============================="
echo "== C++ Tests =="
echo "============================="
# Note: piping the `find` results through `sort` guarantees repeatable ordering.
tmpFile=$(mktemp)
for ex in `find examples/ applications/ targets/ -name '*.cpp' | sort`;
do
filename=$(basename -- "$ex")
filename="${filename%.*}"
echo "Testing $filename:"
echo "Source: $ex"
let "samples+=1"
# Look for a --target flag to nvq++ in the
# comment block at the beginning of the file.
intended_target=`sed -e '/^$/,$d' $ex | grep -oP '^//\s*nvq++.+--target\s+\K\S+'`
if [ -n "$intended_target" ]; then
echo "Intended for execution on $intended_target backend."
fi
use_library_mode=`sed -e '/^$/,$d' $ex | grep -oP '^//\s*nvq++.+-library-mode'`
if [ -n "$use_library_mode" ]; then
nvqpp_extra_options="--library-mode"
fi
for t in $requested_backends
do
# Skipping dynamics examples if target is not dynamics and ex is dynamics
# or gpu is unavailable
if { [ "$t" != "dynamics" ] && [[ "$ex" == *"dynamics"* ]]; } || { [ "$t" == "dynamics" ] && [[ "$ex" != *"dynamics"* ]]; }; then
let "skipped+=1"
echo "Skipping $t target for $ex.";
echo ":white_flag: $filename: Not intended for this target. Test skipped." >> "${tmpFile}_$(echo $t | tr - _)"
continue
fi
if [ "$t" == "default" ]; then target_flag=""
else target_flag="--target $t"
fi
if [ -n "$intended_target" ] && [ "$intended_target" != "$t" ];
then
let "skipped+=1"
echo "Skipping $t target.";
echo ":white_flag: $filename: Not intended for this target. Test skipped." >> "${tmpFile}_$(echo $t | tr - _)"
continue
elif [ "$t" == "density-matrix-cpu" ] && [[ "$ex" != *"nois"* ]];
then
let "skipped+=1"
echo "Skipping $t target."
echo ":white_flag: $filename: Not executed for performance reasons. Test skipped." >> "${tmpFile}_$(echo $t | tr - _)"
continue
# Skip long-running tests, not suitable for cutensornet-based backends.
elif [[ "$t" == "tensornet" || "$t" == "tensornet-mps" || "$t" == "nvidia-mqpu-mps" ]] && [[ " ${tensornet_backend_skipped_tests[*]} " =~ " $ex " ]]; then
let "skipped+=1"
echo "Skipping $t target."
echo ":white_flag: $filename: Issue https://github.com/NVIDIA/cuda-quantum/issues/884. Test skipped." >> "${tmpFile}_$(echo $t | tr - _)"
continue
elif [ "$t" == "remote-mqpu" ]; then
# Skipped long-running tests (variational optimization loops) for the "remote-mqpu" target to keep CI runtime managable.
# A simplified test for these use cases is included in the 'test/Remote-Sim/' test suite.
# Skipped tests that require passing kernel callables to entry-point kernels for the "remote-mqpu" target.
if [[ "$ex" == *"vqe_h2"* || "$ex" == *"qaoa_maxcut"* || "$ex" == *"gradients"* || "$ex" == *"grover"* || "$ex" == *"multi_controlled_operations"* || "$ex" == *"phase_estimation"* || "$ex" == *"trotter_kernel_mode"* || "$ex" == *"builder.cpp"* ]];
then
let "skipped+=1"
echo "Skipping $t target.";
echo ":white_flag: $filename: Not executed for performance reasons. Test skipped." >> "${tmpFile}_$(echo $t | tr - _)"
continue
# Don't run remote-mqpu if the MPI installation is incomplete (e.g., missing an ssh-client).
elif [[ "$mpi_available" == true && "$ssh_available" == false ]];
then
let "skipped+=1"
echo "Skipping $t target due to incomplete MPI installation.";
echo ":white_flag: $filename: Incomplete MPI installation. Test skipped." >> "${tmpFile}_$(echo $t | tr - _)"
continue
else
# TODO: remove this once the nvqc backend is part of the validation
# tracked in https://github.com/NVIDIA/cuda-quantum/issues/1283
target_flag+=" --enable-mlir"
fi
fi
echo "Testing on $t target..."
if [ "$t" == "nvidia" ]; then
# For the unified 'nvidia' target, we validate all target options as well.
# Note: this overlaps some legacy standalone targets (e.g., nvidia-mqpu, nvidia-mgpu, etc.),
# but we want to make sure all supported configurations in the unified 'nvidia' target are validated.
declare -a optionArray=("fp32" "fp64" "fp32,mqpu" "fp64,mqpu" "fp32,mgpu" "fp64,mgpu")
arraylength=${#optionArray[@]}
for (( i=0; i<${arraylength}; i++ ));
do
echo " Testing $t target option: ${optionArray[$i]}"
nvq++ $nvqpp_extra_options $ex $target_flag --target-option "${optionArray[$i]}"
if [ ! $? -eq 0 ]; then
let "failed+=1"
echo " :x: Compilation failed for $filename." >> "${tmpFile}_$(echo $t | tr - _)"
continue
fi
./a.out &> /tmp/cudaq_validation.out
status=$?
echo " Exited with code $status"
if [ "$status" -eq "0" ]; then
let "passed+=1"
echo " :white_check_mark: Successfully ran $filename." >> "${tmpFile}_$(echo $t | tr - _)"
else
cat /tmp/cudaq_validation.out
let "failed+=1"
echo " :x: Failed to execute $filename." >> "${tmpFile}_$(echo $t | tr - _)"
fi
rm a.out /tmp/cudaq_validation.out &> /dev/null
done
else
nvq++ $nvqpp_extra_options $ex $target_flag
if [ ! $? -eq 0 ]; then
let "failed+=1"
echo ":x: Compilation failed for $filename." >> "${tmpFile}_$(echo $t | tr - _)"
continue
fi
./a.out &> /tmp/cudaq_validation.out
status=$?
echo "Exited with code $status"
if [ "$status" -eq "0" ]; then
let "passed+=1"
echo ":white_check_mark: Successfully ran $filename." >> "${tmpFile}_$(echo $t | tr - _)"
else
cat /tmp/cudaq_validation.out
let "failed+=1"
echo ":x: Failed to execute $filename." >> "${tmpFile}_$(echo $t | tr - _)"
fi
rm a.out /tmp/cudaq_validation.out &> /dev/null
fi
done
echo "============================="
done
echo "============================="
echo "== Python Tests =="
echo "============================="
# Note: some of the tests do their own "!pip install ..." during the test, and
# for that to work correctly on the first time, the user site directory (e.g.
# ~/.local/lib/python3.10/site-packages) must already exist, so create it here.
if [ -x "$(command -v python3)" ]; then
mkdir -p $(python3 -m site --user-site)
fi
# Long-running dynamics examples
dynamics_backend_skipped_examples=(\
examples/python/dynamics/transmon_resonator.py \
examples/python/dynamics/silicon_spin_qubit.py)
# Note divisive_clustering_src is not currently in the Published container under
# the "examples" folder, but the Publishing workflow moves all examples from
# docs/sphinx/examples, docs/sphinx/targets into the examples directory for the
# purposes of the container validation. The divisive_clustering_src Python
# files are used by the Divisive_clustering.ipynb notebook, so they are tested
# elsewhere and should be excluded from this test.
# Same with afqmc.
# Note: piping the `find` results through `sort` guarantees repeatable ordering.
for ex in `find examples/ targets/ -name '*.py' | sort`;
do
filename=$(basename -- "$ex")
filename="${filename%.*}"
echo "Testing $filename:"
echo "Source: $ex"
let "samples+=1"
skip_example=false
explicit_targets=`cat $ex | grep -Po '^\s*cudaq.set_target\("\K.*(?=")'`
for t in $explicit_targets; do
if [ -z "$(echo $requested_backends | grep $t)" ]; then
echo "Explicitly set target $t not available."
skip_example=true
elif [ "$t" == "quera" ] || [ "$t" == "braket" ] ; then
# Skipped because GitHub does not have the necessary authentication token
# to submit a (paid) job to Amazon Braket (includes QuEra).
echo "Explicitly set target braket or quera; skipping validation due to paid submission."
skip_example=true
elif [[ "$t" == "dynamics" ]] && [[ " ${dynamics_backend_skipped_examples[*]} " =~ " $ex " ]]; then
echo "Skipping due to long run time."
skip_example=true
fi
done
if $skip_example;
then
let "skipped+=1"
echo "Skipped.";
echo ":white_flag: $filename: Necessary backend(s) not available. Test skipped." >> "${tmpFile}"
else
python3 $ex 1> /dev/null
status=$?
echo "Exited with code $status"
if [ "$status" -eq "0" ]; then
let "passed+=1"
echo ":white_check_mark: Successfully ran $filename." >> "${tmpFile}"
else
let "failed+=1"
echo ":x: Failed to run $filename." >> "${tmpFile}"
fi
fi
echo "============================="
done
if [ -n "$(find examples/ applications/ -name '*.ipynb')" ]; then
echo "Validating notebooks:"
export OMP_NUM_THREADS=8
echo "$available_backends" | python3 notebook_validation.py
if [ $? -eq 0 ]; then
let "passed+=1"
echo ":white_check_mark: Notebooks validation passed." >> "${tmpFile}"
else
let "failed+=1"
echo ":x: Notebooks validation failed. See log for details." >> "${tmpFile}"
fi
else
let "skipped+=1"
echo "Skipped notebook validation.";
echo ":white_flag: Notebooks validation skipped." >> "${tmpFile}"
fi
# Python snippet validation
if [ -d "snippets/" ];
then
# Skip NVQC and multi-GPU snippets.
for ex in `find snippets/ -name '*.py' -not -path '*/nvqc/*' -not -path '*/multi_gpu_workflows/*' | sort`;
do
filename=$(basename -- "$ex")
filename="${filename%.*}"
echo "Testing $filename:"
echo "Source: $ex"
let "samples+=1"
python3 $ex 1> /dev/null
status=$?
echo "Exited with code $status"
if [ "$status" -eq "0" ]; then
let "passed+=1"
echo ":white_check_mark: Successfully ran $filename." >> "${tmpFile}"
else
let "failed+=1"
echo ":x: Failed to run $filename." >> "${tmpFile}"
fi
done
fi
if [ -f "$GITHUB_STEP_SUMMARY" ];
then
for t in $requested_backends
do
file="${tmpFile}_$(echo $t | tr - _)"
if [ -f "$file" ]; then
echo "## Execution on $t target" >> $GITHUB_STEP_SUMMARY
cat "$file" >> $GITHUB_STEP_SUMMARY
rm -rf "$file"
fi
done
if [ -f "$tmpFile" ] && [ -n "$(cat "$tmpFile")" ]; then
echo "## Python examples and notebooks" >> $GITHUB_STEP_SUMMARY
cat "$tmpFile" >> $GITHUB_STEP_SUMMARY
fi
fi
rm -rf "$tmpFile"*
echo "============================="
echo "$samples examples found."
echo "Total passed: $passed"
echo "Total failed: $failed"
echo "Skipped: $skipped"
echo "============================="
if [ "$failed" -eq "0" ] && [ "$samples" != "0" ]; then exit 0; else exit 10; fi