Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
37 commits
Select commit Hold shift + click to select a range
1c87a3c
Added ENABLE_SUBCOMM build option
otbrown Feb 27, 2026
19ac320
Moved from MPI_COMM_WORLD to mpiQuestComm
otbrown Feb 27, 2026
95415b7
Decided passing *MPI_Comm was probably overly cautious, and updated f…
otbrown Feb 27, 2026
0699e58
environment.cpp: added methods to reset rank and numNodes, and report…
otbrown Feb 27, 2026
bfec279
comm_config.hpp/cpp: added comm_setMpiComm
otbrown Feb 27, 2026
3a3bdff
CMakeLists.txt: PUBLIC MPI::MPI_CXX turned out to be unhelpful, even …
otbrown Mar 2, 2026
3358581
Added new custom QuESTEnv initialiser which allow user to positively …
otbrown Mar 2, 2026
6a093d0
validation.cpp: updated comm_end call
otbrown Mar 2, 2026
727d1bc
Merge branch 'devel' into mpi-update
otbrown Mar 2, 2026
588b636
comm_config.hpp: added config.h include so COMPILE_MPI is actually de…
otbrown Mar 6, 2026
7c6caac
subcommunicator.h/cpp: implemented QuESTEnv initialiser with custom M…
otbrown Mar 9, 2026
e6628e4
CMake: added subcommunicator.cpp
otbrown Mar 9, 2026
bb2d5f2
comm_config.hpp: added missing config.h include...
otbrown Mar 9, 2026
7c30b8c
comm_config.cpp: explicitly initialise mpiCommQuest to MPI_COMM_NULL,…
otbrown Mar 9, 2026
7512e67
Merge branch 'mpi-update' of github.com:otbrown/QuEST into mpi-update
otbrown Mar 9, 2026
cb72846
quest.h: added subcommunicator header
otbrown Mar 9, 2026
7ff2a2e
CMake: added MPI to application binaries when SUBCOMM is enabled
otbrown Mar 9, 2026
13769be
Merge branch 'devel' into mpi-update
otbrown Apr 13, 2026
68e435b
comm_routines.cpp: post Irecv before Isend which probably won't do an…
otbrown Apr 13, 2026
f15def4
tests: added new env test for initCustomMpiQuESTEnv
otbrown Apr 13, 2026
dbe2b1e
Added error throws to comm_config to cover new scenarios of badness w…
otbrown Apr 13, 2026
bf62480
subcommunicator.cpp: updated var names to match QuEST style
otbrown May 4, 2026
f26ae47
Merge branch 'devel' into mpi-update
otbrown May 4, 2026
6edbd1c
Merge branch devel
otbrown May 12, 2026
ea23f30
tests/unit/initialisations.cpp: slightly modified setQuregAmps test t…
otbrown May 13, 2026
142db02
Updated validation in comm_setMpiComm
otbrown May 13, 2026
d9d2369
userOwnsMpi int->bool
otbrown May 13, 2026
20d2a9b
comm_config.cpp: corrected call to MPI_Comm_free
otbrown May 14, 2026
562b883
subcommunicator.cpp: userOwnsMpi int->bool
otbrown May 14, 2026
beb1a61
subcommunicator.cpp: added comm_isInit guard around comm_setMpiComm
otbrown May 15, 2026
34a8083
environment.cpp: USER_OWNS_MPI -> userOwnsMpi
otbrown May 15, 2026
1fe9740
comm_init: fixed case where useDistrib = 0 and userOwnsMpi = true
otbrown May 15, 2026
226e653
comm_init: moved (recently) misplaced MPI_Init
otbrown May 15, 2026
70efc1f
Merge remote-tracking branch 'origin/devel' into mpi-update
otbrown May 18, 2026
87b8cd6
AUTHORS.txt: added iarejula-bsc
otbrown May 22, 2026
7894ade
Added placeholder docstrings to new initialisers
otbrown May 22, 2026
c768075
docs/cmake.md: added ENABLE_SUBCOMM to list of QuEST CMake vars
otbrown May 22, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 4 additions & 2 deletions AUTHORS.txt
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,8 @@ Dr Ian Bush [consultant]
HPC

