Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

v3.7.0 #387

Merged
merged 25 commits into from
Sep 22, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
25 commits
Select commit Hold shift + click to select a range
a23f518
scaffolded cuQuantum build
TysonRayJones Aug 17, 2023
9e2f3ce
prevent CI on working branches (#371)
TysonRayJones Aug 19, 2023
40f936f
proposing cuQuantum memory design
TysonRayJones Aug 19, 2023
240d5ab
setup automatic workspace memory
TysonRayJones Aug 19, 2023
ec08912
added type adapters
TysonRayJones Aug 19, 2023
bb38e38
added wrapped operators
TysonRayJones Aug 19, 2023
7b7c197
added Thrust
TysonRayJones Aug 20, 2023
f06aae3
added unit-test init-state check
TysonRayJones Aug 24, 2023
d34dc21
removed obsolete doc folder
TysonRayJones Aug 24, 2023
2c465c2
removed defunct debugging routines
TysonRayJones Aug 24, 2023
564851e
added state initialisers
TysonRayJones Aug 24, 2023
67153b9
added wrapped decoherence
TysonRayJones Aug 20, 2023
d616481
added bespoke decoherence
TysonRayJones Aug 24, 2023
b047972
optimised diagonal operators
TysonRayJones Aug 24, 2023
14b0a59
added calculations
TysonRayJones Sep 19, 2023
7e2362a
added phase functions
TysonRayJones Sep 20, 2023
f7c6ee6
fixed automatic workspace memory
TysonRayJones Sep 20, 2023
c8d9d77
moved reportStateToScreen to common
TysonRayJones Sep 20, 2023
f7515b0
added cuQuantum to doc
TysonRayJones Sep 20, 2023
c63a0f8
Merge pull request #386 from QuEST-Kit/cuquantum
TysonRayJones Sep 20, 2023
aa5ccd1
Made MPI calls in exchangeStateVectors non-blocking
Sep 1, 2023
8415f64
added Jakub Adamski to authorlist
TysonRayJones Sep 21, 2023
d3022a6
improved test getRandomUnitary
TysonRayJones Sep 21, 2023
3d8b6b7
adding random unitary failsafe
TysonRayJones Sep 21, 2023
29824c7
improved unitarity & CPTP validation
TysonRayJones Sep 21, 2023
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
The table of contents is too big for display.
Diff view
Diff view
  •  
  •  
  •  
3 changes: 2 additions & 1 deletion .github/workflows/coverage.yml
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,8 @@ on:
- develop
pull_request:
branches:
- '**'
- master
- develop

jobs:

Expand Down
3 changes: 2 additions & 1 deletion .github/workflows/llvm-asan.yml
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,8 @@ on:
- develop
pull_request:
branches:
- '**'
- master
- develop

jobs:

Expand Down
3 changes: 2 additions & 1 deletion .github/workflows/macos-unit.yml
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,8 @@ on:
- develop
pull_request:
branches:
- '**'
- master
- develop

jobs:

Expand Down
3 changes: 2 additions & 1 deletion .github/workflows/ubuntu-unit.yml
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,8 @@ on:
- develop
pull_request:
branches:
- '**'
- master
- develop

jobs:

Expand Down
3 changes: 2 additions & 1 deletion .github/workflows/windows-build.yml
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,8 @@ on:
- develop
pull_request:
branches:
- '**'
- master
- develop

jobs:

Expand Down
3 changes: 2 additions & 1 deletion .github/workflows/windows-unit.yml
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,8 @@ on:
- develop
pull_request:
branches:
- '**'
- master
- develop

jobs:

Expand Down
2 changes: 2 additions & 0 deletions AUTHORS.txt
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,8 @@ Dr Mihai Duta [developer]
original prototyping

External contributors:
Jakub Adamski
optimised distributed communication by sending max-size messages asynchronously
Bruno Villasenor Alvarez on behalf of AMD
ported the GPU backend to HIP, for AMD GPU compatibility
Dr Nicolas Vogt on behalf of HQS Quantum Simulations
Expand Down
53 changes: 36 additions & 17 deletions QuEST/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,8 @@ option(USE_HIP "Whether to use HIP for GPU code compilation for AMD GPUs. Set to

set(GPU_ARCH gfx90 CACHE STRING "GPU hardware dependent, used for AMD GPUs when USE_HIP=1. Lookup at https://llvm.org/docs/AMDGPUUsage.html#amdgpu-processor-table. Write without fullstop")

option(USE_CUQUANTUM "Whether to use NVIDIA's cuQuantum library (requires prior installation) in lieu of QuEST's bespoke GPU kernel. Set to 1 to enable." 0)


# *****************************************************************************
# ***** NO CHANGES SHOULD BE REQUIRED FROM THE USER BEYOND THIS POINT *********
Expand All @@ -49,6 +51,7 @@ message(STATUS "OMP acceleration is ${MULTITHREADED}")
message(STATUS "MPI distribution is ${DISTRIBUTED}")
if (${GPUACCELERATED})
message(STATUS "HIP compilation is ${USE_HIP}")
message(STATUS "cuQuantum compilation is ${USE_CUQUANTUM}")
endif()


Expand Down Expand Up @@ -119,25 +122,28 @@ endif()
if (GPUACCELERATED)
if (USE_HIP)

if(NOT DEFINED HIP_PATH)
if(NOT DEFINED ENV{HIP_PATH})
message(WARNING "WARNING: HIP_PATH is not defiend. Using default HIP_PATH=/opt/rocm/hip " ${HIP_VERSION})
set(HIP_PATH "/opt/rocm/hip" CACHE PATH "Path to which HIP has been installed")
else()
set(HIP_PATH $ENV{HIP_PATH} CACHE PATH "Path to which HIP has been installed")
if(NOT DEFINED HIP_PATH)
if(NOT DEFINED ENV{HIP_PATH})
message(WARNING "WARNING: HIP_PATH is not defiend. Using default HIP_PATH=/opt/rocm/hip " ${HIP_VERSION})
set(HIP_PATH "/opt/rocm/hip" CACHE PATH "Path to which HIP has been installed")
else()
set(HIP_PATH $ENV{HIP_PATH} CACHE PATH "Path to which HIP has been installed")
endif()
endif()
endif()

if(EXISTS "${HIP_PATH}")
set(CMAKE_MODULE_PATH "${HIP_PATH}/cmake" ${CMAKE_MODULE_PATH})
find_package(HIP REQUIRED)
message(STATUS "Found HIP: " ${HIP_VERSION})
message(STATUS "HIP PATH: " ${HIP_PATH})
endif()

ADD_DEFINITIONS( -DUSE_HIP )
ADD_DEFINITIONS( -D__HIP_PLATFORM_AMD__ )
if(EXISTS "${HIP_PATH}")
set(CMAKE_MODULE_PATH "${HIP_PATH}/cmake" ${CMAKE_MODULE_PATH})
find_package(HIP REQUIRED)
message(STATUS "Found HIP: " ${HIP_VERSION})
message(STATUS "HIP PATH: " ${HIP_PATH})
endif()
ADD_DEFINITIONS( -DUSE_HIP )
ADD_DEFINITIONS( -D__HIP_PLATFORM_AMD__ )

elseif (USE_CUQUANTUM)
find_package(CUDA REQUIRED)
ADD_DEFINITIONS( -DUSE_CUQUANTUM )
else()
find_package(CUDA REQUIRED)
endif()
Expand Down Expand Up @@ -280,7 +286,12 @@ endif()
# ----- C++ COMPILER FLAGS --------------------------------------------------

# set C++ flags that are common between compilers and build types
set (CMAKE_CXX_STANDARD 98)
if (USE_CUQUANTUM)
set(CMAKE_CXX_STANDARD 14)
set(CMAKE_CXX_STANDARD_REQUIRED ON)
else ()
set (CMAKE_CXX_STANDARD 98)
endif ()

# Use -O2 for all but debug mode by default
if (NOT("${CMAKE_BUILD_TYPE}" STREQUAL "Debug"))
Expand Down Expand Up @@ -412,6 +423,14 @@ target_link_libraries(QuEST PUBLIC ${MPI_C_LIBRARIES})
# ----- GPU -------------------------------------------------------------------
if (USE_HIP)
target_link_libraries(QuEST PUBLIC ${HIP_PATH}/lib/libamdhip64.so )
elseif (USE_CUQUANTUM)
find_library(CUQUANTUM_LIBRARIES custatevec)
if (NOT CUQUANTUM_LIBRARIES)
message(FATAL_ERROR "cuQuantum library (specifically custatevec) not found")
endif ()

target_link_libraries(QuEST ${CUDA_LIBRARIES} ${CUQUANTUM_LIBRARIES})
target_include_directories(QuEST PUBLIC "/usr/local/cuda/include")
else()
target_link_libraries(QuEST ${CUDA_LIBRARIES})
endif()
Expand Down
30 changes: 30 additions & 0 deletions QuEST/include/QuEST.h
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,23 @@

# include "QuEST_precision.h"



// ensure custatevecHandle_t is defined, even if no GPU
# ifdef USE_CUQUANTUM
# include <custatevec.h>
typedef struct CuQuantumConfig {
cudaMemPool_t cuMemPool;
cudaStream_t cuStream;
custatevecHandle_t cuQuantumHandle;
custatevecDeviceMemHandler_t cuMemHandler;
} CuQuantumConfig;
# else
# define CuQuantumConfig void*
# endif



// prevent C++ name mangling
#ifdef __cplusplus
extern "C" {
Expand Down Expand Up @@ -368,6 +385,11 @@ typedef struct Qureg
//! Storage for reduction of probabilities on GPU
qreal *firstLevelReduction, *secondLevelReduction;

//! Storage for wavefunction amplitues and config (copy of QuESTEnv's handle) in cuQuantum deployment
cuAmp* cuStateVec;
cuAmp* deviceCuStateVec;
CuQuantumConfig* cuConfig;

//! Storage for generated QASM output
QASMLogger* qasmLog;

Expand All @@ -386,6 +408,10 @@ typedef struct QuESTEnv
int numRanks;
unsigned long int* seeds;
int numSeeds;

// a copy of the QuESTEnv's config, used only in cuQuantum deployment
CuQuantumConfig* cuConfig;

} QuESTEnv;


Expand Down Expand Up @@ -4236,6 +4262,10 @@ qreal calcPurity(Qureg qureg);
* linear algebra calculation.
*
* The number of qubits represented in \p qureg and \p pureState must match.
*
* > In the GPU-accelerated cuQuantum backend, this function further assumes that
* > the density matrix \p qureg is correctly normalised, and otherwise returns the
* > fidelity of the conjugate-transpose of \p qureg.
*
* @see
* - calcHilbertSchmidtDistance()
Expand Down
23 changes: 19 additions & 4 deletions QuEST/include/QuEST_precision.h
Original file line number Diff line number Diff line change
Expand Up @@ -10,15 +10,27 @@
* @author Tyson Jones (doc)
*/

# include <math.h>

# ifndef QUEST_PRECISION_H
# define QUEST_PRECISION_H

# include <math.h>


// define CUDA complex types as void if not using cuQuantum.
// note we used cuComplex.h for complex numbers, in lieu of
// Thrust's complex<qreal>, so that the QuEST.h header can
// always be compiled with C99, rather than C++14.
# ifdef USE_CUQUANTUM
# include <cuComplex.h>
# else
# define cuFloatComplex void
# define cuDoubleComplex void
# endif


// set default double precision if not set during compilation
# ifndef QuEST_PREC
# define QuEST_PREC 2
# define QuEST_PREC 2
# endif


Expand All @@ -28,6 +40,7 @@
# if QuEST_PREC==1
# define qreal float
// \cond HIDDEN_SYMBOLS
# define cuAmp cuFloatComplex
# define MPI_QuEST_REAL MPI_FLOAT
# define MPI_MAX_AMPS_IN_MSG (1LL<<29) // must be 2^int
# define REAL_STRING_FORMAT "%.8f"
Expand All @@ -41,7 +54,8 @@
*/
# elif QuEST_PREC==2
# define qreal double
// \cond HIDDEN_SYMBOLS
// \cond HIDDEN_SYMBOLS
# define cuAmp cuDoubleComplex
# define MPI_QuEST_REAL MPI_DOUBLE
# define MPI_MAX_AMPS_IN_MSG (1LL<<28) // must be 2^int
# define REAL_STRING_FORMAT "%.14f"
Expand All @@ -57,6 +71,7 @@
# elif QuEST_PREC==4
# define qreal long double
// \cond HIDDEN_SYMBOLS
# define cuAmp void // invalid
# define MPI_QuEST_REAL MPI_LONG_DOUBLE
# define MPI_MAX_AMPS_IN_MSG (1LL<<27) // must be 2^int
# define REAL_STRING_FORMAT "%.17Lf"
Expand Down
103 changes: 0 additions & 103 deletions QuEST/src/CPU/QuEST_cpu.c
Original file line number Diff line number Diff line change
Expand Up @@ -1641,53 +1641,6 @@ void statevec_cloneQureg(Qureg targetQureg, Qureg copyQureg) {
}
}

/**
* Initialise the state vector of probability amplitudes such that one qubit is set to 'outcome' and all other qubits are in an equal superposition of zero and one.
* @param[in,out] qureg object representing the set of qubits to be initialised
* @param[in] qubitId id of qubit to set to state 'outcome'
* @param[in] outcome of qubit 'qubitId'
*/
void statevec_initStateOfSingleQubit(Qureg *qureg, int qubitId, int outcome)
{
long long int chunkSize, stateVecSize;
long long int index;
int bit;
long long int chunkId=qureg->chunkId;

// dimension of the state vector
chunkSize = qureg->numAmpsPerChunk;
stateVecSize = chunkSize*qureg->numChunks;
qreal normFactor = 1.0/sqrt((qreal)stateVecSize/2.0);

// Can't use qureg->stateVec as a private OMP var
qreal *stateVecReal = qureg->stateVec.real;
qreal *stateVecImag = qureg->stateVec.imag;

// initialise the state to |0000..0000>
# ifdef _OPENMP
# pragma omp parallel \
default (none) \
shared (chunkSize, stateVecReal, stateVecImag, normFactor, qubitId, outcome, chunkId) \
private (index, bit)
# endif
{
# ifdef _OPENMP
# pragma omp for schedule (static)
# endif
for (index=0; index<chunkSize; index++) {
bit = extractBit(qubitId, index+chunkId*chunkSize);
if (bit==outcome) {
stateVecReal[index] = normFactor;
stateVecImag[index] = 0.0;
} else {
stateVecReal[index] = 0.0;
stateVecImag[index] = 0.0;
}
}
}
}


/**
* Initialise the state vector of probability amplitudes to an (unphysical) state with
* each component of each probability amplitude a unique floating point value. For debugging processes
Expand Down Expand Up @@ -1726,62 +1679,6 @@ void statevec_initDebugState (Qureg qureg)
}
}

// returns 1 if successful, else 0
int statevec_initStateFromSingleFile(Qureg *qureg, char filename[200], QuESTEnv env){
long long int chunkSize, stateVecSize;
long long int indexInChunk, totalIndex;

chunkSize = qureg->numAmpsPerChunk;
stateVecSize = chunkSize*qureg->numChunks;

qreal *stateVecReal = qureg->stateVec.real;
qreal *stateVecImag = qureg->stateVec.imag;

FILE *fp;
char line[200];

for (int rank=0; rank<(qureg->numChunks); rank++){
if (rank==qureg->chunkId){
fp = fopen(filename, "r");

// indicate file open failure
if (fp == NULL)
return 0;

indexInChunk = 0; totalIndex = 0;
while (fgets(line, sizeof(char)*200, fp) != NULL && totalIndex<stateVecSize){
if (line[0]!='#'){
int chunkId = (int) (totalIndex/chunkSize);
if (chunkId==qureg->chunkId){
sscanf(line, REAL_SPECIFIER ", " REAL_SPECIFIER, &(stateVecReal[indexInChunk]),
&(stateVecImag[indexInChunk]));
indexInChunk += 1;
}
totalIndex += 1;
}
}
fclose(fp);
}
syncQuESTEnv(env);
}

// indicate success
return 1;
}

int statevec_compareStates(Qureg mq1, Qureg mq2, qreal precision){
qreal diff;
long long int chunkSize = mq1.numAmpsPerChunk;

for (long long int i=0; i<chunkSize; i++){
diff = absReal(mq1.stateVec.real[i] - mq2.stateVec.real[i]);
if (diff>precision) return 0;
diff = absReal(mq1.stateVec.imag[i] - mq2.stateVec.imag[i]);
if (diff>precision) return 0;
}
return 1;
}

void statevec_compactUnitaryLocal (Qureg qureg, int targetQubit, Complex alpha, Complex beta)
{
long long int sizeBlock, sizeHalfBlock;
Expand Down
Loading