Skip to content

Commit 9307f5e

Browse files
Added Qureg checkpointing via ADIOS2 (#780)
Added new functions saveQuregToFile() and createQuregFromFile(), which are optionally enabled through ADIOS2 with new CMake option QUEST_ENABLE_ADIOS2. Ashmit added the core functionality, doc and prototyped tests. Tyson added input validation, bug fixes, and auto ADIOS2 downloading. --------- Co-authored-by: Tyson Jones <tyson.jones.input@gmail.com>
1 parent 90527c3 commit 9307f5e

13 files changed

Lines changed: 799 additions & 18 deletions

File tree

‎.github/workflows/compile.yml‎

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,7 @@ jobs:
4747
${{ matrix.cuda == 'ON' && 'CUDA' || '' }}
4848
${{ matrix.hip == 'ON' && 'HIP' || '' }}
4949
${{ matrix.cuquantum == 'ON' && 'CUQ' || '' }}
50+
${{ matrix.adios2 == 'ON' && 'CKPT' || '' }}
5051
5152
runs-on: ${{ matrix.os }}
5253

@@ -67,6 +68,7 @@ jobs:
6768
cuda: [ON, OFF]
6869
hip: [ON, OFF]
6970
cuquantum: [ON, OFF]
71+
adios2: [ON, OFF]
7072
mpilib: ['', 'mpich', 'ompi', 'impi', 'msmpi']
7173

7274
# disable deprecated API on MSVC, and assign unique compilers,
@@ -249,14 +251,16 @@ jobs:
249251
-DQUEST_ENABLE_CUDA=${{ matrix.cuda }}
250252
-DQUEST_ENABLE_HIP=${{ matrix.hip }}
251253
-DQUEST_ENABLE_CUQUANTUM=${{ matrix.cuquantum }}
254+
-DQUEST_ENABLE_ADIOS2=${{ matrix.adios2 }}
252255
-DCMAKE_CUDA_ARCHITECTURES=${{ env.cuda_arch }}
253256
-DCMAKE_HIP_ARCHITECTURES=${{ env.hip_arch }}
254257
-DCMAKE_CXX_COMPILER=${{ matrix.compiler }}
255258
-DCMAKE_CXX_FLAGS=${{ matrix.mpi == 'ON' && matrix.cuda == 'ON' && '-fno-lto' || '' }}
256259
257-
# force 'Release' build (needed by MSVC to enable optimisations)
260+
# force 'Release' build (needed by MSVC to enable optimisations),
261+
# and force serial compilation to avoid ADIOS2 OOM error
258262
- name: Compile
259-
run: cmake --build ${{ env.build_dir }} --config Release --parallel
263+
run: cmake --build ${{ env.build_dir }} --config Release --parallel 1
260264

261265
# run all compiled isolated examples to test for link-time errors,
262266
# continuing if any fail (since some deliberately fail)

‎.github/workflows/test_free.yml‎

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -59,7 +59,7 @@ jobs:
5959
- name: Get QuEST
6060
uses: actions/checkout@main
6161

62-
# compile serial unit tests, optionally include deprecated test
62+
# compile serial unit tests, optionally include deprecated test, always including ADIOS2
6363
- name: Configure CMake
6464
run: >
6565
cmake -B ${{ env.build_dir }}
@@ -68,16 +68,18 @@ jobs:
6868
-DQUEST_ENABLE_DEPRECATED_API=${{ matrix.version == 3 && 'ON' || 'OFF' }}
6969
-DQUEST_DISABLE_DEPRECATION_WARNINGS=${{ matrix.version == 3 && 'ON' || 'OFF' }}
7070
-DQUEST_FLOAT_PRECISION=${{ matrix.precision }}
71+
-DQUEST_ENABLE_ADIOS2=ON
7172
72-
# force 'Release' build (needed by MSVC to enable optimisations)
73+
# force 'Release' build (needed by MSVC to enable optimisations), and force serial (to avoid ADIOS2 OOM)
7374
- name: Compile
74-
run: cmake --build ${{ env.build_dir }} --config Release --parallel
75+
run: cmake --build ${{ env.build_dir }} --config Release --parallel 1
7576

7677
# run v4 unit tests in random order, excluding the integration tests,
7778
# using the default environment variables (e.g. test all permutations)
7879
# TODO:
7980
# ctest currently doesn't know of our Catch2 tags, so we
8081
# are manually excluding each integration test by name
82+
8183
- name: Run v4 tests
8284
if: ${{ matrix.version == 4 }}
8385
run: ctest -j2 --output-on-failure --schedule-random -C Release -E "density evolution"

‎CMakeLists.txt‎

Lines changed: 91 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -187,7 +187,6 @@ message(STATUS "AMD GPU acceleration is turned ${QUEST_ENABLE_HIP}. Set QUEST_EN
187187

188188
# GPU Performance Tuning
189189
# (We do not print this value when configuring CMake as it is for advanced users only)
190-
191190
set(quest_tpb_description # (the games we play for multi-line set() strings!)
192191
"The default number of threads per block QuEST will use when offloading to a GPU. Set to 128 by default. "
193192
"Must be a multiple of 32 (on NVIDIA GPUs) or 64 (on AMD GPUs). Can be overridden at executable launch "
@@ -199,6 +198,21 @@ set(QUEST_DEFAULT_NUM_GPU_THREADS_PER_BLOCK 128
199198
mark_as_advanced(QUEST_DEFAULT_NUM_GPU_THREADS_PER_BLOCK)
200199

201200

201+
# Checkpointing with ADIOS2
202+
option(
203+
QUEST_ENABLE_ADIOS2
204+
"Whether QuEST will be built with ADIOS2, enabling checkpointing (via saveQuregToFile / createQuregFromFile). Turned OFF by default."
205+
OFF
206+
)
207+
message(STATUS "ADIOS2 integration is turned ${QUEST_ENABLE_ADIOS2}. Set QUEST_ENABLE_ADIOS2 to modify.")
208+
209+
option(
210+
QUEST_DOWNLOAD_ADIOS2
211+
"Whether ADIOS2 will be downloaded if it is enabled but not found. Turned ON by default."
212+
ON
213+
)
214+
215+
202216
# Deprecated API
203217
option(
204218
QUEST_ENABLE_DEPRECATED_API
@@ -543,6 +557,81 @@ endif()
543557

544558

545559

560+
# Checkpointing (ADIOS2)
561+
if (QUEST_ENABLE_ADIOS2)
562+
563+
find_package(adios2 QUIET)
564+
565+
# A distributed QuEST needs an MPI-enabled ADIOS2 (which provides the
566+
# adios2::cxx_mpi target). A serial system install lacks it, so in that case we
567+
# ignore the found package and fetch an MPI-enabled build instead of failing.
568+
set(quest_use_found_adios2 ${adios2_FOUND})
569+
if (adios2_FOUND AND QUEST_ENABLE_MPI AND NOT TARGET adios2::cxx_mpi)
570+
message(STATUS "Found ADIOS2 lacks MPI support (no adios2::cxx_mpi target); fetching an MPI-enabled build instead")
571+
set(quest_use_found_adios2 FALSE)
572+
endif()
573+
574+
if(NOT quest_use_found_adios2 AND QUEST_DOWNLOAD_ADIOS2)
575+
message(STATUS "fetching ADIOS2 via FetchContent")
576+
577+
include(FetchContent)
578+
FetchContent_Declare(
579+
adios2
580+
GIT_REPOSITORY https://github.com/ornladios/ADIOS2.git
581+
GIT_TAG v2.12.1
582+
)
583+
584+
# Match ADIOS2's MPI to QuEST's so distributed runs write per-rank slices
585+
# into one shared file. ADIOS2's CUDA support is deliberately left OFF:
586+
# checkpointing copies amps to host memory (syncQuregFromGpu/syncQuregToGpu)
587+
# before any I/O, so ADIOS2 never touches device pointers. Building it with
588+
# CUDA is unnecessary and stalls the Windows CUDA CI job.
589+
set(ADIOS2_USE_MPI ${QUEST_ENABLE_MPI} CACHE BOOL "" FORCE)
590+
set(ADIOS2_USE_CUDA OFF CACHE BOOL "" FORCE)
591+
592+
# Forego unused facilities
593+
set(ADIOS2_BUILD_TESTING OFF CACHE BOOL "" FORCE)
594+
set(ADIOS2_BUILD_EXAMPLES OFF CACHE BOOL "" FORCE)
595+
set(ADIOS2_USE_SODIUM OFF CACHE BOOL "" FORCE)
596+
set(ADIOS2_USE_Fortran OFF CACHE BOOL "" FORCE)
597+
set(ADIOS2_USE_HDF5 OFF CACHE BOOL "" FORCE)
598+
set(ADIOS2_USE_ZeroMQ OFF CACHE BOOL "" FORCE)
599+
set(ADIOS2_USE_SST OFF CACHE BOOL "" FORCE)
600+
set(ADIOS2_USE_DataMan OFF CACHE BOOL "" FORCE)
601+
set(ADIOS2_USE_SSC OFF CACHE BOOL "" FORCE)
602+
set(ADIOS2_USE_MHS OFF CACHE BOOL "" FORCE)
603+
set(ADIOS2_USE_DAOS OFF CACHE BOOL "" FORCE)
604+
set(ADIOS2_USE_MGARD OFF CACHE BOOL "" FORCE)
605+
set(ADIOS2_USE_BZip2 OFF CACHE BOOL "" FORCE)
606+
set(ADIOS2_USE_Blosc OFF CACHE BOOL "" FORCE)
607+
set(ADIOS2_USE_Blosc2 OFF CACHE BOOL "" FORCE)
608+
set(ADIOS2_USE_SZ OFF CACHE BOOL "" FORCE)
609+
set(ADIOS2_USE_ZFP OFF CACHE BOOL "" FORCE)
610+
set(ADIOS2_USE_PNG OFF CACHE BOOL "" FORCE)
611+
set(ADIOS2_USE_Profiling OFF CACHE BOOL "" FORCE)
612+
set(ADIOS2_USE_Python OFF CACHE BOOL "" FORCE)
613+
614+
FetchContent_MakeAvailable(adios2)
615+
616+
else()
617+
# re-run non-QUIET so configuration fails with a clear error if the package
618+
# somehow became unavailable between the two calls
619+
find_package(adios2 REQUIRED)
620+
endif()
621+
622+
# In distributed builds link ADIOS2's MPI-enabled C++ interface: it defines
623+
# ADIOS2_USE_MPI, which exposes the adios2::ADIOS(MPI_Comm) constructor used in
624+
# qureg.cpp for collective per-rank I/O. The serial target lacks it.
625+
if (QUEST_ENABLE_MPI)
626+
target_link_libraries(QuEST PRIVATE adios2::cxx_mpi)
627+
else()
628+
target_link_libraries(QuEST PRIVATE adios2::cxx)
629+
endif()
630+
set(CMAKE_INSTALL_RPATH_USE_LINK_PATH ON)
631+
endif()
632+
633+
634+
546635
# ===============================
547636
# Set options to save in config.h
548637
# ===============================
@@ -553,6 +642,7 @@ set(QUEST_COMPILE_OMP ${QUEST_ENABLE_OMP})
553642
set(QUEST_COMPILE_MPI ${QUEST_ENABLE_MPI})
554643
set(QUEST_COMPILE_SUBCOMM ${QUEST_ENABLE_SUBCOMM})
555644
set(QUEST_COMPILE_CUQUANTUM ${QUEST_ENABLE_CUQUANTUM})
645+
set(QUEST_COMPILE_ADIOS2 ${QUEST_ENABLE_ADIOS2})
556646
set(QUEST_INCLUDE_DEPRECATED_FUNCTIONS ${QUEST_ENABLE_DEPRECATED_API})
557647

558648

‎docs/cmake.md‎

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,8 @@ make
4444
| `QUEST_ENABLE_CUDA` | (`OFF`), `ON` | Determines whether QuEST will be built with support for NVIDIA GPU acceleration. If turned on, `CMAKE_CUDA_ARCHITECTURES` should probably also be set. |
4545
| `QUEST_ENABLE_CUQUANTUM` | (`OFF`), `ON` | Determines whether QuEST will make use of the NVIDIA CuQuantum library. Cannot be turned on if `QUEST_ENABLE_CUDA` is off. |
4646
| `QUEST_ENABLE_HIP` | (`OFF`), `ON` | Determines whether QuEST will be built with support for AMD GPU acceleration. If turned on, `CMAKE_HIP_ARCHITECTURES` should probably also be set. |
47+
| `QUEST_ENABLE_ADIOS2` | (`OFF`), `ON` | Determines whether QuEST will be built with ADIOS2 to enable checkpointing, via functions `saveQuregToFile()` and `createQuregFromFile()`. |
48+
| `QUEST_DOWNLOAD_ADIOS2` | (`ON`), `OFF` | Determines whether to download ADIOS2 from Github, when ADIOS2 is enabled but not found. |
4749
| `QUEST_ENABLE_DEPRECATED_API` | (`OFF`), `ON` | Determines whether QuEST will be built with support for the deprecated (v3) API. ***Note**: this will generate compiler warnings and is not supported by MSVC.* |
4850
| `QUEST_DISABLE_DEPRECATION_WARNINGS` | (`OFF`), `ON` | Whether to disable the compile-time deprecation warnings when using the deprecated (v3) API. |
4951
| `USER_SOURCE_NAMES` | (Undefined), String | The source file for a user program which will be compiled alongside QuEST. `USER_OUTPUT_EXE_NAME` *must* also be defined. |

‎docs/compile.md‎

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,7 @@ Compiling is configured with variables supplied by the [`-D` flag](https://cmake
4545
> - <a href="#compile_cuquantum">cuQuantum</a>
4646
> - <a href="#compile_distribution">Distribution</a>
4747
> - <a href="#compile_multi-gpu">Multi-GPU</a>
48+
> - <a href="#compile_checkpointing">Checkpointing</a>
4849
4950
> **See also**:
5051
> - [`cmake.md`](cmake.md) for the full list of passable compiler variables.
@@ -689,3 +690,32 @@ Note that distributed executables are launched in a distinct way to the other de
689690
> - UCX
690691
> - launch flags
691692
> - checking via reportenv
693+
694+
695+
696+
697+
------------------
698+
699+
700+
<!-- permit doxygen to reference section -->
701+
<a id="compile_checkpointing"></a>
702+
703+
## Checkpointing
704+
705+
QuEST has optional facilities for _checkpointing_ a `Qureg`; writing its state to a file with [`saveQuregToFile()`](https://quest-kit.github.io/QuEST/group__experimental.html#gaf9a1aec34fdfdb3c650dc60e5a8ac9d9), to be later restored into a new `Qureg` with [`createQuregFromFile()`](https://quest-kit.github.io/QuEST/group__experimental.html#gab1ebe89e2ff15470fa340d4c2ced5703). This is useful for long-running jobs which risk timeout or failure - an evolving `Qureg` can be periodically saved and resumed in a subsequent process.
706+
707+
Checkpointing is built upon [ADIOS2](https://github.com/ornladios/ADIOS2) and is _disabled_ by default. To enable it, simply specify `QUEST_ENABLE_ADIOS2` at configuration:
708+
```bash
709+
# configure
710+
cmake .. -D QUEST_ENABLE_ADIOS2=ON
711+
712+
# build
713+
cmake --build . --parallel
714+
```
715+
716+
If a compatible ADIOS2 is not found, it will be automatically downloaded and installed from the ADIOS2 [Github](https://github.com/ornladios/ADIOS2), unless `QUEST_DOWNLOAD_ADIOS2` is overridden to be `OFF`. If an existing ADIOS2 is installed in a non-standard location (such as `~/.local`), pass its prefix via [`CMAKE_PREFIX_PATH`](https://cmake.org/cmake/help/latest/variable/CMAKE_PREFIX_PATH.html):
717+
> ```bash
718+
> cmake .. -D QUEST_ENABLE_ADIOS2=ON -D CMAKE_PREFIX_PATH=$HOME/.local
719+
> ```
720+
721+
Calling `saveQuregToFile()` or `createQuregFromFile()` in a build _without_ checkpointing enabled will trigger a runtime validation error.

‎quest/include/config.h.in‎

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,7 @@
4141
defined(QUEST_COMPILE_CUDA) || \
4242
defined(QUEST_COMPILE_HIP) || \
4343
defined(QUEST_COMPILE_CUQUANTUM) || \
44+
defined(QUEST_COMPILE_ADIOS2) || \
4445
defined(QUEST_ENABLE_NUMA) || \
4546
defined(QUEST_INCLUDE_DEPRECATED_FUNCTIONS) || \
4647
defined(QUEST_DISABLE_DEPRECATION_WARNINGS)
@@ -84,6 +85,7 @@
8485
#cmakedefine01 QUEST_COMPILE_CUDA
8586
#cmakedefine01 QUEST_COMPILE_CUQUANTUM
8687
#cmakedefine01 QUEST_COMPILE_HIP
88+
#cmakedefine01 QUEST_COMPILE_ADIOS2
8789

8890

8991
// crucial to QuEST source (informs optional NUMA usage)
@@ -125,6 +127,7 @@
125127
! defined(QUEST_COMPILE_CUDA) || \
126128
! defined(QUEST_COMPILE_HIP) || \
127129
! defined(QUEST_COMPILE_CUQUANTUM) || \
130+
! defined(QUEST_COMPILE_ADIOS2) || \
128131
! defined(QUEST_ENABLE_NUMA) || \
129132
! defined(QUEST_INCLUDE_DEPRECATED_FUNCTIONS) || \
130133
! defined(QUEST_DISABLE_DEPRECATION_WARNINGS)
@@ -152,6 +155,7 @@
152155
! (QUEST_COMPILE_CUDA == 0 || QUEST_COMPILE_CUDA == 1) || \
153156
! (QUEST_COMPILE_HIP == 0 || QUEST_COMPILE_HIP == 1) || \
154157
! (QUEST_COMPILE_CUQUANTUM == 0 || QUEST_COMPILE_CUQUANTUM == 1) || \
158+
! (QUEST_COMPILE_ADIOS2 == 0 || QUEST_COMPILE_ADIOS2 == 1) || \
155159
! (QUEST_ENABLE_NUMA == 0 || QUEST_ENABLE_NUMA == 1) || \
156160
! (QUEST_INCLUDE_DEPRECATED_FUNCTIONS == 0 || QUEST_INCLUDE_DEPRECATED_FUNCTIONS == 1) || \
157161
! (QUEST_DISABLE_DEPRECATION_WARNINGS == 0 || QUEST_DISABLE_DEPRECATION_WARNINGS == 1)

0 commit comments

Comments
 (0)