External contributors:
Íñigo Aréjula Aísa
patched validation error in the experimental user-owned MPI interface (#722)
Daniel Expósito Patiño
patched the applyMultiStateControlledSqrtSwap C++ signature (#737)
Diogo Pratas Maia
Expand All @@ -70,8 +72,8 @@ SchineCompton
patched GPU Cmake Release build
Christopher J. Anders
patched Cmake build when multhithreading defaults off
revsied Cmake min version for GPU build
revised Cmake min version for GPU build
Gleb Struchalin
patched the cmake standalone build
Milos Prokop
implemented serial prototype of initDiagonalOpFromPauliHamil
implemented serial prototype of initDiagonalOpFromPauliHamil
17 changes: 17 additions & 0 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -145,6 +145,12 @@ option(
)
message(STATUS "Distribution is turned ${ENABLE_DISTRIBUTION}. Set ENABLE_DISTRIBUTION to modify.")

option(
ENABLE_SUBCOMM
"Whether QuEST will be built with support for restricting it to a user-defined MPI communicator. Turned OFF by default."
OFF
)
message(STATUS "Custom communicator support is turned ${ENABLE_SUBCOMM}. Set ENABLE_SUBCOMM to modify.")

# GPU Acceleration
option(
Expand Down Expand Up @@ -207,6 +213,9 @@ if (ENABLE_CUQUANTUM AND NOT ENABLE_CUDA)
message(FATAL_ERROR "Use of cuQuantum requires CUDA.")
endif()

if (ENABLE_SUBCOMM AND NOT ENABLE_DISTRIBUTION)
message(FATAL_ERROR "Distribution must be enabled to make use of a user-defined communicator for QuEST.")
endif()

if(WIN32)

Expand Down Expand Up @@ -402,8 +411,11 @@ endif()
# MPI
if (ENABLE_DISTRIBUTION)
find_package(MPI REQUIRED
# Component CXX is the C api usable from C++
# NOT the deprecated C++ API
COMPONENTS CXX
)

target_link_libraries(QuEST
PRIVATE
MPI::MPI_CXX
Expand Down Expand Up @@ -476,6 +488,7 @@ endif()
# set vars which will be written to config.h.in (auto-converted to 0 or 1)
set(COMPILE_OPENMP ${ENABLE_MULTITHREADING})
set(COMPILE_MPI ${ENABLE_DISTRIBUTION})
set(COMPILE_SUBCOMM ${ENABLE_SUBCOMM})
set(COMPILE_CUQUANTUM ${ENABLE_CUQUANTUM})
set(INCLUDE_DEPRECATED_FUNCTIONS ${ENABLE_DEPRECATED_API})

Expand Down Expand Up @@ -530,6 +543,10 @@ add_executable(min_example
)
target_link_libraries(min_example PRIVATE QuEST::QuEST)

if (ENABLE_DISTRIBUTION AND ENABLE_SUBCOMM)
target_link_libraries(min_example PRIVATE MPI::MPI_CXX)
endif()

if (INSTALL_BINARIES)
install(TARGETS min_example
RUNTIME
Expand Down
1 change: 1 addition & 0 deletions docs/cmake.md
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@ make
| `INSTALL_BINARIES` | (`OFF`), `ON` | Determines whether compiled binaries such as the examples will be installed as well as the QuEST library. |
| `ENABLE_MULTITHREADING` | (`ON`), `OFF` | Determines whether QuEST will be built with support for parallelisation with OpenMP. |
| `ENABLE_DISTRIBUTION` | (`OFF`), `ON` | Determines whether QuEST will be built with support for parallelisation with MPI. |
| `ENABLE_SUBCOMM` | (`OFF`), `ON` | Determines whether QuEST will be built with support for custom MPI communicators. _**Note**: This has the unfortunate side-effect of requiring the MPI header in the public header for QuEST, meaning MPI will become a dependency of any application or library which includes the QuEST header whether it uses MPI or not._ |
| `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. |
| `ENABLE_CUQUANTUM` | (`OFF`), `ON` | Determines whether QuEST will make use of the NVIDIA CuQuantum library. Cannot be turned on if `ENABLE_CUDA` is off. |
| `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. |
Expand Down
4 changes: 4 additions & 0 deletions examples/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,10 @@ function(add_example direc in_fn)
add_executable(${target} ${in_fn})
target_link_libraries(${target} PUBLIC QuEST)

if (ENABLE_DISTRIBUTION AND ENABLE_SUBCOMM)
target_link_libraries(${target} PRIVATE MPI::MPI_CXX)
endif()

if (INSTALL_BINARIES)
install(
TARGETS ${target}
Expand Down
4 changes: 4 additions & 0 deletions quest/include/config.h.in
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@
#if defined(FLOAT_PRECISION) || \
defined(COMPILE_OPENMP) || \
defined(COMPILE_MPI) || \
defined(COMPILE_SUBCOMM) || \
defined(COMPILE_CUDA) || \
defined(COMPILE_HIP) || \
defined(COMPILE_CUQUANTUM) || \
Expand Down Expand Up @@ -79,6 +80,7 @@
// crucial to QuEST source (informs external library usage)
#cmakedefine01 COMPILE_OPENMP
#cmakedefine01 COMPILE_MPI
#cmakedefine01 COMPILE_SUBCOMM
#cmakedefine01 COMPILE_CUDA
#cmakedefine01 COMPILE_CUQUANTUM

Expand Down Expand Up @@ -118,6 +120,7 @@
#if ! defined(FLOAT_PRECISION) || \
! defined(COMPILE_OPENMP) || \
! defined(COMPILE_MPI) || \
! defined(COMPILE_SUBCOMM) || \
! defined(COMPILE_CUDA) || \
! defined(COMPILE_HIP) || \
! defined(COMPILE_CUQUANTUM) || \
Expand All @@ -144,6 +147,7 @@

#if ! (COMPILE_OPENMP == 0 || COMPILE_OPENMP == 1) || \
! (COMPILE_MPI == 0 || COMPILE_MPI == 1) || \
! (COMPILE_SUBCOMM == 0 || COMPILE_SUBCOMM == 1) || \
! (COMPILE_CUDA == 0 || COMPILE_CUDA == 1) || \
! (COMPILE_HIP == 0 || COMPILE_HIP == 1) || \
! (COMPILE_CUQUANTUM == 0 || COMPILE_CUQUANTUM == 1) || \
Expand Down
9 changes: 9 additions & 0 deletions quest/include/environment.h
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,8 @@
#ifndef ENVIRONMENT_H
#define ENVIRONMENT_H

#include <stdbool.h>

// enable invocation by both C and C++ binaries
#ifdef __cplusplus
extern "C" {
Expand All @@ -36,6 +38,7 @@ typedef struct {
int isMultithreaded;
int isGpuAccelerated;
int isDistributed;
bool userOwnsMpi;

// deployment modes which cannot be directly changed after compilation
int isCuQuantumEnabled;
Expand All @@ -61,6 +64,12 @@ void initQuESTEnv();
*/
void initCustomQuESTEnv(int useDistrib, int useGpuAccel, int useMultithread);

/** @notyetdoced
* Advanced initialiser which lets the user positively declare that they take responsibility for MPI.
* This means we assume they have called MPI_Init, and that they will call MPI_Finalize.
*/
void initCustomMpiQuESTEnv(int useDistrib, bool userOwnsMpi, int useGpuAccel, int useMultithread);
Comment thread
otbrown marked this conversation as resolved.

/// @notyetdoced
void finalizeQuESTEnv();

Expand Down
1 change: 1 addition & 0 deletions quest/include/quest.h
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,7 @@
#include "quest/include/operations.h"
#include "quest/include/paulis.h"
#include "quest/include/qureg.h"
#include "quest/include/subcommunicator.h"
#include "quest/include/matrices.h"
#include "quest/include/wrappers.h"

Expand Down
31 changes: 31 additions & 0 deletions quest/include/subcommunicator.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
#ifndef SUBCOMMUNICATOR_H
#define SUBCOMMUNICATOR_H

#include "quest/include/config.h"

#if COMPILE_MPI && COMPILE_SUBCOMM

#include <mpi.h>

#ifdef __cplusplus
extern "C" {
#endif

/** @notyetdoced
* Advanced initialiser which allows the user to provide an MPI communicator for QuEST to use.
* Use of this initialiser implies userOwnsMpi = true, (exposed by initCustomMpiQuESTEnv) and
* therefore that they have already initialised MPI, and they will call MPI_Finalize at the
* appropriate time.
*
* The user-provided MPI communicator undergoes the same validation procedure as any that QuEST
* would use, and so must contain a power-of-2 number of processes.
*/
void initCustomMpiCommQuESTEnv(MPI_Comm questComm, int useGpuAccel, int useMultithread);

#ifdef __cplusplus
}
#endif

#endif

#endif
3 changes: 2 additions & 1 deletion quest/src/api/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ target_sources(QuEST
operations.cpp
paulis.cpp
qureg.cpp
subcommunicator.cpp
trotterisation.cpp
types.cpp
)
)
42 changes: 30 additions & 12 deletions quest/src/api/environment.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -71,7 +71,7 @@ static bool hasEnvBeenFinalized = false;
*/


void validateAndInitCustomQuESTEnv(int useDistrib, int useGpuAccel, int useMultithread, const char* caller) {
void validateAndInitCustomQuESTEnv(int useDistrib, bool userOwnsMpi, int useGpuAccel, int useMultithread, const char* caller) {

// ensure that we are never re-initialising QuEST (even after finalize) because
// this leads to undefined behaviour in distributed mode, as per the MPI
Expand All @@ -93,8 +93,7 @@ void validateAndInitCustomQuESTEnv(int useDistrib, int useGpuAccel, int useMulti
// and before any GPU initialisation and validation, since we will
// perform that specifically upon the MPI-process-bound GPU(s). Further,
// we can make sure validation errors are reported only by the root node.
if (useDistrib)
comm_init();
comm_init(useDistrib, userOwnsMpi);

validate_newEnvDistributedBetweenPower2Nodes(caller);

Expand Down Expand Up @@ -145,6 +144,7 @@ void validateAndInitCustomQuESTEnv(int useDistrib, int useGpuAccel, int useMulti
globalEnvPtr->isMultithreaded = useMultithread;
globalEnvPtr->isGpuAccelerated = useGpuAccel;
globalEnvPtr->isDistributed = useDistrib;
globalEnvPtr->userOwnsMpi = userOwnsMpi;
globalEnvPtr->isCuQuantumEnabled = useCuQuantum;
globalEnvPtr->isGpuSharingEnabled = permitGpuSharing;

Expand All @@ -153,6 +153,11 @@ void validateAndInitCustomQuESTEnv(int useDistrib, int useGpuAccel, int useMulti
globalEnvPtr->numNodes = (useDistrib)? comm_getNumNodes() : 1;
}

void updateQuESTEnvDistInfo() {
globalEnvPtr->rank = (globalEnvPtr->isDistributed)? comm_getRank() : 0;
globalEnvPtr->numNodes = (globalEnvPtr->isDistributed)? comm_getNumNodes() : 1;
return;
}


/*
Expand Down Expand Up @@ -187,10 +192,11 @@ void printCompilationInfo() {

print_table(
"compilation", {
{"isMpiCompiled", comm_isMpiCompiled()},
{"isGpuCompiled", gpu_isGpuCompiled()},
{"isOmpCompiled", cpu_isOpenmpCompiled()},
{"isCuQuantumCompiled", gpu_isCuQuantumCompiled()},
{"isMpiCompiled", comm_isMpiCompiled()},
{"isMpiSubCommunicatorCompiled", comm_isMpiSubCommunicatorCompiled()},
{"isGpuCompiled", gpu_isGpuCompiled()},
{"isOmpCompiled", cpu_isOpenmpCompiled()},
{"isCuQuantumCompiled", gpu_isCuQuantumCompiled()},
});
}

Expand All @@ -200,6 +206,7 @@ void printDeploymentInfo() {
print_table(
"deployment", {
{"isMpiEnabled", globalEnvPtr->isDistributed},
{"doesUserOwnMpi", globalEnvPtr->userOwnsMpi},
{"isGpuEnabled", globalEnvPtr->isGpuAccelerated},
{"isOmpEnabled", globalEnvPtr->isMultithreaded},
{"isCuQuantumEnabled", globalEnvPtr->isCuQuantumEnabled},
Expand Down Expand Up @@ -397,13 +404,19 @@ extern "C" {

void initCustomQuESTEnv(int useDistrib, int useGpuAccel, int useMultithread) {

validateAndInitCustomQuESTEnv(useDistrib, useGpuAccel, useMultithread, __func__);
const bool userOwnsMpi = false;
validateAndInitCustomQuESTEnv(useDistrib, userOwnsMpi, useGpuAccel, useMultithread, __func__);
}


void initCustomMpiQuESTEnv(int useDistrib, bool userOwnsMpi, int useGpuAccel, int useMultithread) {
validateAndInitCustomQuESTEnv(useDistrib, userOwnsMpi, useGpuAccel, useMultithread, __func__);
}

void initQuESTEnv() {

validateAndInitCustomQuESTEnv(modeflag::USE_AUTO, modeflag::USE_AUTO, modeflag::USE_AUTO, __func__);
const bool userOwnsMpi = false;
validateAndInitCustomQuESTEnv(modeflag::USE_AUTO, userOwnsMpi, modeflag::USE_AUTO, modeflag::USE_AUTO, __func__);
}


Expand Down Expand Up @@ -436,7 +449,7 @@ void finalizeQuESTEnv() {

if (globalEnvPtr->isDistributed) {
comm_sync();
comm_end();
comm_end(globalEnvPtr->userOwnsMpi);
}

// free global env's heap memory and flag it as unallocated
Expand All @@ -454,8 +467,12 @@ void syncQuESTEnv() {
if (globalEnvPtr->isGpuAccelerated)
gpu_sync();

if (globalEnvPtr->isDistributed)
if (globalEnvPtr->isDistributed) {
comm_sync();
#if COMPILE_SUBCOMM
updateQuESTEnvDistInfo();
#endif
}
}


Expand Down Expand Up @@ -498,10 +515,11 @@ void getEnvironmentString(char str[200]) {
int cuQuantum = env.isGpuAccelerated && gpu_isCuQuantumCompiled();
int gpuDirect = env.isGpuAccelerated && gpu_isDirectGpuCommPossible();

snprintf(str, 200, "CUDA=%d OpenMP=%d MPI=%d threads=%d ranks=%d cuQuantum=%d gpuDirect=%d",
snprintf(str, 200, "CUDA=%d OpenMP=%d MPI=%d userOwnsMPI=%d threads=%d ranks=%d cuQuantum=%d gpuDirect=%d",
env.isGpuAccelerated,
env.isMultithreaded,
env.isDistributed,
env.userOwnsMpi,
numThreads,
env.numNodes,
cuQuantum,
Expand Down
31 changes: 31 additions & 0 deletions quest/src/api/subcommunicator.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
#include "quest/include/config.h"
#include "quest/include/environment.h"
#include "quest/include/subcommunicator.h"

#include "quest/src/comm/comm_config.hpp"
#include "quest/src/core/errors.hpp"

#if COMPILE_MPI && COMPILE_SUBCOMM

#include <stdbool.h>
#include <mpi.h>

void initCustomMpiCommQuESTEnv(MPI_Comm userQuestComm, int useGpuAccel, int useMultithread) {
// useDistrib and userOwnsMpi are implied by the user of this initialiser
const int useDistrib = 1;
const bool userOwnsMpi = true;

// set mpiCommQuest to user provided communicator
if (comm_isInit()) {
comm_setMpiComm(userQuestComm);
} else {
error_commNotInit();
}

// initialise QuEST around that communicator
initCustomMpiQuESTEnv(useDistrib, userOwnsMpi, useGpuAccel, useMultithread);
Comment thread
otbrown marked this conversation as resolved.

return;
}

#endif
Loading
Loading