diff --git a/.github/workflows/test_free.yml b/.github/workflows/test_free.yml index 3d3aace47..7efd540d3 100644 --- a/.github/workflows/test_free.yml +++ b/.github/workflows/test_free.yml @@ -54,10 +54,6 @@ jobs: build_dir: "build" depr_dir: "build/tests/deprecated" - # run all slow, rigorous tests (because runner is free) - num_qubit_perms: 0 - test_all_deploys: ON - # perform the job steps: - name: Get QuEST @@ -71,14 +67,13 @@ jobs: -DENABLE_MULTITHREADING=OFF -DENABLE_DEPRECATED_API=${{ matrix.version == 3 && 'ON' || 'OFF' }} -DFLOAT_PRECISION=${{ matrix.precision }} - -DTEST_ALL_DEPLOYMENTS=${{ env.test_all_deploys }} - -DTEST_MAX_NUM_QUBIT_PERMUTATIONS=${{ env.num_qubit_perms }} # force 'Release' build (needed by MSVC to enable optimisations) - name: Compile run: cmake --build ${{ env.build_dir }} --config Release --parallel - # run v4 unit tests in random order, excluding the integration tests + # run v4 unit tests in random order, excluding the integration tests, + # using the default environment variables (e.g. test all permutations) # TODO: # ctest currently doesn't know of our Catch2 tags, so we # are manually excluding each integration test by name diff --git a/.github/workflows/test_paid.yml b/.github/workflows/test_paid.yml index c8fe34c03..4c17d9439 100644 --- a/.github/workflows/test_paid.yml +++ b/.github/workflows/test_paid.yml @@ -90,7 +90,7 @@ jobs: # tests will be non-comprehensive/faster to save $$$ num_qubit_perms: 10 - test_all_deploys: OFF + test_all_deploys: 0 # perform the job steps: @@ -139,6 +139,12 @@ jobs: - name: Compile run: cmake --build ${{ env.build_dir }} --parallel + # specifying only env-vars with non-default values + - name: Configure tests with environment variables + run: | + echo "TEST_MAX_NUM_QUBIT_PERMUTATIONS=${{ env.num_qubit_perms }}" >> $GITHUB_ENV + echo "TEST_ALL_DEPLOYMENTS=${{ env.test_all_deploys }}" >> $GITHUB_ENV + # cannot use ctests when distributed, grr! - name: Run multithreaded + distributed v4 tests (16 nodes, 4 threads eeach) if: ${{ matrix.mpi == 'ON' }} @@ -206,11 +212,11 @@ jobs: # which will be shared between 4 MPI processes # (no --oversubscribe flag necessary on MPICH) num_mpi_nodes: 4 - mpi_share_gpu: ON + mpi_share_gpu: 1 # we will test all combinations of deployments # (e.g. CPU + MPI vs GPU), repeated 5 times each - test_all_deploys: ON + test_all_deploys: 1 test_repetitions: 5 # perform the job @@ -255,16 +261,17 @@ jobs: -DENABLE_CUDA=${{ matrix.cuda }} -DENABLE_CUQUANTUM=${{ matrix.cuquantum }} -DCMAKE_CUDA_ARCHITECTURES=${{ env.cuda_arch }} - -DTEST_ALL_DEPLOYMENTS=${{ env.test_all_deploys }} - -DTEST_NUM_MIXED_DEPLOYMENT_REPETITIONS=${{ env.test_repetitions }} -DCMAKE_CXX_FLAGS=${{ matrix.mpi == 'ON' && matrix.cuda == 'ON' && '-fno-lto' || '' }} - name: Compile run: cmake --build ${{ env.build_dir }} --parallel - # permit use of single GPU by multiple MPI processes (detriments performance) - - name: Set env-var to permit GPU sharing - run: echo "PERMIT_NODES_TO_SHARE_GPU=${{ env.mpi_share_gpu }}" >> $GITHUB_ENV + # specify only env-vars with non-default values + - name: Configure tests with environment variables + run: | + echo "TEST_ALL_DEPLOYMENTS=${{ env.test_all_deploys }}" >> $GITHUB_ENV + echo "TEST_NUM_MIXED_DEPLOYMENT_REPETITIONS=${{ env.test_repetitions }}" >> $GITHUB_ENV + echo "PERMIT_NODES_TO_SHARE_GPU=${{ env.mpi_share_gpu }}" >> $GITHUB_ENV # cannot use ctests when distributed, grr! - name: Run GPU + distributed v4 mixed tests (4 nodes sharing 1 GPU) diff --git a/CMakeLists.txt b/CMakeLists.txt index 33e2dff42..933e23086 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -123,65 +123,6 @@ option( ON ) -string(CONCAT DESCRIPTON_OF_TEST_MAX_NUM_QUBIT_PERMUTATIONS # for multiline description - "The maximum number of control and target qubit permutations under which to unit test each function. " - "Set to 0 (default) to test all permutations, or to a positive integer (e.g. 50) to accelerate the unit tests. " - "This is used to accelerate the v4 unit tests, and has no effect when ENABLE_TESTING is OFF, nor on the v3 deprecated tests." -) -set(TEST_MAX_NUM_QUBIT_PERMUTATIONS 0 - CACHE - STRING - "${DESCRIPTON_OF_TEST_MAX_NUM_QUBIT_PERMUTATIONS}" -) -if (ENABLE_TESTING) - set(PERM_STRING "${TEST_MAX_NUM_QUBIT_PERMUTATIONS} random") - if (TEST_MAX_NUM_QUBIT_PERMUTATIONS EQUAL 0) - set(PERM_STRING "all") - endif() - message(STATUS "Tests will use ${PERM_STRING} qubit permutations. Set TEST_MAX_NUM_QUBIT_PERMUTATIONS to modify.") -endif() - -string(CONCAT DESCRIPTON_OF_TEST_MAX_NUM_SUPEROP_TARGETS # for multiline description - "The maximum number of superoperator targets for which to unit test functions mixKrausMap and mixSuperOp. " - "This is computationally equivalent to simulating unitaries with double the number of targets upon a density matrix. " - "Set to 0 to test all sizes which is likely prohibitively slow, or to a positive integer (e.g. the default of 4) to accelerate the unit tests. " - "This is used to accelerate the v4 unit tests, and has no effect when ENABLE_TESTING is OFF, nor on the v3 deprecated tests." -) -set(TEST_MAX_NUM_SUPEROP_TARGETS 4 - CACHE - STRING - "${DESCRIPTON_OF_TEST_MAX_NUM_SUPEROP_TARGETS}" -) -if (ENABLE_TESTING) - set(PERM_STRING "${TEST_MAX_NUM_SUPEROP_TARGETS} random") - if (TEST_MAX_NUM_SUPEROP_TARGETS EQUAL 0) - set(PERM_STRING "all") - endif() - message(STATUS "Tests will use superoperators of up to ${PERM_STRING} qubits. Set TEST_MAX_NUM_SUPEROP_TARGETS to modify.") -endif() - -set(TEST_NUM_MIXED_DEPLOYMENT_REPETITIONS 10 - CACHE - STRING - "The number of times (minimum=1) to repeat each mixed-deployment unit test for each deployment combination." -) -if (ENABLE_TESTING) - if (TEST_NUM_MIXED_DEPLOYMENT_REPETITIONS LESS_EQUAL 0) - message(FATAL_ERROR "Cannot set TEST_NUM_MIXED_DEPLOYMENT_REPETITIONS <= 0. Must be at least 1.") - endif() - message(STATUS "Tests will repeat each mixed-deployment unit test ${TEST_NUM_MIXED_DEPLOYMENT_REPETITIONS} times. Set TEST_NUM_MIXED_DEPLOYMENT_REPETITIONS to modify.") -endif() - -string(CONCAT DESCRIPTION_OF_TEST_ALL_DEPLOYMENTS # for multiline description - "Whether unit tests will be run using all possible deployment combinations (i.e. OpenMP, CUDA, MPI) in-turn (ON), " - "or only once using all available deployments simultaneously (OFF). Turned ON by default. " - "This is used to accelerate the v4 unit tests, and has no effect when ENABLE_TESTING is OFF, nor on the v3 deprecated tests." -) -option(TEST_ALL_DEPLOYMENTS "${DESCRIPTION_OF_TEST_ALL_DEPLOYMENTS}" ON) -if (ENABLE_TESTING) - message(STATUS "Testing all deployments is turned ${TEST_ALL_DEPLOYMENTS}. Set TEST_ALL_DEPLOYMENTS to modify.") -endif() - # Multithreading option( ENABLE_MULTITHREADING diff --git a/docs/cmake.md b/docs/cmake.md index 5007553e3..336dcf28c 100644 --- a/docs/cmake.md +++ b/docs/cmake.md @@ -55,10 +55,8 @@ make | `ENABLE_TESTING` | (`OFF`), `ON` | Determines whether to additionally build QuEST's unit and integration tests. If built, tests can be run from the `build` directory with `make test`, or `ctest`, or manually launched with `./tests/tests` which enables distribution (i.e. `mpirun -np 8 ./tests/tests`) | | `ENABLE_DEPRECATED_API` | (`OFF`), `ON` | As described above. When enabled alongside testing, the `v3 deprecated` unit tests will additionally be compiled and can be run from within `build` via `cd tests/deprecated; ctest`, or manually launched with `./tests/deprecated/dep_tests` (enabling distribution, as above). | `DOWNLOAD_CATCH2` | (`ON`), `OFF` | QuEST's tests require Catch2. By default, if you don't have Catch2 installed (or CMake doesn't find it) it will be downloaded from Github and built for you. If you don't want that to happen, for example because you _do_ have Catch2 installed, set this to `OFF`. | -| `TEST_MAX_NUM_QUBIT_PERMUTATIONS` | (`0`), Integer | Determines the maximum number of control and target qubit permutations with which to test each API function. Set to `0` to test all permutations, or to a positive integer (e.g. `50`) to accelerate the unit tests. | -| `TEST_MAX_NUM_SUPEROP_TARGETS` | (`4`), Integer | Determines the maximum number of superoperator targets in the unit tests (for functions `mixKrausMap` and `mixSuperOp`). Set to `0` to impose no maximum (which is extraordinarily slow), or a positive integer (e.g. `3`) to accelerate the unit tests. | -| `TEST_NUM_MIXED_DEPLOYMENT_REPETITIONS` | (`10`), Integer | Determines the number of times (minimum of `1`) to repeat the randomised unit tests of functions which accept multiple distinctly-deployed `Qureg`s. Set to a small, positive integer to accelerate mixed-deployment unit tests. | -| `TEST_ALL_DEPLOYMENTS` | (`ON`), `OFF` | Determines whether unit tests will be repeatedly run using all possible combinations of available `Qureg` deployments (i.e. `OpenMP` and/or `CUDA` and/or `MPI`), else only once using all available deployments simultaneously. Set to `OFF` to accelerate unit tests. | + +> As of `v4.2`, macros which configure the unit tests such as `TEST_MAX_NUM_QUBIT_PERMUTATIONS` have become environment variables specified before launch. See [`launch.md`](launch.md) --------------------------- diff --git a/docs/launch.md b/docs/launch.md index 44a0f7fd7..a76ce612b 100644 --- a/docs/launch.md +++ b/docs/launch.md @@ -216,6 +216,21 @@ Test project /build Alas tests launched in this way cannot be deployed with distribution. +#### Environment variables + +The `v4` unit tests make use of the below, optional environment variables to control their rigour and runtime. + + +| Environment variable | Default | Description | +| -------- | ------- | ------- | +| `TEST_NUM_QUBITS_IN_QUREG` | `6` | The number of qubits in the Qureg(s) undergoing unit testing. In addition to operation upon larger Quregs being exponentially slower, beware that more qubits permit more variations and permutations of input parameters like target qubits, factorially increasing the number of tests per operation. | +| `TEST_MAX_NUM_QUBIT_PERMUTATIONS` | `0` | The maximum number of control and target qubit permutations under which to unit test each function. Set to `0` (default) to test all permutations, or to a positive integer (e.g. `50`) to accelerate the unit tests. See more info [here](https://quest-kit.github.io/QuEST/group__testutilsconfig.html#gac5adcc10bd26c56f20344f5ae3d9ba41). | +| `TEST_MAX_NUM_SUPEROP_TARGETS` | `4` | The maximum number of superoperator targets for which to unit test functions `mixKrausMap()` and `mixSuperOp()`. These are computationally equivalent to simulating unitaries with double the number of targets upon a density matrix. Set to `0` to test all sizes which is likely prohibitively slow, or to a positive integer (e.g. the default of `4`) to accelerate the unit tests. | +| `NUM_MIXED_DEPLOYMENT_REPETITIONS` | `10` | The number of times (minimum of `1`) to repeat each random mixed-deployment unit test for each deployment combination. | +| `TEST_ALL_DEPLOYMENTS` | `1` | Whether unit tests will be run using all possible deployment combinations (i.e. OpenMP, CUDA, MPI) in-turn (`=1`), or only once using all available deployments simultaneously (`=0`). | + + + @@ -256,7 +271,7 @@ QuEST execution can be configured prior to runtime using the below [environment - [`PERMIT_NODES_TO_SHARE_GPU`](https://quest-kit.github.io/QuEST/group__modes.html#ga7e12922138caa68ddaa6221e40f62dda) - [`DEFAULT_VALIDATION_EPSILON`](https://quest-kit.github.io/QuEST/group__modes.html#ga55810d6f3d23de810cd9b12a2bbb8cc2) - +Note the unit tests in the preceding section accept additional environment variables. --------------------- diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt index ba4fe0d78..31b0ea75a 100644 --- a/tests/CMakeLists.txt +++ b/tests/CMakeLists.txt @@ -1,5 +1,4 @@ # @author Oliver Thomson Brown -# @author Tyson Jones (macros and MPI ctests) add_executable(tests main.cpp @@ -16,12 +15,5 @@ if (ENABLE_DEPRECATED_API) endif() -# map test-related cmake vars to preprocessors -target_compile_definitions(tests PRIVATE TEST_MAX_NUM_QUBIT_PERMUTATIONS=${TEST_MAX_NUM_QUBIT_PERMUTATIONS}) -target_compile_definitions(tests PRIVATE TEST_MAX_NUM_SUPEROP_TARGETS=${TEST_MAX_NUM_SUPEROP_TARGETS}) -target_compile_definitions(tests PRIVATE TEST_NUM_MIXED_DEPLOYMENT_REPETITIONS=${TEST_NUM_MIXED_DEPLOYMENT_REPETITIONS}) -target_compile_definitions(tests PRIVATE TEST_ALL_DEPLOYMENTS=$) - - # let Catch2 register all tests with CTest catch_discover_tests(tests) diff --git a/tests/main.cpp b/tests/main.cpp index 29647753e..fca57f5ff 100644 --- a/tests/main.cpp +++ b/tests/main.cpp @@ -50,6 +50,7 @@ #include #include "quest.h" +#include "tests/utils/config.hpp" #include "tests/utils/cache.hpp" #include "tests/utils/macros.hpp" #include "tests/utils/random.hpp" @@ -95,8 +96,14 @@ class startListener : public Catch::EventListenerBase { std::cout << " GPU-sharing ok: " << env.isGpuSharingEnabled << std::endl; std::cout << " cuQuantum: " << env.isCuQuantumEnabled << std::endl; std::cout << " num nodes: " << env.numNodes << std::endl; - std::cout << " num qubits: " << getNumCachedQubits() << std::endl; - std::cout << " num qubit perms: " << TEST_MAX_NUM_QUBIT_PERMUTATIONS << std::endl; + std::cout << std::endl; + + std::cout << "Testing configuration:" << std::endl; + std::cout << " test all deployments: " << getWhetherToTestAllDeployments() << std::endl; + std::cout << " num qubits in qureg: " << getNumCachedQubits() << std::endl; + std::cout << " max num qubit perms: " << getMaxNumTestedQubitPermutations() << std::endl; + std::cout << " max num superop targs: " << getMaxNumTestedSuperoperatorTargets() << std::endl; + std::cout << " num mixed-deploy reps: " << getNumTestedMixedDeploymentRepetitions() << std::endl; std::cout << std::endl; std::cout << "Tested Qureg deployments:" << std::endl; diff --git a/tests/unit/calculations.cpp b/tests/unit/calculations.cpp index e0b4e9962..4b4db284e 100644 --- a/tests/unit/calculations.cpp +++ b/tests/unit/calculations.cpp @@ -23,6 +23,7 @@ #include "tests/utils/lists.hpp" #include "tests/utils/macros.hpp" #include "tests/utils/random.hpp" +#include "tests/utils/config.hpp" #include "tests/utils/cache.hpp" #include "tests/utils/measure.hpp" @@ -412,7 +413,7 @@ TEST_CASE( "calcInnerProduct", TEST_CATEGORY LABEL_MIXED_DEPLOY_TAG ) { qmatrix refDM = getRefDensmatr(); auto apiFunc = calcInnerProduct; - GENERATE( range(0, TEST_NUM_MIXED_DEPLOYMENT_REPETITIONS) ); + GENERATE( range(0, getNumTestedMixedDeploymentRepetitions()) ); SECTION( LABEL_STATEVEC LABEL_DELIMITER LABEL_STATEVEC ) { @@ -461,7 +462,7 @@ TEST_CASE( "calcFidelity", TEST_CATEGORY LABEL_MIXED_DEPLOY_TAG ) { qmatrix refDM = getRefDensmatr(); auto apiFunc = calcFidelity; - GENERATE( range(0, TEST_NUM_MIXED_DEPLOYMENT_REPETITIONS) ); + GENERATE( range(0, getNumTestedMixedDeploymentRepetitions()) ); SECTION( LABEL_STATEVEC LABEL_DELIMITER LABEL_STATEVEC ) { @@ -503,7 +504,7 @@ TEST_CASE( "calcDistance", TEST_CATEGORY LABEL_MIXED_DEPLOY_TAG ) { qmatrix refDM = getRefDensmatr(); auto apiFunc = calcDistance; - GENERATE( range(0, TEST_NUM_MIXED_DEPLOYMENT_REPETITIONS) ); + GENERATE( range(0, getNumTestedMixedDeploymentRepetitions()) ); SECTION( LABEL_STATEVEC LABEL_DELIMITER LABEL_STATEVEC ) { @@ -550,7 +551,7 @@ TEST_CASE( "calcExpecFullStateDiagMatr", TEST_CATEGORY LABEL_MIXED_DEPLOY_TAG ) qmatrix refMatr = getRandomDiagonalHermitian(getNumCachedQubits()); auto apiFunc = calcExpecFullStateDiagMatr; - GENERATE( range(0, TEST_NUM_MIXED_DEPLOYMENT_REPETITIONS) ); + GENERATE( range(0, getNumTestedMixedDeploymentRepetitions()) ); SECTION( LABEL_STATEVEC ) { @@ -579,7 +580,7 @@ TEST_CASE( "calcExpecNonHermitianFullStateDiagMatr", TEST_CATEGORY LABEL_MIXED_D qmatrix refMatr = getRandomDiagonalMatrix(getPow2(getNumCachedQubits())); auto apiFunc = calcExpecNonHermitianFullStateDiagMatr; - GENERATE( range(0, TEST_NUM_MIXED_DEPLOYMENT_REPETITIONS) ); + GENERATE( range(0, getNumTestedMixedDeploymentRepetitions()) ); SECTION( LABEL_STATEVEC ) { @@ -635,7 +636,7 @@ TEST_CASE( "calcExpecFullStateDiagMatrPower", TEST_CATEGORY LABEL_MIXED_DEPLOY_T CAPTURE( exponent ); - GENERATE( range(0, TEST_NUM_MIXED_DEPLOYMENT_REPETITIONS) ); + GENERATE( range(0, getNumTestedMixedDeploymentRepetitions()) ); SECTION( LABEL_STATEVEC ) { @@ -676,7 +677,7 @@ TEST_CASE( "calcExpecNonHermitianFullStateDiagMatrPower", TEST_CATEGORY LABEL_MI CAPTURE( exponent ); - GENERATE( range(0, TEST_NUM_MIXED_DEPLOYMENT_REPETITIONS) ); + GENERATE( range(0, getNumTestedMixedDeploymentRepetitions()) ); SECTION( LABEL_STATEVEC ) { diff --git a/tests/unit/decoherence.cpp b/tests/unit/decoherence.cpp index 5fc373a44..f36c491bb 100644 --- a/tests/unit/decoherence.cpp +++ b/tests/unit/decoherence.cpp @@ -15,6 +15,7 @@ #include "tests/utils/qvector.hpp" #include "tests/utils/qmatrix.hpp" +#include "tests/utils/config.hpp" #include "tests/utils/cache.hpp" #include "tests/utils/compare.hpp" #include "tests/utils/convert.hpp" @@ -276,7 +277,7 @@ TEST_CASE( "mixKrausMap", TEST_CATEGORY ) { SECTION( LABEL_CORRECTNESS ) { - int maxFlag = TEST_MAX_NUM_SUPEROP_TARGETS; + int maxFlag = getMaxNumTestedSuperoperatorTargets(); int numQubits = getNumCachedQubits(); int maxNumTargs = (maxFlag != 0 && numQubits > maxFlag)? maxFlag : numQubits; @@ -305,7 +306,7 @@ TEST_CASE( "mixSuperOp", TEST_CATEGORY ) { SECTION( LABEL_CORRECTNESS ) { int numQubits = getNumCachedQubits(); - int maxFlag = TEST_MAX_NUM_SUPEROP_TARGETS; + int maxFlag = getMaxNumTestedSuperoperatorTargets(); int maxNumTargs = (maxFlag != 0 && numQubits > maxFlag)? maxFlag : numQubits; @@ -336,7 +337,7 @@ TEST_CASE( "mixQureg", TEST_CATEGORY LABEL_MIXED_DEPLOY_TAG ) { CAPTURE( prob ); - GENERATE( range(0, TEST_NUM_MIXED_DEPLOYMENT_REPETITIONS) ); + GENERATE( range(0, getNumTestedMixedDeploymentRepetitions()) ); SECTION( LABEL_DENSMATR LABEL_DELIMITER LABEL_STATEVEC ) { diff --git a/tests/unit/operations.cpp b/tests/unit/operations.cpp index 55bed11ab..041000c4f 100644 --- a/tests/unit/operations.cpp +++ b/tests/unit/operations.cpp @@ -22,6 +22,7 @@ #include #include +#include "tests/utils/config.hpp" #include "tests/utils/cache.hpp" #include "tests/utils/qvector.hpp" #include "tests/utils/qmatrix.hpp" @@ -1738,7 +1739,7 @@ TEST_CASE( "multiplyFullStateDiagMatr", TEST_CATEGORY LABEL_MIXED_DEPLOY_TAG ) { qmatrix refMatr = getRandomDiagonalMatrix(getPow2(numQubits)); auto apiFunc = multiplyFullStateDiagMatr; - GENERATE( range(0, TEST_NUM_MIXED_DEPLOYMENT_REPETITIONS) ); + GENERATE( range(0, getNumTestedMixedDeploymentRepetitions()) ); SECTION( LABEL_STATEVEC ) { @@ -1776,7 +1777,7 @@ TEST_CASE( "multiplyFullStateDiagMatrPower", TEST_CATEGORY LABEL_MIXED_DEPLOY_TA CAPTURE( exponent ); - GENERATE( range(0, TEST_NUM_MIXED_DEPLOYMENT_REPETITIONS) ); + GENERATE( range(0, getNumTestedMixedDeploymentRepetitions()) ); SECTION( LABEL_STATEVEC ) { @@ -1814,7 +1815,7 @@ TEST_CASE( "applyFullStateDiagMatr", TEST_CATEGORY LABEL_MIXED_DEPLOY_TAG ) { qmatrix refMatr = getRandomDiagonalUnitary(numQubits); auto apiFunc = applyFullStateDiagMatr; - GENERATE( range(0, TEST_NUM_MIXED_DEPLOYMENT_REPETITIONS) ); + GENERATE( range(0, getNumTestedMixedDeploymentRepetitions()) ); SECTION( LABEL_STATEVEC ) { @@ -1858,7 +1859,7 @@ TEST_CASE( "applyFullStateDiagMatrPower", TEST_CATEGORY LABEL_MIXED_DEPLOY_TAG ) CAPTURE( exponent ); - GENERATE( range(0, TEST_NUM_MIXED_DEPLOYMENT_REPETITIONS) ); + GENERATE( range(0, getNumTestedMixedDeploymentRepetitions()) ); if (!testRealExp) setValidationEpsilon(0); diff --git a/tests/utils/CMakeLists.txt b/tests/utils/CMakeLists.txt index cae21694b..c9c06075f 100644 --- a/tests/utils/CMakeLists.txt +++ b/tests/utils/CMakeLists.txt @@ -4,6 +4,7 @@ target_sources(tests PUBLIC cache.cpp compare.cpp + config.cpp convert.cpp evolve.cpp linalg.cpp diff --git a/tests/utils/cache.cpp b/tests/utils/cache.cpp index 21dee8482..ec5001bcc 100644 --- a/tests/utils/cache.cpp +++ b/tests/utils/cache.cpp @@ -12,6 +12,7 @@ #include "qmatrix.hpp" #include "macros.hpp" #include "linalg.hpp" +#include "config.hpp" #include "cache.hpp" #include @@ -36,19 +37,15 @@ quregCache densmatrs1; quregCache densmatrs2; matrixCache matrices; - - -/* - * while the number of qubits in the unit-test Quregs/matr - * is fixed, it is defined privately here (with internal - * linkage) so that it can be changed between compilations - * without having to recompiling the entire test suite - */ - -static constexpr int NUM_QUBITS_IN_CACHE = 6; - int getNumCachedQubits() { - return NUM_QUBITS_IN_CACHE; + + // we are merely aliasing the below env-var fetching function + // to minimise a diff since pre-runtime controlling the tested + // Qureg sizes is experimental and not fully designed (we may + // eventually wish to specify different sizes for statevectors + // vs density matrices, or control integration test Qureg sizes + // also through environment variables, etc) + return getNumQubitsInUnitTestedQuregs(); } @@ -68,7 +65,7 @@ deployInfo getSupportedDeployments() { bool gpu = env.isGpuAccelerated; // return only the "most-accelerated" deployment, unless all are desired - bool one = ! TEST_ALL_DEPLOYMENTS; + bool one = ! getWhetherToTestAllDeployments(); // add only those supported to the output list, in order of preference. // flag order is (MPI, GPU, OMP), matching createCustomQureg @@ -100,7 +97,7 @@ quregCache createCachedStatevecsOrDensmatrs(bool isDensMatr) { // only add supported-deployment quregs to the cache for (auto [label, mpi, gpu, omp] : getSupportedDeployments()) - out[label] = createCustomQureg(NUM_QUBITS_IN_CACHE, isDensMatr, mpi, gpu, omp); + out[label] = createCustomQureg(getNumCachedQubits(), isDensMatr, mpi, gpu, omp); return out; } @@ -184,7 +181,7 @@ void createCachedFullStateDiagMatrs() { // only add supported-deployment matrices to the cache for (auto [label, mpi, gpu, omp] : getSupportedDeployments()) - matrices[label] = createCustomFullStateDiagMatr(NUM_QUBITS_IN_CACHE, mpi, gpu, omp); + matrices[label] = createCustomFullStateDiagMatr(getNumCachedQubits(), mpi, gpu, omp); } void destroyCachedFullStateDiagMatrs() { @@ -213,8 +210,8 @@ matrixCache getCachedFullStateDiagMatrs() { */ qvector getRefStatevec() { - return getZeroVector(getPow2(NUM_QUBITS_IN_CACHE)); + return getZeroVector(getPow2(getNumCachedQubits())); } qmatrix getRefDensmatr() { - return getZeroMatrix(getPow2(NUM_QUBITS_IN_CACHE)); + return getZeroMatrix(getPow2(getNumCachedQubits())); } diff --git a/tests/utils/config.cpp b/tests/utils/config.cpp new file mode 100644 index 000000000..c5362e899 --- /dev/null +++ b/tests/utils/config.cpp @@ -0,0 +1,76 @@ +/** @file + * Testing utilities for loading environment variables + * which configure the unit tests, independent of QuEST's + * internal environment variable facilities + * + * @author Tyson Jones + */ + +#include +#include +#include + +using std::string; + + +/* + * PRIVATE + */ + +string getEnvVarValue(string name) { + + // unspecified var returns empty string + const char* ptr = std::getenv(name.c_str()); + return (ptr == nullptr)? "" : std::string(ptr); +} + +int getIntEnvVarValueOrDefault(string name, int defaultValue) { + + string strValue = getEnvVarValue(name); + int intValue = defaultValue; + + // overwrite default only when passed variable is interpretable + try { + intValue = std::stoi(strValue); + } + catch (const std::out_of_range&) { } + catch (const std::invalid_argument&) { } + return intValue; +} + + +/* + * PUBLIC + * + * which each call std::getenv only once + */ + +int getNumQubitsInUnitTestedQuregs() { + + static int value = getIntEnvVarValueOrDefault("TEST_NUM_QUBITS_IN_QUREG", 6); + return value; +} + +int getMaxNumTestedQubitPermutations() { + + static int value = getIntEnvVarValueOrDefault("TEST_MAX_NUM_QUBIT_PERMUTATIONS", 0); + return value; +} + +int getMaxNumTestedSuperoperatorTargets() { + + static int value = getIntEnvVarValueOrDefault("TEST_MAX_NUM_SUPEROP_TARGETS", 4); + return value; +} + +int getNumTestedMixedDeploymentRepetitions() { + + static int value = getIntEnvVarValueOrDefault("TEST_NUM_MIXED_DEPLOYMENT_REPETITIONS", 10); + return value; +} + +bool getWhetherToTestAllDeployments() { + + static bool value = getIntEnvVarValueOrDefault("TEST_ALL_DEPLOYMENTS", 1); + return value; +} diff --git a/tests/utils/config.hpp b/tests/utils/config.hpp new file mode 100644 index 000000000..a1ef142c5 --- /dev/null +++ b/tests/utils/config.hpp @@ -0,0 +1,94 @@ +/** @file + * Testing utilities for loading environment variables + * which configure the unit tests, independent of QuEST's + * internal environment variable facilities + * + * @author Tyson Jones + */ + + +/** @file + * @author Tyson Jones + * + * @defgroup testutilsconfig Config + * @ingroup testutils + * @brief + * Testing utilities for loading environment variables + * which configure the unit tests, independent of QuEST's + * internal environment variable facilities + * @{ + */ + +#ifndef CONFIG_HPP +#define CONFIG_HPP + + +/* + * SPECIFYING ENV-VARS + */ + +// spoofing as macros to doc; beware that the values below +// merely duplicate but do not change the default values +// which are hardcoded in config.cpp +#if 0 + + /// @envvardoc + const int TEST_NUM_QUBITS_IN_QUREG = 6; + + /** @envvardoc + * + * Specifies the maximum number of control and target qubit permutations for which to unit test each relevant + * API function. + * + * Many QuEST functions accept a varying number of target qubits (like applyCompMatr()) and/or control qubits + * (like applyMultiControlledCompMatr()). The unit tests will run these functions, passing every possible number + * of target qubits (alongside every possible number of control qubits, if possible), from one (zero) up to the + * number contained within the tested `Qureg` (minus the number of target qubits). + * + * For each of these tested number-of-targets and number-of-controls combinations, there are factorially-many + * possible choices of the arbitrarily-ordered qubit indices, i.e. sub-permutations of all Qureg qubits. + * By default, the unit tests deterministically check every permutation in-turn. This can become prohibitively + * slow when the tested `Qureg` are large. For example, there are `604,800` unique, non-overlapping choices of + * `4` targets and `3` controls in a Qureg containing `10` qubits. + * + * When this environment variable is set to a non-zero value, the unit tests will forego testing every permutation + * and instead perform only the number specified, randomising the involved qubits. This can significantly speed up the + * tests though risks missing esoteric edge-cases. The runtime of the tests are approximately linearly proportional + * to the specified number of permutations. When the specified non-zero value exceeds the number of unique + * permutations, the tests will revert to deterministically evaluating each once. + * + * @envvarvalues + * + * - set to `0` (default) to systematically test all permutations. + * - set to a positive integer (e.g. `50`) to test (at most) that many random permutations and accelerate the tests. + * + * @author Tyson Jones + */ + const int TEST_MAX_NUM_QUBIT_PERMUTATIONS = 0; + + /// @envvardoc + const int TEST_MAX_NUM_SUPEROP_TARGETS = 4; + + /// @envvardoc + const int TEST_ALL_DEPLOYMENTS = 1; + + /// @envvardoc + const int TEST_NUM_MIXED_DEPLOYMENT_REPETITIONS = 10; + +#endif + + +/* + * ACCESSING ENV-VARS + */ + +int getNumQubitsInUnitTestedQuregs(); +int getMaxNumTestedQubitPermutations(); +int getMaxNumTestedSuperoperatorTargets(); +int getNumTestedMixedDeploymentRepetitions(); +bool getWhetherToTestAllDeployments(); + + +#endif // CONFIG_PP + +/** @} (end defgroup) */ diff --git a/tests/utils/lists.cpp b/tests/utils/lists.cpp index aa20f34db..b7ea3c340 100644 --- a/tests/utils/lists.cpp +++ b/tests/utils/lists.cpp @@ -10,6 +10,7 @@ #include "quest.h" +#include "config.hpp" #include "lists.hpp" #include "macros.hpp" #include "random.hpp" @@ -264,7 +265,7 @@ listpair GENERATE_CTRLS_AND_TARGS(int numQubits, int numCtrls, int numTargs) { // impose a limit on the number of {ctrls,targs} to generate (max-int if none set) int numPerms = getNumPermutations(numQubits, numCtrls + numTargs); - int maxPerms = TEST_MAX_NUM_QUBIT_PERMUTATIONS; + int maxPerms = getMaxNumTestedQubitPermutations(); if (maxPerms == 0) maxPerms = std::numeric_limits::max(); diff --git a/tests/utils/macros.hpp b/tests/utils/macros.hpp index 7d5882051..da924ad88 100644 --- a/tests/utils/macros.hpp +++ b/tests/utils/macros.hpp @@ -14,57 +14,6 @@ #include -/** - * macros which affect the speed and rigour of the unit tests, useful - * for accelerating tests on particular platforms (e.g. paid github runners). - * The default values are those which perform the most rigorous tests at - * the slowest speed, so adjusting these macros accelerates tests. - * - * @todo - * These are clunky preprocessors (invoking full recompilation when changed), - * rather than runtime arguments, because of the nuisance of passing such - * args to cmake. It can be done however using environment variables; see - * https://stackoverflow.com/questions/28812533/ - */ - -// 0 = perform all, and a sensible value to accelerate tests is 50 -#ifndef TEST_MAX_NUM_QUBIT_PERMUTATIONS -#define TEST_MAX_NUM_QUBIT_PERMUTATIONS 0 -#endif - -// 0 = perform all (very slow), while 4 limits to superops = 8-qubit matrices -#ifndef TEST_MAX_NUM_SUPEROP_TARGETS -#define TEST_MAX_NUM_SUPEROP_TARGETS 4 -#endif - -// 0 = use all available deployments at once, 1 = try all combinations in-turn -#ifndef TEST_ALL_DEPLOYMENTS -#define TEST_ALL_DEPLOYMENTS 1 -#endif - -// number of times to repeat each "[mixed]" test (minimum 1) -#ifndef TEST_NUM_MIXED_DEPLOYMENT_REPETITIONS -#define TEST_NUM_MIXED_DEPLOYMENT_REPETITIONS 10 -#endif - -// spoofing above macros as consts to doc -#if 0 - - /// @macrodoc - const int TEST_MAX_NUM_QUBIT_PERMUTATIONS = 0; - - /// @macrodoc - const int TEST_MAX_NUM_SUPEROP_TARGETS = 4; - - /// @macrodoc - const int TEST_ALL_DEPLOYMENTS = 1; - - /// @macrodoc - const int TEST_NUM_MIXED_DEPLOYMENT_REPETITIONS = 10; - -#endif - - /* * preconditions to the internal unit testing functions are checked using * DEMAND rather than Catch2's REQUIRE, so that they are not counted in the