├── .github ├── ISSUE_TEMPLATE │ ├── bug_report.md │ ├── custom.md │ └── feature_request.md └── workflows │ ├── cpp_build_with_cmake.yml │ ├── docker-image.yml │ ├── python_build_mpi.yml │ └── python_build_no_mpi.yml ├── .gitignore ├── CHANGELOG.md ├── CITATION.cff ├── CMakeLists.txt ├── CODE_OF_CONDUCT.md ├── CONTRIBUTING.md ├── Dockerfile ├── Jenkinsfile ├── LICENSE.md ├── README.md ├── benchmarks ├── CMakeLists.txt ├── basic_code_for_scaling.cpp ├── output │ └── .gitignore ├── script_pcl.sh ├── script_strong_scaling.sh ├── script_weak_scaling.sh └── specv2_bench.cpp ├── cmake ├── FindMKL.cmake └── gtest.cmake.in ├── docker_build ├── docs ├── Makefile ├── directory_structure.md ├── docker_guide.md ├── doxy-html.config ├── install_guide.md ├── make.bat ├── requirements.txt ├── source │ ├── CONTRIBUTING.md │ ├── conf.py │ ├── get_started_examples.ipynb │ ├── getting-started.md │ ├── index.rst │ └── qaoa_example.ipynb └── todo_list.md ├── examples ├── CMakeLists.txt ├── benchgates.cpp ├── circuit_with_noise_gates.cpp ├── communication_reduction_via_qubit_reordering.cpp ├── expect_value_test.cpp ├── grover_4qubit.cpp ├── heisenberg_dynamics.cpp ├── launcher_all_examples.sh ├── noise_via_chi_matrix.cpp ├── quantum_fourier_transform.cpp └── test_of_custom_gates.cpp ├── include ├── NoisyQureg.hpp ├── QubitRegisterMetric.hpp ├── alignedallocator.hpp ├── bitops.hpp ├── chi_matrix.hpp ├── conversion.hpp ├── gate_counter.hpp ├── gate_spec.hpp ├── highperfkernels.hpp ├── mpi_env.hpp ├── mpi_exception.hpp ├── mpi_utils.hpp ├── permutation.hpp ├── qaoa_features.hpp ├── qureg.hpp ├── qureg_version.hpp ├── rng_utils.hpp ├── spec_kernels.hpp ├── timer.hpp ├── tinymatrix.hpp └── utils.hpp ├── interface ├── CMakeLists.txt ├── include │ ├── interface_api_memory.h │ ├── interface_api_qasm.h │ ├── interface_api_qubitid.h │ └── interface_api_version.h └── src │ ├── CMakeLists.txt │ ├── intelqs_interface_main.cpp │ ├── interface_api_memory.cpp │ ├── interface_api_qasm.cpp │ ├── interface_api_qubitid.cpp │ └── interface_api_version.cpp ├── notebooks ├── basic_script.py ├── chi_matrix_with_mpi.py ├── get_started_examples.ipynb ├── noise_via_chi_matrix_example.ipynb ├── print_distributed_state.py └── qaoa_example.ipynb ├── pybind11 ├── CMakeLists.txt └── intelqs_py.cpp ├── src ├── CMakeLists.txt ├── chi_matrix.cpp ├── gate_spec.cpp ├── highperfkernels.cpp ├── mpi_env.cpp ├── mpi_exception.cpp ├── qaoa_features.cpp ├── qureg_apply1qubitgate.cpp ├── qureg_apply2qubitgate.cpp ├── qureg_apply_channel.cpp ├── qureg_applyctrl1qubitgate.cpp ├── qureg_applydiag.cpp ├── qureg_applyswap.cpp ├── qureg_applytoffoli.cpp ├── qureg_expectval.cpp ├── qureg_fusion.cpp ├── qureg_init.cpp ├── qureg_measure.cpp ├── qureg_noisysimul.cpp ├── qureg_permute.cpp ├── qureg_utils.cpp ├── qureg_version.cpp ├── rng_utils.cpp ├── spec_kernels.cpp └── utils.cpp ├── tutorials ├── .ipynb_checkpoints │ └── get_started_with_IQS-checkpoint.ipynb ├── CMakeLists.txt ├── basic_use_presentation.ipynb ├── get_started_with_IQS.cpp ├── get_started_with_IQS.ipynb ├── get_started_with_noisy_IQS.cpp └── get_started_with_noisy_IQS.py ├── unit_test ├── CMakeLists.txt ├── data │ ├── 5_qubit_hubbard_renyi_U_1_SpeedFactor_2_DeltaT_0.1.qasmf │ └── binary_welded_tree.n2s2.qasmf ├── import_iqs.py ├── include │ ├── apply_1q_gate_test.hpp │ ├── apply_swap_gate_test.hpp │ ├── chi_matrix_test.hpp │ ├── chunking_communication_test.hpp │ ├── compiler_flags_test.hpp │ ├── conversion_test.hpp │ ├── expectation_values_test.hpp │ ├── gate_counter_test.hpp │ ├── measure_test.hpp │ ├── multiple_states_test.hpp │ ├── noisy_simulation_test.hpp │ ├── one_qubit_register_test.hpp │ ├── permutation_test.hpp │ ├── qaoa_features_test.hpp │ ├── qureg_apply_channel.hpp │ ├── qureg_permute_test.hpp │ ├── random_number_generator_test.hpp │ ├── single_qubit_gates_test.hpp │ ├── state_initialization_test.hpp │ ├── tinymatrix_test.hpp │ ├── two_qubit_register_test.hpp │ └── utility_methods_test.hpp ├── mpi_env_test.cpp ├── mpi_speedup_test.cpp ├── openmp_test.cpp └── suite_of_tests.cpp └── util ├── BigMPI ├── .gitignore ├── .travis.yml ├── CMakeLists.txt ├── INSTALL.md ├── LICENSE ├── Mac-MPI-Accelerate.cmake ├── Makefile.am ├── README.md ├── VERSION ├── autogen.sh ├── configure.ac ├── m4 │ ├── aclocal_am.m4 │ ├── aclocal_atomic.m4 │ ├── aclocal_attr_alias.m4 │ ├── aclocal_bugfix.m4 │ ├── aclocal_cache.m4 │ ├── aclocal_cc.m4 │ ├── aclocal_cxx.m4 │ ├── aclocal_f77.m4 │ ├── aclocal_f77new.m4 │ ├── aclocal_fc.m4 │ ├── aclocal_libs.m4 │ ├── aclocal_make.m4 │ ├── aclocal_mpi.m4 │ ├── aclocal_romio.m4 │ ├── aclocal_runlog.m4 │ ├── aclocal_shl.m4 │ ├── aclocal_subcfg.m4 │ ├── aclocal_util.m4 │ ├── ax_prefix_config_h.m4 │ └── ax_tls.m4 ├── src │ ├── CMakeLists.txt │ ├── bigmpi.h │ ├── bigmpi_impl.h │ ├── collectives_x.c │ ├── fileio_x.c │ ├── likely.h │ ├── neighborhood_collectives_x.c │ ├── reductions_x.c │ ├── rma_x.c │ ├── sendrecv_x.c │ ├── type_contiguous_x.c │ ├── type_hindexed_x.c │ ├── utils.c │ └── vcollectives_x.c ├── test │ ├── CMakeLists.txt │ ├── Makefile.mk │ ├── README.md │ ├── devel │ │ ├── Makefile.mk │ │ ├── README.md │ │ ├── aint_overflow.c │ │ ├── in_place_user_def_reduce.c │ │ ├── preprocessor.c │ │ ├── rounding.c │ │ └── type_create_struct.c │ ├── mpi │ │ ├── Makefile.mk │ │ ├── README.md │ │ ├── bcast.c │ │ ├── reduce_scatter.c │ │ └── scatterv.c │ ├── perf │ │ ├── Makefile │ │ ├── reductions.c │ │ ├── typecontig.c │ │ └── typepiggy.c │ ├── test_allgather_x.c │ ├── test_allreduce_x.c │ ├── test_alltoall_x.c │ ├── test_assert_x.c │ ├── test_bcast_x.c │ ├── test_contig_x.c │ ├── test_factorize.c │ ├── test_gather_x.c │ ├── test_irsend_irecv_x.c │ ├── test_isend_irecv_x.c │ ├── test_issend_irecv_x.c │ ├── test_reduce_x.c │ ├── test_rma2_x.c │ ├── test_rma_x.c │ ├── test_rsend_recv_x.c │ ├── test_scatter_x.c │ ├── test_send_recv_x.c │ ├── test_sendrecv_x.c │ ├── test_ssend_recv_x.c │ └── verify_buffer.h └── travis │ ├── build-run.sh │ ├── install-autotools.sh │ ├── install-deps.sh │ └── install-mpi.sh └── tests ├── alignedallocator_test.cpp ├── bitops_btest.cpp ├── bitops_test.cpp ├── blas_test.cpp └── naive_integral_base.cpp /.github/ISSUE_TEMPLATE/bug_report.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Bug report 3 | about: Create a report to help us improve 4 | title: '' 5 | labels: '' 6 | assignees: '' 7 | 8 | --- 9 | 10 | **Describe the bug** 11 | A clear and concise description of what the bug is. 12 | 13 | **To Reproduce** 14 | Steps to reproduce the behavior: 15 | 1. Go to '...' 16 | 2. Click on '....' 17 | 3. Scroll down to '....' 18 | 4. See error 19 | 20 | **Expected behavior** 21 | A clear and concise description of what you expected to happen. 22 | 23 | **Screenshots** 24 | If applicable, add screenshots to help explain your problem. 25 | 26 | **Desktop (please complete the following information):** 27 | - OS: [e.g. iOS] 28 | - Browser [e.g. chrome, safari] 29 | - Version [e.g. 22] 30 | 31 | **Smartphone (please complete the following information):** 32 | - Device: [e.g. iPhone6] 33 | - OS: [e.g. iOS8.1] 34 | - Browser [e.g. stock browser, safari] 35 | - Version [e.g. 22] 36 | 37 | **Additional context** 38 | Add any other context about the problem here. 39 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/custom.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Custom issue template 3 | about: Describe this issue template's purpose here. 4 | title: '' 5 | labels: '' 6 | assignees: '' 7 | 8 | --- 9 | 10 | 11 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/feature_request.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Feature request 3 | about: Suggest an idea for this project 4 | title: '' 5 | labels: '' 6 | assignees: '' 7 | 8 | --- 9 | 10 | **Is your feature request related to a problem? Please describe.** 11 | A clear and concise description of what the problem is. Ex. I'm always frustrated when [...] 12 | 13 | **Describe the solution you'd like** 14 | A clear and concise description of what you want to happen. 15 | 16 | **Describe alternatives you've considered** 17 | A clear and concise description of any alternative solutions or features you've considered. 18 | 19 | **Additional context** 20 | Add any other context or screenshots about the feature request here. 21 | -------------------------------------------------------------------------------- /.github/workflows/cpp_build_with_cmake.yml: -------------------------------------------------------------------------------- 1 | name: C++ build with CMake 2 | permissions: read-all 3 | 4 | # Controls when the action will run: 5 | # Triggers the workflow on push or pull request events but only for the master branch 6 | on: 7 | push: 8 | branches: [ master ] 9 | pull_request: 10 | branches: [ master, development ] 11 | 12 | # A workflow run is made up of one or more jobs that can run sequentially or in parallel 13 | jobs: 14 | # This workflow contains a single job called "build" 15 | build-ubuntu-gcc: 16 | # The type of runner that the job will run on 17 | runs-on: ubuntu-latest 18 | 19 | # Steps represent a sequence of tasks that will be executed as part of the job 20 | steps: 21 | # Checks-out your repository under $GITHUB_WORKSPACE, so your job can access it 22 | - uses: actions/checkout@v2 23 | 24 | - name: configure 25 | run: mkdir build && cd build && CXX=g++ cmake -DIqsMPI=OFF -DIqsUtest=ON .. 26 | - name: build 27 | run: cmake --build build 28 | 29 | - name: unit test 30 | run: ./build/bin/utest 31 | -------------------------------------------------------------------------------- /.github/workflows/docker-image.yml: -------------------------------------------------------------------------------- 1 | name: Docker Image CI 2 | permissions: read-all 3 | 4 | on: 5 | push: 6 | branches: [ master ] 7 | pull_request: 8 | branches: [ master, development ] 9 | 10 | jobs: 11 | 12 | build: 13 | 14 | runs-on: ubuntu-latest 15 | 16 | steps: 17 | - uses: actions/checkout@v2 18 | - name: Build the Docker image 19 | run: docker build -t intel-qs:$(date +%s) . 20 | -------------------------------------------------------------------------------- /.github/workflows/python_build_mpi.yml: -------------------------------------------------------------------------------- 1 | name: Python build with MPI 2 | permissions: read-all 3 | 4 | # Triggers the workflow on push or pull request events but only for the master branch 5 | on: 6 | push: 7 | branches: [ master , development ] 8 | pull_request: 9 | branches: [ master , development ] 10 | 11 | # A workflow run is made up of one or more jobs that can run sequentially or in parallel 12 | jobs: 13 | # This workflow contains a single job called "build-ubuntu-conda-gcc" 14 | build-ubuntu-conda-gcc: 15 | # The type of runner that the job will run on 16 | runs-on: ubuntu-latest 17 | 18 | # Steps represent a sequence of tasks that will be executed as part of the job 19 | steps: 20 | - uses: conda-incubator/setup-miniconda@v2 21 | with: 22 | auto-update-conda: true 23 | python-version: 3.7 24 | - name: Conda info, list, pybind install and activate 25 | shell: bash -l {0} 26 | run: | 27 | conda info 28 | conda list 29 | conda install -y pybind11 30 | conda activate /usr/share/miniconda/envs/test 31 | - name: Install MPICH 32 | run: | 33 | sudo apt-get update 34 | sudo apt-get install --yes --no-install-recommends libmpich-dev mpich 35 | which mpic++ 36 | mpic++ --version 37 | 38 | # Checks-out your repository under $GITHUB_WORKSPACE, so your job can access it 39 | - uses: actions/checkout@v2 40 | 41 | - name: configure 42 | shell: bash -l {0} 43 | run: mkdir build && cd build && CXX=mpic++ cmake PYTHON_EXECUTABLE=/usr/share/miniconda/envs/test/bin/python -DIqsMPI=ON -DIqsPython=ON -DIqsUtest=OFF .. 44 | - name: build 45 | run: cmake --build build --target intelqs_py 46 | 47 | - name: unit test 48 | run: cd unit_test && /usr/share/miniconda/envs/test/bin/python import_iqs.py 49 | -------------------------------------------------------------------------------- /.github/workflows/python_build_no_mpi.yml: -------------------------------------------------------------------------------- 1 | name: Python build (no MPI) 2 | permissions: read-all 3 | 4 | # Triggers the workflow on push or pull request events but only for the master branch 5 | on: 6 | push: 7 | branches: [ master , development ] 8 | pull_request: 9 | branches: [ master , development ] 10 | 11 | # A workflow run is made up of one or more jobs that can run sequentially or in parallel 12 | jobs: 13 | # This workflow contains a single job called "build-ubuntu-conda-gcc" 14 | build-ubuntu-conda-gcc: 15 | # The type of runner that the job will run on 16 | runs-on: ubuntu-latest 17 | 18 | # Steps represent a sequence of tasks that will be executed as part of the job 19 | steps: 20 | - uses: conda-incubator/setup-miniconda@v2 21 | with: 22 | auto-update-conda: true 23 | python-version: 3.7 24 | - name: Conda info, list, pybind install and activate 25 | shell: bash -l {0} 26 | run: | 27 | conda info 28 | conda list 29 | conda install -y pybind11 30 | conda activate /usr/share/miniconda/envs/test 31 | 32 | # Checks-out your repository under $GITHUB_WORKSPACE, so your job can access it 33 | - uses: actions/checkout@v2 34 | 35 | - name: configure 36 | shell: bash -l {0} 37 | run: mkdir build && cd build && which python && whereis python && CXX=g++ cmake PYTHON_EXECUTABLE=/usr/share/miniconda/envs/test/bin/python -DIqsMPI=OFF -DIqsPython=ON -DIqsUtest=OFF .. 38 | - name: build 39 | run: cmake --build build --target intelqs_py 40 | 41 | - name: unit test 42 | run: cd unit_test && which python && whereis python && ls ../build/lib && /usr/share/miniconda/envs/test/bin/python import_iqs.py 43 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | *.o 2 | **/libintel_qs.a 3 | docs/source/_static 4 | docs/source/_templates 5 | docs/build 6 | venv 7 | docs/source/doxyoutput 8 | docs/source/api 9 | -------------------------------------------------------------------------------- /CHANGELOG.md: -------------------------------------------------------------------------------- 1 | # Change Log 2 | 3 | All notable changes to this project will be documented in this file. 4 | 5 | ---- 6 | 7 | ## [ 2.1.0 ] - [ 2021-04-xx ] 8 | 9 | ### Added 10 | - Python bindings with MPI 11 | - new gate specialization for OpenMP performance improvement 12 | - distributed implementation of SWAP-type gates 13 | - class `Permutation` and method `PermuteQubits` to manipulate the representation 14 | of quantum states and possibly reduce the overhead from MPI communication 15 | - class `ChiMatrix` to represent quantum channels and method `ApplyChannel` 16 | to simulate 1- and 2-qubit channels 17 | - extra examples and tutorials 18 | - ReadTheDocs for easy-to-navigate documentation 19 | 20 | ### Changed 21 | - CMake build is now modular 22 | - the library is part of namespace `iqs` 23 | 24 | ### Removed 25 | 26 | ### Fixed 27 | - when compiling with GCC, the option `-O3` is used for performance improvement 28 | - a few minor bugs 29 | - update examples to current syntax 30 | 31 | ---- 32 | 33 | ## [ 2.0.0 ] - [ 2019-12-12 ] 34 | 35 | ### Added 36 | - pool of state functionality: parallel execution of multiple circuits 37 | - Python bindings based on [PyBind11](https://github.com/pybind/pybind11) (no MPI) 38 | - tutorials and a few new examples 39 | - methods to simulate with noise and decoherence within QubitRegister class 40 | - benchmarks to reproduce weak and strong scaling of 1-qubit gate runtime 41 | - methods specialized for emulation of QAOA circuits 42 | 43 | ### Changed 44 | - building process based on CMake instead of Make 45 | - main class name changed from `QbitRegister` to `QubitRegister` 46 | - MPI environment extended to support the "pool of state" functionality 47 | - examples updated to new syntax and methods 48 | 49 | ### Removed 50 | 51 | ### Fixed 52 | 53 | ---- 54 | 55 | ## [1.0.0 ] - [ 2017-11-06 ] 56 | 57 | Hosted by the (now deprecated) repository . 58 | 59 | ### Added 60 | - implementation of customized MPI environment 61 | - implementation of `QbitRegister` class for simulation of quantum circuits 62 | - methods to simulate 1-qubit gates and controlled-1-qubit gates, 63 | state preparation and measurement 64 | 65 | ### Changed 66 | 67 | ### Removed 68 | 69 | ### Fixed 70 | 71 | -------------------------------------------------------------------------------- /CITATION.cff: -------------------------------------------------------------------------------- 1 | # YAML 1.2 2 | --- 3 | cff-version: "1.2.0" 4 | message: "When using Intel Quantum Simulator for research projects, please cite it as below." 5 | title: "Intel Quantum Simulator" 6 | abstract: "Intel Quantum Simulator (Intel-QS), also known as qHiPSTER (The Quantum High Performance Software Testing Environment), is a simulator of quantum circuits optimized to take maximum advantage of multi-core and multi-nodes architectures. It is based on a complete representation of the qubit state, but avoids the explicit representation of gates and other quantum operations in terms of matrices. Intel-QS uses the MPI (message-passing-interface) protocol to handle communication between the distributed resources used to store and manipulate quantum states." 7 | authors: 8 | - family-names: Guerreschi 9 | given-names: "Gian Giacomo" 10 | orcid: "https://orcid.org/0000-0002-5579-451X" 11 | - family-names: Hogaboam 12 | given-names: Justin 13 | - family-names: Baruffa 14 | given-names: Fabio 15 | - family-names: Sawaya 16 | given-names: "Nicolas P. D." 17 | orcid: "https://orcid.org/0000-0001-8510-8480" 18 | date-released: 2017-11-06 19 | keywords: 20 | - "quantum computing" 21 | - "high performance computing" 22 | - "cloud computing" 23 | - "quantum circuits" 24 | - "intel quantum simulator" 25 | license: "Apache-2.0" 26 | repository-code: "https://github.com/iqusoft/intel-qs" 27 | version: "2.1.0" 28 | preferred-citation: 29 | type: article 30 | authors: 31 | - family-names: Guerreschi 32 | given-names: "Gian Giacomo" 33 | orcid: "https://orcid.org/0000-0002-5579-451X" 34 | - family-names: Hogaboam 35 | given-names: Justin 36 | - family-names: Baruffa 37 | given-names: Fabio 38 | - family-names: Sawaya 39 | given-names: "Nicolas P. D." 40 | orcid: "https://orcid.org/0000-0001-8510-8480" 41 | doi: "10.1088/2058-9565/ab8505" 42 | url: "https://doi.org/10.1088/2058-9565/ab8505" 43 | journal: "Quantum Science and Technology" 44 | month: 7 45 | title: "Intel Quantum Simulator: a cloud-ready high-performance simulator of quantum circuits" 46 | issue: 3 47 | volume: 5 48 | year: 2020 49 | references: 50 | - type: article 51 | scope: "The original implementation is described here." 52 | authors: 53 | - family-names: Smelyanskiy 54 | given-names: Mikhail 55 | orcid: "https://orcid.org/0000-0002-2433-6110" 56 | - family-names: Sawaya 57 | given-names: "Nicolas P. D." 58 | orcid: "https://orcid.org/0000-0001-8510-8480" 59 | - family-names: Aspuru-Guzik 60 | given-names: "Alán" 61 | orcid: "https://orcid.org/0000-0002-8277-4434" 62 | title: "qHiPSTER: The Quantum High Performance Software Testing Environment" 63 | abstract: "We present qHiPSTER, the Quantum High Performance Software Testing Environment. qHiPSTER is a distributed high-performance implementation of a quantum simulator on a classical computer, that can simulate general single-qubit gates and two-qubit controlled gates. We perform a number of single- and multi-node optimizations, including vectorization, multi-threading, cache blocking, as well as overlapping computation with communication. Using the TACC Stampede supercomputer, we simulate quantum circuits (“quantum software”) of up to 40 qubits. We carry out a detailed performance analysis to show that our simulator achieves both high performance and high hardware efficiency, limited only by the sustainable memory and network bandwidth of the machine." 64 | year: 2016 65 | month: 5 66 | url: "https://arxiv.org/abs/1601.07195" 67 | ... 68 | -------------------------------------------------------------------------------- /CODE_OF_CONDUCT.md: -------------------------------------------------------------------------------- 1 | # Contributor Covenant Code of Conduct 2 | 3 | ## Our Pledge 4 | 5 | In the interest of fostering an open and welcoming environment, we as contributors and maintainers pledge to making participation in our project and our community a harassment-free experience for everyone, regardless of age, body size, disability, ethnicity, gender identity and expression, level of experience, nationality, personal appearance, race, religion, or sexual identity and orientation. 6 | 7 | ## Our Standards 8 | 9 | Examples of behavior that contributes to creating a positive environment include: 10 | 11 | * Using welcoming and inclusive language 12 | * Being respectful of differing viewpoints and experiences 13 | * Gracefully accepting constructive criticism 14 | * Focusing on what is best for the community 15 | * Showing empathy towards other community members 16 | 17 | Examples of unacceptable behavior by participants include: 18 | 19 | * The use of sexualized language or imagery and unwelcome sexual attention or advances 20 | * Trolling, insulting/derogatory comments, and personal or political attacks 21 | * Public or private harassment 22 | * Publishing others' private information, such as a physical or electronic address, without explicit permission 23 | * Other conduct which could reasonably be considered inappropriate in a professional setting 24 | 25 | ## Our Responsibilities 26 | 27 | Project maintainers are responsible for clarifying the standards of acceptable behavior and are expected to take appropriate and fair corrective action in response to any instances of unacceptable behavior. 28 | 29 | Project maintainers have the right and responsibility to remove, edit, or reject comments, commits, code, wiki edits, issues, and other contributions that are not aligned to this Code of Conduct, or to ban temporarily or permanently any contributor for other behaviors that they deem inappropriate, threatening, offensive, or harmful. 30 | 31 | ## Scope 32 | 33 | This Code of Conduct applies both within project spaces and in public spaces when an individual is representing the project or its community. Examples of representing a project or community include using an official project e-mail address, posting via an official social media account, or acting as an appointed representative at an online or offline event. Representation of a project may be further defined and clarified by project maintainers. 34 | 35 | ## Enforcement 36 | 37 | Instances of abusive, harassing, or otherwise unacceptable behavior may be reported by contacting one or all the project team members at their email addresses. The project team will review and investigate all complaints, and will respond in a way that it deems appropriate to the circumstances. The project team is obligated to maintain confidentiality with regard to the reporter of an incident. Further details of specific enforcement policies may be posted separately. 38 | 39 | Project maintainers who do not follow or enforce the Code of Conduct in good faith may face temporary or permanent repercussions as determined by other members of the project's leadership. 40 | 41 | ## Attribution 42 | 43 | This Code of Conduct is adapted from the [Contributor Covenant][homepage], version 1.4, available at [https://contributor-covenant.org/version/1/4][version] 44 | 45 | [homepage]: https://contributor-covenant.org 46 | [version]: https://contributor-covenant.org/version/1/4/ 47 | -------------------------------------------------------------------------------- /CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | # Contributing 2 | 3 | Thanks for your interest in the project! 4 | 5 | Any contribution, project participation and pull request from developers are welcome. All contributors agree to the Apache 2 license. Please follow this process: 6 | 7 | * Clone this repository or fork it. Create a new branch and add your modifications. 8 | * Remember to add unit tests to verify the desired behavior of the new features or methods. 9 | * When the first version of the code is ready, create a pull-request to the **development** branch of `iqusoft/intel-qs`. 10 | * Edits may be required to resolve conflicts since it is possible that the repository has changed while you worked on your new contribution. 11 | Please resolve the merge conflicts. 12 | * Verify that all unit tests, and not only the one added in the contribution, run correctly. 13 | * The IQS team will help with the revision of the pull-request. 14 | 15 | To facilitate the review consider starting with small contributions (a couple files and ~100 lines). 16 | For contributions that require substantial changes or changes in many files, please contact the IQS team to discuss the most effective strategy. 17 | 18 | Creating your pull request from a fork? We suggest allowing edits from maintainers. Then, anyone with Write access to the upstream repository will be able to add commits to your branch. This can make the review process easier for maintainers since they can make a small change themselves instead of asking you to make the change. 19 | 20 | If you would like to contribute to IQS, please visit our wiki page [https://github.com/intel/intel-qs/wiki/Contribute](https://github.com/intel/intel-qs/wiki/Contribute). 21 | -------------------------------------------------------------------------------- /Jenkinsfile: -------------------------------------------------------------------------------- 1 | pipeline { 2 | agent any 3 | 4 | stages { 5 | stage('Build') { 6 | steps { 7 | echo 'Building..' 8 | echo '$USER' 9 | sh 'sudo usermod -a -G docker $USER' 10 | sh '$WORKSPACE/docker_build' 11 | } 12 | } 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /benchmarks/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | add_executable(basic_code_for_scaling.exe basic_code_for_scaling.cpp) 2 | add_executable(specv2_bench.exe specv2_bench.cpp) 3 | target_link_libraries(basic_code_for_scaling.exe PRIVATE iqs) 4 | target_link_libraries(specv2_bench.exe PRIVATE iqs) 5 | 6 | set_target_properties( 7 | basic_code_for_scaling.exe 8 | specv2_bench.exe 9 | PROPERTIES 10 | RUNTIME_OUTPUT_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}/bin" 11 | ) 12 | -------------------------------------------------------------------------------- /benchmarks/output/.gitignore: -------------------------------------------------------------------------------- 1 | # Ignore everything 2 | * 3 | 4 | # But not this file 5 | !.gitignore 6 | -------------------------------------------------------------------------------- /benchmarks/script_pcl.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | #clear 3 | 4 | echo -e "\n#############################################################" 5 | echo -e "##### test of computational time using slurp ################" 6 | echo -e "#############################################################" 7 | 8 | ########################################################################## 9 | 10 | echo -e "\n -- Setting the simulation parameters -- \n" 11 | 12 | num_ranks=16 13 | num_threads_per_rank=1 14 | 15 | out_directory="output/" 16 | out_filename_root="basic_strong_scaling" 17 | num_qubits=28 18 | num_gates=1 19 | 20 | exec_args=" -nq "$num_qubits" -ng "$num_gates" -od "$out_directory" -of "$out_filename_root\ 21 | " -nt "$num_threads_per_rank 22 | 23 | ########################################################################## 24 | 25 | exec_name="basic_scaling" 26 | exec_file="./bin/basic_code_for_scaling.exe" 27 | 28 | ########################################################################## 29 | 30 | echo -e "\n -- Create the output folder if not present -- \n" 31 | 32 | if [ ! -d $out_directory ]; then 33 | mkdir $out_directory 34 | else 35 | # Eliminate the summary files if they exist. 36 | filename=$out_directory$out_filename_root"_first_q"$num_qubits".txt" 37 | echo "% Time cost (in sec) for 1-qubit gate on first qubit vs num_ranks" > $filename 38 | filename=$out_directory$out_filename_root"_last_q"$num_qubits".txt" 39 | echo "% Time cost (in sec) for 1-qubit gate on last qubit vs num_ranks" > $filename 40 | fi 41 | 42 | ########################################################################## 43 | 44 | echo -e " -- Creating the slurm job file -- \n" 45 | 46 | job_file="job_"$exec_name".slurm" 47 | job_content=\ 48 | "#!/bin/bash"$'\n\n'\ 49 | "#SBATCH -o "$out_directory$exec_name".o%j"$'\n'\ 50 | "#SBATCH -e "$out_directory$exec_name".err%j"$'\n'\ 51 | "#SBATCH -D ./"$'\n'\ 52 | "#SBATCH --get-user-env"$'\n'\ 53 | "#SBATCH --partition=clx"$'\n'\ 54 | "#SBATCH --time=01:00:00"$'\n'\ 55 | "#SBATCH --ntasks="$num_ranks$'\n'\ 56 | "#SBATCH --cpus-per-task="$num_threads_per_rank$'\n'\ 57 | "#SBATCH -J "$exec_name$'\n'\ 58 | "#SBATCH --mail-user=gian.giacomo.guerreschi@intel.com"$'\n'\ 59 | "#SBATCH --mail-type=begin --mail-type=end"$'\n\n'\ 60 | "export INTEL_LICENSE_FILE=/swtools/intel/licenses/"$'\n'\ 61 | "export I_MPI_HYDRA_BOOTSTRAP=slurm"$'\n\n'\ 62 | "mpiexec.hydra -genv I_MPI_DEBUG 4 -genv OMP_NUM_THREADS "$num_threads_per_rank\ 63 | " -genv KMP_AFFINITY granularity=thread,1,0,verbose -ppn $num_ranks "$exec_file" "$exec_args 64 | 65 | echo "$job_content" > $job_file 66 | 67 | ########################################################################## 68 | 69 | echo -e "\n -- Running the simulations in a single job -- \n" 70 | sbatch $job_file 71 | 72 | ########################################################################## 73 | -------------------------------------------------------------------------------- /cmake/FindMKL.cmake: -------------------------------------------------------------------------------- 1 | ################################################################################ 2 | # 3 | # \file cmake/FindMKL.cmake 4 | # \author J. Bakosi 5 | # \copyright 2012-2015, Jozsef Bakosi, 2016, Los Alamos National Security, LLC. 6 | # \brief Find the Math Kernel Library from Intel 7 | # \date Thu 26 Jan 2017 02:05:50 PM MST 8 | # 9 | ################################################################################ 10 | 11 | # Find the Math Kernel Library from Intel 12 | # 13 | # MKL_FOUND - System has MKL 14 | # MKL_INCLUDE_DIRS - MKL include files directories 15 | # MKL_LIBRARIES - The MKL libraries 16 | # MKL_INTERFACE_LIBRARY - MKL interface library 17 | # MKL_SEQUENTIAL_LAYER_LIBRARY - MKL sequential layer library 18 | # MKL_CORE_LIBRARY - MKL core library 19 | # 20 | # The environment variables MKLROOT and INTEL are used to find the library. 21 | # Everything else is ignored. If MKL is found "-DMKL_ILP64" is added to 22 | # CMAKE_C_FLAGS and CMAKE_CXX_FLAGS. 23 | # 24 | # Example usage: 25 | # 26 | # find_package(MKL) 27 | # if(MKL_FOUND) 28 | # target_link_libraries(TARGET ${MKL_LIBRARIES}) 29 | # endif() 30 | 31 | # If already in cache, be silent 32 | if (MKL_INCLUDE_DIRS AND MKL_LIBRARIES AND MKL_INTERFACE_LIBRARY AND 33 | MKL_SEQUENTIAL_LAYER_LIBRARY AND MKL_CORE_LIBRARY) 34 | set (MKL_FIND_QUIETLY TRUE) 35 | endif() 36 | 37 | if(NOT BUILD_SHARED_LIBS) 38 | set(INT_LIB "libmkl_intel_ilp64.a") 39 | set(SEQ_LIB "libmkl_sequential.a") 40 | set(THR_LIB "libmkl_intel_thread.a") 41 | set(COR_LIB "libmkl_core.a") 42 | else() 43 | set(INT_LIB "mkl_intel_ilp64") 44 | set(SEQ_LIB "mkl_sequential") 45 | set(THR_LIB "mkl_intel_thread") 46 | set(COR_LIB "mkl_core") 47 | endif() 48 | 49 | find_path(MKL_INCLUDE_DIR NAMES mkl.h HINTS $ENV{MKLROOT}/include) 50 | 51 | find_library(MKL_INTERFACE_LIBRARY 52 | NAMES ${INT_LIB} 53 | PATHS $ENV{MKLROOT}/lib 54 | $ENV{MKLROOT}/lib/intel64 55 | $ENV{INTEL}/mkl/lib/intel64 56 | NO_DEFAULT_PATH) 57 | 58 | find_library(MKL_SEQUENTIAL_LAYER_LIBRARY 59 | NAMES ${SEQ_LIB} 60 | PATHS $ENV{MKLROOT}/lib 61 | $ENV{MKLROOT}/lib/intel64 62 | $ENV{INTEL}/mkl/lib/intel64 63 | NO_DEFAULT_PATH) 64 | 65 | find_library(MKL_CORE_LIBRARY 66 | NAMES ${COR_LIB} 67 | PATHS $ENV{MKLROOT}/lib 68 | $ENV{MKLROOT}/lib/intel64 69 | $ENV{INTEL}/mkl/lib/intel64 70 | NO_DEFAULT_PATH) 71 | 72 | set(MKL_INCLUDE_DIRS ${MKL_INCLUDE_DIR}) 73 | set(MKL_LIBRARIES ${MKL_INTERFACE_LIBRARY} ${MKL_SEQUENTIAL_LAYER_LIBRARY} ${MKL_CORE_LIBRARY}) 74 | 75 | if (MKL_INCLUDE_DIR AND 76 | MKL_INTERFACE_LIBRARY AND 77 | MKL_SEQUENTIAL_LAYER_LIBRARY AND 78 | MKL_CORE_LIBRARY) 79 | 80 | if (NOT DEFINED ENV{CRAY_PRGENVPGI} AND 81 | NOT DEFINED ENV{CRAY_PRGENVGNU} AND 82 | NOT DEFINED ENV{CRAY_PRGENVCRAY} AND 83 | NOT DEFINED ENV{CRAY_PRGENVINTEL}) 84 | set(ABI "-m64") 85 | endif() 86 | 87 | set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -DMKL_ILP64 ${ABI}") 88 | set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -DMKL_ILP64 ${ABI}") 89 | 90 | else() 91 | 92 | set(MKL_INCLUDE_DIRS "") 93 | set(MKL_LIBRARIES "") 94 | set(MKL_INTERFACE_LIBRARY "") 95 | set(MKL_SEQUENTIAL_LAYER_LIBRARY "") 96 | set(MKL_CORE_LIBRARY "") 97 | 98 | endif() 99 | 100 | # Handle the QUIETLY and REQUIRED arguments and set MKL_FOUND to TRUE if 101 | # all listed variables are TRUE. 102 | INCLUDE(FindPackageHandleStandardArgs) 103 | FIND_PACKAGE_HANDLE_STANDARD_ARGS(MKL DEFAULT_MSG MKL_LIBRARIES MKL_INCLUDE_DIRS MKL_INTERFACE_LIBRARY MKL_SEQUENTIAL_LAYER_LIBRARY MKL_CORE_LIBRARY) 104 | 105 | MARK_AS_ADVANCED(MKL_INCLUDE_DIRS MKL_LIBRARIES MKL_INTERFACE_LIBRARY MKL_SEQUENTIAL_LAYER_LIBRARY MKL_CORE_LIBRARY) 106 | -------------------------------------------------------------------------------- /cmake/gtest.cmake.in: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 2.8.2) 2 | 3 | project(googletest-download NONE) 4 | 5 | include(ExternalProject) 6 | ExternalProject_Add(googletest 7 | GIT_REPOSITORY https://github.com/google/googletest.git 8 | GIT_TAG main 9 | SOURCE_DIR "${CMAKE_CURRENT_BINARY_DIR}/googletest-src" 10 | BINARY_DIR "${CMAKE_CURRENT_BINARY_DIR}/googletest-build" 11 | CONFIGURE_COMMAND "" 12 | BUILD_COMMAND "" 13 | INSTALL_COMMAND "" 14 | TEST_COMMAND "" 15 | ) 16 | -------------------------------------------------------------------------------- /docker_build: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | check_if_container_exists () { 4 | if test ! -z "$(docker ps -q --filter ancestor=qhipster)"; then 5 | mapfile -t my_array < <(docker ps -q --filter ancestor=qhipster) 6 | declare -p my_array 7 | echo "${my_array[0]}" 8 | # command docker exec -it "${my_array[0]}" /bin/bash 9 | # build_iqs_in_container 10 | else 11 | docker run -t -d qhipster 12 | container_id=$(docker ps -q --filter ancestor=qhipster) 13 | echo $container_id 14 | # command docker exec -it $container_id /bin/bash 15 | # build_iqs_in_container 16 | fi 17 | } 18 | 19 | #build_iqs_in_container () { 20 | #CXX=g++ cmake -DEnableMPI=OFF -DIqsUtest=ON -DIqsPython=OFF .. 21 | #make 22 | #} 23 | 24 | 25 | if test ! -z "$(docker images -q qhipster)"; then 26 | echo "already exists" 27 | check_if_container_exists 28 | else 29 | echo "doesnt exist" 30 | docker build --tag=qhipster . 31 | check_if_container_exists 32 | fi 33 | -------------------------------------------------------------------------------- /docs/Makefile: -------------------------------------------------------------------------------- 1 | # Minimal makefile for Sphinx documentation 2 | # 3 | 4 | # You can set these variables from the command line, and also 5 | # from the environment for the first two. 6 | SPHINXOPTS ?= 7 | SPHINXBUILD ?= sphinx-build 8 | SOURCEDIR = source 9 | BUILDDIR = build 10 | 11 | # Put it first so that "make" without argument is like "make help". 12 | help: 13 | @$(SPHINXBUILD) -M help "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O) 14 | 15 | .PHONY: help Makefile 16 | 17 | # Catch-all target: route all unknown targets to Sphinx using the new 18 | # "make mode" option. $(O) is meant as a shortcut for $(SPHINXOPTS). 19 | %: Makefile 20 | @$(SPHINXBUILD) -M $@ "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O) 21 | -------------------------------------------------------------------------------- /docs/directory_structure.md: -------------------------------------------------------------------------------- 1 | # Directory structure of Intel-QS 2 | 3 | ``` 4 | . 5 | |-- README.md 6 | |-- CMakeLists.txt 7 | |-- 8 | | 9 | |-- \docs 10 | | |-- 11 | | 12 | |-- \benchmarks 13 | | |-- CMakeLists.txt 14 | | |-- 15 | | 16 | |-- \interface 17 | | |-- CMakeLists.txt 18 | | |-- \include 19 | | |--
20 | | |-- \src 21 | | |-- CMakeLists.txt 22 | | |-- 23 | | 24 | |-- \include 25 | | |-- qureg.hpp 26 | | |--
27 | | 28 | |-- \src 29 | | |-- 30 | | |-- 31 | | 32 | |-- \pybind11 33 | | |-- intelqs_py.cpp 34 | | 35 | |-- \cmake 36 | | |-- FindMKL.cmake 37 | | |-- gtest.cmake.in 38 | | 39 | |-- \tutorials 40 | | |-- CMakeLists.txt 41 | | |-- get_started_with_IQS.cpp 42 | | |-- get_started_with_IQS.ipynb 43 | | |-- get_started_with_noisy_IQS.cpp 44 | | 45 | |-- \unit_test 46 | | |-- suite_of_tests.cpp 47 | | |-- \include 48 | | | |--
49 | | |-- \data 50 | | |-- 51 | | 52 | |-- \examples 53 | | |-- 54 | | 55 | |-- \notebooks 56 | |-- 57 | ``` 58 | -------------------------------------------------------------------------------- /docs/docker_guide.md: -------------------------------------------------------------------------------- 1 | ## Docker: build image and run/execute container 2 | 3 | `Dockerfile` includes the instructions to build the docker image of an Ubuntu machine 4 | with Intel-QS already installed. The image can be 'run' to create a container. 5 | The container can be 'executed' to login into the machine. 6 | For this, three steps need to be followed to prepare containerirzed intelqs simulator. 7 | 8 | * Create container 9 | * Configure SSH tunneling 10 | * Launch Jupyter notebook 11 | 12 | #### Create container 13 | 14 | Important: If user is not `root`, add `sudo` before each bash and docker command. 15 | In the code snippet below, the first command will build the docker image for Intel-QS 16 | The default namne is qhipster, but one can choose other names too. 17 | In the latter case, replace the chosen name in all other commands as well. 18 | The second command will create the container while mapping 8080 port to the localhost. 19 | The third command will enable conda env, execute cmake and make command, and launch Jupyter 20 | notebook in the terminal. Copy and save the printed token from the terminal. 21 | `Example of a given token : http://127.0.0.1:8080/?token=6ee42173ee71353c1f1b33f8feb33132aed15f2a07960bc8`. 22 | Last command is optional, this can be executed to loging to the container. 23 | 24 | ```bash 25 | docker build -t qhipster . 26 | docker run -d -t -p 8080:8080 qhipster 27 | docker exec -i $(docker ps|grep -i qhipster|cut -d ' ' -f1) /bin/bash -c ". ~/.bashrc && . /opt/intel/mkl/bin/mklvars.sh intel64 ilp64 && . /opt/intel/bin/compilervars.sh -arch intel64 -platform linux && mkdir build && cd build && CXX=g++ cmake -DIqsMPI=OFF -DIqsUtest=ON -DIqsPython=ON .. && make && cd .. && jupyter notebook --ip 0.0.0.0 --port 8080 --no-browser --allow-root" 28 | docker exec -it $(docker ps|grep -i qhipster|cut -d ' ' -f1) /bin/bash 29 | ``` 30 | 31 | If Docker is used on a Windows host machine, the last line should be substituted by: 32 | `winpty docker exec -it //bin/bash`. 33 | 34 | 35 | #### Configure SSH tunneling 36 | 37 | In local laptop, open Ubuntu emulator. This allows using the SSH protocol for port forwarding. 38 | For example, if you use MobaxTerm tool, launch a session and type following command in the mobxterm shell: 39 | 40 | ```bash 41 | ssh -L 8080:localhost:8080 user@domain.com 42 | ``` 43 | 44 | #### Launch Jupyter notebook 45 | 46 | Now, paste the copied token (which we copied from 'Create Container' section) in your preffered web browser 47 | (most importantly, please clear your browser cache before pasting the token). Once you are seeing all 48 | folders and files in browser, follow below section to begin. 49 | 50 | -------------------------------------------------------------------------------- /docs/make.bat: -------------------------------------------------------------------------------- 1 | @ECHO OFF 2 | 3 | pushd %~dp0 4 | 5 | REM Command file for Sphinx documentation 6 | 7 | if "%SPHINXBUILD%" == "" ( 8 | set SPHINXBUILD=sphinx-build 9 | ) 10 | set SOURCEDIR=source 11 | set BUILDDIR=build 12 | 13 | if "%1" == "" goto help 14 | 15 | %SPHINXBUILD% >NUL 2>NUL 16 | if errorlevel 9009 ( 17 | echo. 18 | echo.The 'sphinx-build' command was not found. Make sure you have Sphinx 19 | echo.installed, then set the SPHINXBUILD environment variable to point 20 | echo.to the full path of the 'sphinx-build' executable. Alternatively you 21 | echo.may add the Sphinx directory to PATH. 22 | echo. 23 | echo.If you don't have Sphinx installed, grab it from 24 | echo.http://sphinx-doc.org/ 25 | exit /b 1 26 | ) 27 | 28 | %SPHINXBUILD% -M %1 %SOURCEDIR% %BUILDDIR% %SPHINXOPTS% %O% 29 | goto end 30 | 31 | :help 32 | %SPHINXBUILD% -M help %SOURCEDIR% %BUILDDIR% %SPHINXOPTS% %O% 33 | 34 | :end 35 | popd 36 | -------------------------------------------------------------------------------- /docs/requirements.txt: -------------------------------------------------------------------------------- 1 | alabaster==0.7.12 2 | async-generator==1.10 3 | attrs==20.2.0 4 | Babel==2.9.1 5 | beautifulsoup4==4.9.3 6 | bleach==3.3.0 7 | breathe==4.23.0 8 | bs4==0.0.1 9 | certifi==2024.7.4 10 | chardet==3.0.4 11 | commonmark==0.9.1 12 | decorator==4.4.2 13 | defusedxml==0.6.0 14 | docutils==0.16 15 | entrypoints==0.3 16 | idna==3.7 17 | imagesize==1.2.0 18 | importlib-metadata==2.0.0 19 | ipython-genutils==0.2.0 20 | Jinja2==3.1.6 21 | jsonschema==3.2.0 22 | jupyter-client==6.1.7 23 | jupyter-core==4.11.2 24 | jupyterlab-pygments==0.1.2 25 | lxml==4.9.1 26 | MarkupSafe==1.1.1 27 | mistune==2.0.3 28 | nbclient==0.5.1 29 | nbconvert==6.5.1 30 | nbformat==5.0.8 31 | nbsphinx==0.8.0 32 | nest-asyncio==1.4.2 33 | packaging==20.4 34 | pandocfilters==1.4.3 35 | Pygments==2.15.0 36 | pyparsing==2.4.7 37 | pyrsistent==0.17.3 38 | python-dateutil==2.8.1 39 | pytz==2020.1 40 | pyzmq==19.0.2 41 | recommonmark==0.6.0 42 | requests==2.32.4 43 | six==1.15.0 44 | snowballstemmer==2.0.0 45 | soupsieve==2.0.1 46 | Sphinx==3.2.1 47 | sphinxcontrib-applehelp==1.0.2 48 | sphinxcontrib-devhelp==1.0.2 49 | sphinxcontrib-htmlhelp==1.0.3 50 | sphinxcontrib-jsmath==1.0.1 51 | sphinxcontrib-qthelp==1.0.3 52 | sphinxcontrib-serializinghtml==1.1.4 53 | testpath==0.4.4 54 | tornado==6.5.1 55 | traitlets==4.3.3 56 | urllib3==2.5.0 57 | webencodings==0.5.1 58 | zipp==3.19.1 59 | exhale==0.2.3 60 | -------------------------------------------------------------------------------- /docs/source/CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | # Contributing 2 | 3 | Thanks for your interest in the project! 4 | 5 | Any contribution, project participation and pull request from developers are welcome. Please follow this process: 6 | 7 | * Clone this repository or fork it. Create a new branch and add your modifications. 8 | * Remember to add unit tests to verify the desired behavior of the new features or methods. 9 | * When the first version of the code is ready, create a pull-request to the **development** branch of `iqusoft/intel-qs`. 10 | * Edits may be required to resolve conflicts since it is possible that the repository has changed while you worked on your new contribution. 11 | Please resolve the merge conflicts. 12 | * Verify that all unit tests, and not only the one added in the contribution, run correctly. 13 | * The IQS team will help with the revision of the pull-request. 14 | 15 | To facilitate the review consider starting with small contributions (a couple files and ~100 lines). 16 | For contributions that require substantial changes or changes in many files, please contact the IQS team to discuss the most effective strategy. 17 | 18 | Creating your pull request from a fork? We suggest allowing edits from maintainers. Then, anyone with Write access to the upstream repository will be able to add commits to your branch. This can make the review process easier for maintainers since they can make a small change themselves instead of asking you to make the change. 19 | 20 | If you would like to contribute to IQS, please visit our wiki page [https://github.com/iqusoft/intel-qs/wiki/Contribute](https://github.com/iqusoft/intel-qs/wiki/Contribute). 21 | -------------------------------------------------------------------------------- /docs/source/conf.py: -------------------------------------------------------------------------------- 1 | # Configuration file for the Sphinx documentation builder. 2 | # 3 | # This file only contains a selection of the most common options. For a full 4 | # list see the documentation: 5 | # https://www.sphinx-doc.org/en/master/usage/configuration.html 6 | 7 | # -- Path setup -------------------------------------------------------------- 8 | 9 | # If extensions (or modules to document with autodoc) are in another directory, 10 | # add these directories to sys.path here. If the directory is relative to the 11 | # documentation root, use os.path.abspath to make it absolute, like shown here. 12 | # 13 | # import os 14 | # import sys 15 | # sys.path.insert(0, os.path.abspath('.')) 16 | 17 | 18 | # -- Project information ----------------------------------------------------- 19 | 20 | project = 'Intel QS' 21 | copyright = '2020, Intel' 22 | author = 'Intel' 23 | 24 | 25 | # -- General configuration --------------------------------------------------- 26 | 27 | # Add any Sphinx extension module names here, as strings. They can be 28 | # extensions coming with Sphinx (named 'sphinx.ext.*') or your custom 29 | # ones. 30 | extensions = ['myst_parser', 'nbsphinx', 'breathe', 'exhale'] 31 | 32 | # Add any paths that contain templates here, relative to this directory. 33 | templates_path = ['_templates'] 34 | 35 | # List of patterns, relative to source directory, that match files and 36 | # directories to ignore when looking for source files. 37 | # This pattern also affects html_static_path and html_extra_path. 38 | exclude_patterns = [] 39 | 40 | 41 | # -- Options for HTML output ------------------------------------------------- 42 | 43 | # The theme to use for HTML and HTML Help pages. See the documentation for 44 | # a list of builtin themes. 45 | # 46 | html_theme = 'default' 47 | 48 | # Add any paths that contain custom static files (such as style sheets) here, 49 | # relative to this directory. They are copied after the builtin static files, 50 | # so a file named "default.css" will overwrite the builtin "default.css". 51 | html_static_path = ['_static'] 52 | 53 | source_parsers = { 54 | '.md': 'recommonmark.parser.CommonMarkParser', 55 | } 56 | 57 | source_suffix = ['.rst', '.md'] 58 | # Setup the breathe extension 59 | breathe_projects = { 60 | "My Project": "./doxyoutput/xml" 61 | } 62 | breathe_default_project = "My Project" 63 | 64 | # Setup the exhale extension 65 | exhale_args = { 66 | # These arguments are required 67 | "containmentFolder": "./api", 68 | "rootFileName": "library_root.rst", 69 | "rootFileTitle": "API References", 70 | "doxygenStripFromPath": "..", 71 | # Suggested optional arguments 72 | "createTreeView": True, 73 | # TIP: if using the sphinx-bootstrap-theme, you need 74 | # "treeViewIsBootstrap": True, 75 | "exhaleExecutesDoxygen": True, 76 | "exhaleDoxygenStdin": "INPUT = ../../include" 77 | } 78 | 79 | # Tell sphinx what the primary language being documented is. 80 | primary_domain = 'cpp' 81 | 82 | # Tell sphinx what the pygments highlight language should be. 83 | highlight_language = 'cpp' 84 | -------------------------------------------------------------------------------- /docs/source/index.rst: -------------------------------------------------------------------------------- 1 | .. Intel QS documentation master file, created by 2 | sphinx-quickstart on Tue Oct 27 20:11:28 2020. 3 | You can adapt this file completely to your liking, but it should at least 4 | contain the root `toctree` directive. 5 | 6 | Welcome to Intel QS's documentation! 7 | ==================================== 8 | 9 | .. toctree:: 10 | :maxdepth: 2 11 | 12 | getting-started 13 | 14 | .. toctree:: 15 | :maxdepth: 2 16 | :caption: Tutorials: 17 | 18 | get_started_examples 19 | qaoa_example 20 | 21 | .. toctree:: 22 | :maxdepth: 2 23 | :caption: Libraries: 24 | 25 | CONTRIBUTING 26 | 27 | .. toctree:: 28 | :maxdepth: 2 29 | 30 | api/library_root 31 | 32 | 33 | 34 | Indices and tables 35 | ================== 36 | 37 | * :ref:`genindex` 38 | * :ref:`modindex` 39 | * :ref:`search` 40 | -------------------------------------------------------------------------------- /docs/todo_list.md: -------------------------------------------------------------------------------- 1 | ## List of TODO 2 | 3 | Instead of printing TODO messages during compilation, the suggestions 4 | are collected here. 5 | The messages are left in the source code as comments (search for keyword TODO). 6 | 7 | 8 | highperfkernels.cpp: 9 | * Not using ICC vectorization: need to rewrite in intrincics 10 | * Allow for case where state is not aligned: need SIMD ISA for un-aligned access 11 | * Add nthreads check to clamp to smaller number if too little work 12 | * Generalize for AVX3 cases so we check for pos <=1 etc 13 | 14 | qureg_apply1qubitgate.cpp 15 | * Fix problem when coming here from controlled gate 16 | * Add diagonal special case 17 | 18 | qureg_applyctrl1qubitgate.cpp 19 | * Way to fix problem with X and Y specialization 20 | * Insert Loop_SN specialization for this case 21 | 22 | -------------------------------------------------------------------------------- /examples/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | ################################################################################ 2 | 3 | add_executable(benchgates.exe benchgates.cpp) 4 | target_link_libraries(benchgates.exe PRIVATE iqs) 5 | 6 | add_executable(grover_4qubit.exe grover_4qubit.cpp) 7 | target_link_libraries(grover_4qubit.exe PRIVATE iqs) 8 | 9 | add_executable(quantum_fourier_transform.exe quantum_fourier_transform.cpp) 10 | target_link_libraries(quantum_fourier_transform.exe iqs) 11 | 12 | add_executable(expect_value_test.exe expect_value_test.cpp) 13 | target_link_libraries(expect_value_test.exe iqs) 14 | 15 | add_executable(heisenberg_dynamics.exe heisenberg_dynamics.cpp) 16 | target_link_libraries(heisenberg_dynamics.exe iqs) 17 | 18 | add_executable(circuit_with_noise_gates.exe circuit_with_noise_gates.cpp) 19 | target_link_libraries(circuit_with_noise_gates.exe iqs) 20 | 21 | add_executable(noise_via_chi_matrix.exe noise_via_chi_matrix.cpp) 22 | target_link_libraries(noise_via_chi_matrix.exe iqs) 23 | 24 | add_executable(test_of_custom_gates.exe test_of_custom_gates.cpp) 25 | target_link_libraries(test_of_custom_gates.exe iqs) 26 | 27 | add_executable(communication_reduction_via_qubit_reordering.exe communication_reduction_via_qubit_reordering.cpp) 28 | target_link_libraries(communication_reduction_via_qubit_reordering.exe iqs) 29 | 30 | ################################################################################ 31 | 32 | set_target_properties( benchgates.exe 33 | quantum_fourier_transform.exe 34 | grover_4qubit.exe 35 | expect_value_test.exe 36 | heisenberg_dynamics.exe 37 | circuit_with_noise_gates.exe 38 | noise_via_chi_matrix.exe 39 | test_of_custom_gates.exe 40 | communication_reduction_via_qubit_reordering.exe 41 | PROPERTIES 42 | RUNTIME_OUTPUT_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}/bin" 43 | ) 44 | 45 | ################################################################################ 46 | -------------------------------------------------------------------------------- /examples/launcher_all_examples.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | echo -e "\n############################################################" 4 | echo -e "######## launch all examples one after the other ###########" 5 | echo -e "### (just to check that there are no compilation issues) ###" 6 | echo -e "############################################################\n" 7 | 8 | ########################################################################## 9 | 10 | # By default the launcher does not use MPI. 11 | # This can be changed by providing the argument "1" 12 | flag_with_mpi=0 13 | mpi_command="mpiexec.hydra" 14 | 15 | if [[ $# -eq 1 ]]; then 16 | flag_with_mpi=$1 17 | echo $flag_with_mpi 18 | fi 19 | 20 | if [ $flag_with_mpi == "1" ]; then 21 | echo "Run executables with MPI." 22 | else 23 | echo "Run executables without MPI." 24 | fi 25 | 26 | ########################################################################## 27 | 28 | declare -a examples_file_list=( 29 | "benchgates.exe" \ 30 | "circuit_with_noise_gates.exe" \ 31 | "communication_reduction_via_qubit_reordering.exe" \ 32 | "expect_value_test.exe" \ 33 | "grover_4qubit.exe" \ 34 | "heisenberg_dynamics.exe" \ 35 | "noise_via_chi_matrix.exe" \ 36 | "quantum_fourier_transform.exe" \ 37 | "test_of_custom_gates.exe" \ 38 | ) 39 | declare -a examples_num_procs_list=( 40 | "4" \ 41 | "10" \ 42 | "4" \ 43 | "1" \ 44 | "4" \ 45 | "4" \ 46 | "5" \ 47 | "8" \ 48 | "4" \ 49 | ) 50 | declare -a examples_parameter_list=( 51 | "12" \ 52 | "10" \ 53 | "24" \ 54 | " " \ 55 | " " \ 56 | "10" \ 57 | "6" \ 58 | "24" \ 59 | "12" \ 60 | ) 61 | 62 | ########################################################################## 63 | 64 | index=0 65 | for input_file in "${examples_file_list[@]}" 66 | do 67 | echo -e "\n-------------------" 68 | nprocs=${examples_num_procs_list[$index]} 69 | pars=${examples_parameter_list[$((index++))]} 70 | echo "executable = " $input_file 71 | echo "number of processes = " $nprocs 72 | echo "parameter values = " $pars 73 | if [ $flag_with_mpi == "1" ]; then 74 | $mpi_command -n $nprocs ./bin/$input_file $pars 75 | else 76 | ./bin/$input_file $pars 77 | fi 78 | done 79 | 80 | ########################################################################## 81 | -------------------------------------------------------------------------------- /include/QubitRegisterMetric.hpp: -------------------------------------------------------------------------------- 1 | #ifndef QUBIT_REGISTER_METRIC_HPP 2 | #define QUBIT_REGISTER_METRIC_HPP 3 | 4 | #include 5 | 6 | using namespace std; 7 | 8 | namespace iqs { 9 | 10 | template 11 | class QubitRegisterMetric: public QubitRegister { 12 | int iTotalQubitGateCount=0; 13 | int iOneQubitGateCount=0; 14 | int iTwoQubitGateCount=0; 15 | std::vector vParallelDepth; 16 | void OneQubitIncrements(int); 17 | void TwoQubitIncrements(int,int); 18 | 19 | public: 20 | //Constructor 21 | QubitRegisterMetric(int iNQubits):QubitRegister(iNQubits){ 22 | vParallelDepth.resize(iNQubits); 23 | } 24 | 25 | //Get stats 26 | int GetTotalQubitGateCount(); 27 | int GetOneQubitGateCount(); 28 | int GetTwoQubitGateCount(); 29 | int GetParallelDepth(); 30 | 31 | //Perform gates 32 | void ApplyHadamard(int); 33 | void ApplyRotationX(int, double); 34 | void ApplyRotationY(int, double); 35 | void ApplyRotationZ(int, double); 36 | void ApplyCPauliX(int, int); 37 | void ApplyControlled1QubitGate(int, int, iqs::TinyMatrix); 38 | }; 39 | 40 | template 41 | int QubitRegisterMetric::GetOneQubitGateCount(){ 42 | return iOneQubitGateCount; 43 | } 44 | 45 | template 46 | int QubitRegisterMetric::GetTwoQubitGateCount(){ 47 | return iTwoQubitGateCount; 48 | } 49 | 50 | template 51 | int QubitRegisterMetric::GetTotalQubitGateCount(){ 52 | return iTotalQubitGateCount; 53 | } 54 | 55 | template 56 | 57 | int QubitRegisterMetric::GetParallelDepth(){ 58 | return *std::max_element(std::begin(vParallelDepth), std::end(vParallelDepth)); 59 | } 60 | 61 | template 62 | void QubitRegisterMetric::OneQubitIncrements(int q){ 63 | iTotalQubitGateCount++; 64 | iOneQubitGateCount++; 65 | vParallelDepth[q]++; 66 | } 67 | 68 | template 69 | void QubitRegisterMetric::TwoQubitIncrements(int q1, int q2){ 70 | iTotalQubitGateCount++; 71 | iTwoQubitGateCount++; 72 | int iNewDepth = max(vParallelDepth[q1],vParallelDepth[q2])+1; 73 | vParallelDepth[q1]=iNewDepth; 74 | vParallelDepth[q2]=iNewDepth; 75 | } 76 | 77 | template 78 | void QubitRegisterMetric::ApplyHadamard(int q){ 79 | QubitRegister::ApplyHadamard(q); 80 | OneQubitIncrements(q); 81 | } 82 | 83 | template 84 | void QubitRegisterMetric::ApplyRotationX(int q, double theta){ 85 | QubitRegister::ApplyRotationX(q,theta); 86 | OneQubitIncrements(q); 87 | } 88 | 89 | template 90 | void QubitRegisterMetric::ApplyRotationY(int q, double theta){ 91 | QubitRegister::ApplyRotationY(q,theta); 92 | OneQubitIncrements(q); 93 | } 94 | 95 | template 96 | void QubitRegisterMetric::ApplyRotationZ(int q, double theta){ 97 | QubitRegister::ApplyRotationZ(q,theta); 98 | OneQubitIncrements(q); 99 | } 100 | 101 | template 102 | void QubitRegisterMetric::ApplyCPauliX(int q1, int q2){ 103 | QubitRegister::ApplyCPauliX(q1,q2); 104 | TwoQubitIncrements(q1,q2); 105 | } 106 | 107 | template 108 | void QubitRegisterMetric::ApplyControlled1QubitGate(int q1, int q2, iqs::TinyMatrix V){ 109 | QubitRegister::ApplyControlled1QubitGate(q1,q2,V); 110 | TwoQubitIncrements(q1,q2); 111 | } 112 | 113 | } // end namespace iqs 114 | 115 | #endif // header guard QUBIT_REGISTER_METRIC_HPP 116 | -------------------------------------------------------------------------------- /include/conversion.hpp: -------------------------------------------------------------------------------- 1 | // Copyright (C) 2016 Theoretical Physics, ETHZ Zurich 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | #ifndef IQS_CONVERSION_HPP 16 | #define IQS_CONVERSION_HPP 17 | 18 | /// \addtogroup util 19 | /// @{ 20 | 21 | /// @file conversion.hpp 22 | /// 23 | /// This header defines type conversion functions. 24 | 25 | #include 26 | #include 27 | #include 28 | 29 | namespace iqs { 30 | 31 | /// @brief convert to a string 32 | /// 33 | /// This function converts any value to a string, by writing it into a string stream. 34 | /// \param[in] val the value to be converted to a string 35 | /// \pre Writing into a std::istream using operator<< needs to be implemented for the type 36 | 37 | template 38 | std::string toString(T const& val) 39 | { 40 | std::ostringstream os; 41 | os << val; 42 | return os.str(); 43 | } 44 | 45 | } // namespace iqs 46 | 47 | /// @}*/ 48 | 49 | #endif // header guard IQS_CONVERSION_HPP 50 | -------------------------------------------------------------------------------- /include/gate_counter.hpp: -------------------------------------------------------------------------------- 1 | #ifndef IQS_GATE_COUNTER_HPP 2 | #define IQS_GATE_COUNTER_HPP 3 | 4 | #include 5 | 6 | ///////////////////////////////////////////////////////////////////////////////////////// 7 | 8 | /// @file gate_counter.hpp 9 | 10 | ///////////////////////////////////////////////////////////////////////////////////////// 11 | 12 | namespace iqs { 13 | 14 | /// \class GateCounter 15 | /// The GateCounter class serves two main purposes: 16 | /// 1) To count the number of gates applied, divided by kind. 17 | /// 2) To estimate the circuit depth if scheduled in a greedy way. 18 | class GateCounter 19 | { 20 | private: 21 | int num_qubits; 22 | int total_gate_count=0; 23 | int one_qubit_gate_count=0; 24 | int two_qubit_gate_count=0; 25 | std::vector parallel_depth; 26 | 27 | public: 28 | 29 | ///////////////////////////////////////////////////////////////////////////////////////// 30 | 31 | // Constructor 32 | GateCounter (int new_num_qubits) 33 | : num_qubits(new_num_qubits) 34 | { 35 | parallel_depth.assign(num_qubits,0); 36 | } 37 | 38 | // Destructor 39 | ~GateCounter() 40 | { } 41 | 42 | ///////////////////////////////////////////////////////////////////////////////////////// 43 | 44 | void Reset() 45 | { 46 | parallel_depth.assign(num_qubits,0); 47 | } 48 | 49 | ///////////////////////////////////////////////////////////////////////////////////////// 50 | 51 | //Get stats 52 | int GetTotalGateCount() { return total_gate_count; } 53 | int GetOneQubitGateCount() { return one_qubit_gate_count; } 54 | int GetTwoQubitGateCount() { return two_qubit_gate_count; } 55 | int GetParallelDepth() 56 | { return *std::max_element(std::begin(parallel_depth), std::end(parallel_depth)); } 57 | 58 | ///////////////////////////////////////////////////////////////////////////////////////// 59 | 60 | /// Update the counters and depth due to the action of a one-qubit gate. 61 | void OneQubitIncrement (int qubit) 62 | { 63 | ++total_gate_count; 64 | ++one_qubit_gate_count; 65 | ++parallel_depth[qubit]; 66 | } 67 | 68 | ///////////////////////////////////////////////////////////////////////////////////////// 69 | 70 | /// Update the counters and depth due to the action of a two-qubit gate. 71 | void TwoQubitIncrement (int qubit_0, int qubit_1) 72 | { 73 | ++total_gate_count; 74 | ++two_qubit_gate_count; 75 | int new_depth = std::max(parallel_depth[qubit_0], parallel_depth[qubit_1]) +1; 76 | parallel_depth[qubit_0] = new_depth; 77 | parallel_depth[qubit_1] = new_depth; 78 | } 79 | 80 | ///////////////////////////////////////////////////////////////////////////////////////// 81 | 82 | /// Print the values of counters and depth. 83 | void Breakdown() 84 | { 85 | if (iqs::mpi::Environment::GetStateRank() == 0) 86 | { 87 | printf("The quantum circuit is composed of %d one-qubit gates and " 88 | "%d two-qubitgates, for a total of %d gates.\nThe greedy depth " 89 | "(all gates lasting one clock cycle) is %d.\n", 90 | GetOneQubitGateCount(), GetTwoQubitGateCount(), 91 | GetTotalGateCount(), GetParallelDepth() ); 92 | } 93 | } 94 | 95 | }; 96 | 97 | ///////////////////////////////////////////////////////////////////////////////////////// 98 | 99 | } // end namespace iqs 100 | 101 | #endif // header guard IQS_GATE_COUNTER_HPP 102 | -------------------------------------------------------------------------------- /include/gate_spec.hpp: -------------------------------------------------------------------------------- 1 | /// @file gate_spec.hpp 2 | /// @brief Declare structs used in specialization v2. 3 | 4 | #ifndef GATE_SPEC_HPP 5 | #define GATE_SPEC_HPP 6 | 7 | namespace iqs { 8 | 9 | /// @brief Known 1-qubit gate types used internally with specialization v2 10 | enum class GateSpec1Q { 11 | Hadamard=0, 12 | RotationX, RotationY, RotationZ, 13 | PauliX, PauliY, PauliZ, 14 | T, 15 | None 16 | }; 17 | 18 | /// @brief Known 2-qubit gate types used internally with specialization v2 19 | enum class GateSpec2Q { 20 | CHadamard=0, 21 | CRotationX, CRotationY, CRotationZ, 22 | CPauliX, CPauliY, CPauliZ, 23 | CPhase, 24 | None 25 | }; 26 | 27 | GateSpec1Q ConvertSpec2to1(GateSpec2Q spec); 28 | 29 | } // end namespace iqs 30 | 31 | #endif 32 | -------------------------------------------------------------------------------- /include/highperfkernels.hpp: -------------------------------------------------------------------------------- 1 | #ifndef HIGH_PERF_KERNELS_HPP 2 | #define HIGH_PERF_KERNELS_HPP 3 | 4 | #include "qureg.hpp" 5 | 6 | namespace iqs { 7 | 8 | ///////////////////////////////////////////////////////////////////////////////////////// 9 | 10 | template< typename Type > 11 | __attribute__((noinline)) 12 | void Loop_SN(std::size_t start, std::size_t end, Type *state0, Type *state1, 13 | std::size_t indsht0, std::size_t indsht1, TM2x2 const&m, 14 | bool specialize, Timer *timer); 15 | 16 | 17 | template< typename Type > 18 | __attribute__((noinline)) 19 | void Loop_DN(std::size_t gstart, std::size_t gend, std::size_t pos, 20 | Type *state0, Type *state1, 21 | std::size_t indsht0, std::size_t indsht1, 22 | TM2x2 const&m, 23 | bool specialize, Timer *timer); 24 | 25 | template< typename Type > 26 | __attribute__((noinline)) 27 | void Loop_TN(Type *state, std::size_t c11, std::size_t c12, 28 | std::size_t c13, std::size_t c21, std::size_t c22, std::size_t c23, 29 | std::size_t c31, std::size_t c32, std::size_t ind_shift, 30 | TM2x2 const&m, bool specialize, Timer *timer); 31 | 32 | template< typename Type > 33 | void ScaleState(std::size_t start, std::size_t end, Type *state, 34 | const Type &s, Timer *timer); 35 | 36 | // for debugging purposes 37 | static __attribute__((noinline)) void LOOP_START() {printf("\n");} 38 | static __attribute__((noinline)) void LOOP_END() {printf("\n");} 39 | 40 | ///////////////////////////////////////////////////////////////////////////////////////// 41 | 42 | } // close namespace iqs 43 | 44 | #endif // header guard HIGH_PERF_KERNELS_HPP 45 | -------------------------------------------------------------------------------- /include/mpi_exception.hpp: -------------------------------------------------------------------------------- 1 | #ifndef IQS_MPI_EXCEPTION_HPP 2 | #define IQS_MPI_EXCEPTION_HPP 3 | 4 | /// \addtogroup util 5 | /// @{ 6 | 7 | /// @file mpi_exception.hpp 8 | /// 9 | /// This header includes the MPI library if available and provides some 10 | /// convenience functions that are implemented even if the MPI library is not provided. 11 | 12 | #include 13 | #include 14 | #include 15 | 16 | ///////////////////////////////////////////////////////////////////////////////////////// 17 | 18 | namespace iqs { 19 | 20 | namespace mpi { 21 | 22 | ///////////////////////////////////////////////////////////////////////////////////////// 23 | 24 | /// @brief Catch-all exception class for MPI errors. 25 | /// 26 | /// Similar to the MPI exception class in the Boost libraries. 27 | /// Instances of this class will be thrown when an MPI error occurs. 28 | class Exception : public std::exception 29 | { 30 | public: 31 | 32 | /// Build a new @c Exception exception. 33 | /// 34 | /// @param routine The MPI routine in which the error occurred. This should be a pointer 35 | /// to a string constant: it will not be copied. 36 | /// 37 | /// @param error_code The result code returned from the MPI routine that aborted with 38 | /// an error. 39 | Exception(const char* routine, int error_code); 40 | 41 | virtual ~Exception() throw(); 42 | 43 | /// A description of the error that occurred. 44 | virtual const char* what() const throw() { return this->description_.c_str(); } 45 | 46 | /// Retrieve the name of the MPI routine that reported the error. 47 | const char* routine() const { return routine_; } 48 | 49 | /// @brief Obtain the result code returned from the MPI routine that caused an error. 50 | int error_code() const { return error_code_; } 51 | 52 | private: 53 | /// The MPI routine that triggered the error. 54 | const char * routine_; 55 | /// The failure code reported by the MPI implementation. 56 | int error_code_; 57 | /// The formatted error description. 58 | std::string description_; 59 | }; 60 | 61 | ///////////////////////////////////////////////////////////////////////////////////////// 62 | 63 | /// Call the MPI routine MPIFunc with arguments Args (surrounded by parentheses). 64 | /// Checks the return value of MPIFunc call and throws a iqs::mpi::exception 65 | /// if the result is not MPI_SUCCESS. 66 | #define QHIPSTER_MPI_CHECK_RESULT(MPIFunc, Args) \ 67 | { \ 68 | int check_result = MPIFunc Args; \ 69 | if (check_result != MPI_SUCCESS) throw iqs::mpi::Exception(#MPIFunc,check_result);\ 70 | } 71 | 72 | ///////////////////////////////////////////////////////////////////////////////////////// 73 | 74 | } // end namespace mpi 75 | } // end namespace iqs 76 | 77 | /// @}*/ 78 | 79 | #endif // header guard IQS_MPI_EXCEPTION_HPP 80 | -------------------------------------------------------------------------------- /include/qureg_version.hpp: -------------------------------------------------------------------------------- 1 | //------------------------------------------------------------------------------ 2 | // Copyright 2017 Intel Corporation 3 | // 4 | // Licensed under the Apache License, Version 2.0 (the "License"); 5 | // you may not use this file except in compliance with the License. 6 | // You may obtain a copy of the License at 7 | // 8 | // http://www.apache.org/licenses/LICENSE-2.0 9 | // 10 | // Unless required by applicable law or agreed to in writing, software 11 | // distributed under the License is distributed on an "AS IS" BASIS, 12 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | // See the License for the specific language governing permissions and 14 | // limitations under the License. 15 | //------------------------------------------------------------------------------ 16 | 17 | #pragma once 18 | 19 | #include 20 | 21 | #define QHIPSTER_VERSION_STRING "SDK-RC-2.1.0" 22 | 23 | namespace iqs { 24 | std::string GetQhipsterVersion(void); 25 | } // close namespace iqs 26 | -------------------------------------------------------------------------------- /include/spec_kernels.hpp: -------------------------------------------------------------------------------- 1 | #ifndef SPEC_KERNELS_HPP 2 | #define SPEC_KERNELS_HPP 3 | 4 | #include "qureg.hpp" 5 | #include "gate_spec.hpp" 6 | 7 | using iqs::GateSpec1Q; 8 | using iqs::GateSpec2Q; 9 | 10 | namespace iqs { 11 | 12 | ///////////////////////////////////////////////////////////////////////////////////////// 13 | 14 | template< typename Type > 15 | __attribute__((noinline)) 16 | void Loop_SN(std::size_t gstart, std::size_t gend, 17 | Type *state0, Type *state1, 18 | std::size_t indsht0, std::size_t indsht1, 19 | GateSpec1Q spec, Timer *timer, double angle); 20 | 21 | template< typename Type > 22 | __attribute__((noinline)) 23 | void Loop_DN(std::size_t gstart, std::size_t gend, std::size_t pos, 24 | Type *state0, Type *state1, 25 | std::size_t indsht0, std::size_t indsht1, 26 | GateSpec1Q spec, Timer *timer, double angle=0); 27 | 28 | template 29 | __attribute__((noinline)) 30 | void Loop_TN(Type *state, 31 | std::size_t c11, std::size_t c12, std::size_t c13, 32 | std::size_t c21, std::size_t c22, std::size_t c23, 33 | std::size_t c31, std::size_t c32, 34 | std::size_t ind_shift, GateSpec2Q spec, Timer *timer, 35 | double angle=0); 36 | 37 | ///////////////////////////////////////////////////////////////////////////////////////// 38 | 39 | } // close namespace iqs 40 | 41 | #endif 42 | -------------------------------------------------------------------------------- /include/utils.hpp: -------------------------------------------------------------------------------- 1 | #ifndef IQS_UTILS_HPP 2 | #define IQS_UTILS_HPP 3 | 4 | #include 5 | 6 | // Helpful defines, if not already provided. 7 | #define DO_PRAGMA(x) _Pragma(#x) 8 | 9 | #ifndef TODO 10 | #define TODO(x) DO_PRAGMA(message("\033[30;43mTODO\033[0m - " #x)) 11 | #endif 12 | 13 | #ifndef INFO 14 | #define INFO(x) DO_PRAGMA(message("\033[30;46mINFO\033[0m - " #x)) 15 | #endif 16 | 17 | #define UL(x) ((std::size_t)(x)) 18 | #define sec() time_in_seconds() 19 | #define xstr(s) __str__(s) 20 | #define __str__(s) #s 21 | 22 | ///////////////////////////////////////////////////////////////////////////////////////// 23 | 24 | using ComplexSP = std::complex; 25 | using ComplexDP = std::complex; 26 | 27 | namespace iqs { 28 | 29 | ///////////////////////////////////////////////////////////////////////////////////////// 30 | 31 | // Structure to extract the value type of a template. 32 | template 33 | struct extract_value_type 34 | { 35 | typedef T value_type; 36 | }; 37 | 38 | // Structure to extract the value type of a template of template. 39 | template class X, typename T> 40 | struct extract_value_type> //specialization 41 | { 42 | typedef T value_type; 43 | }; 44 | 45 | ///////////////////////////////////////////////////////////////////////////////////////// 46 | 47 | double time_in_seconds(void); 48 | 49 | ///////////////////////////////////////////////////////////////////////////////////////// 50 | 51 | /// Utility method to inform on the currently set compiler flags. 52 | void WhatCompileDefinitions(); 53 | 54 | ///////////////////////////////////////////////////////////////////////////////////////// 55 | 56 | } // end namespace iqs 57 | 58 | #endif // header guard IQS_UTILS_HPP 59 | -------------------------------------------------------------------------------- /interface/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | add_subdirectory(src) 2 | 3 | -------------------------------------------------------------------------------- /interface/include/interface_api_memory.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | /** 4 | * \addtogroup interface 5 | * @{ 6 | */ 7 | 8 | /** 9 | * @file interface_api_memory.h 10 | * 11 | * This file provides handlers for malloc/free operations on sets of qubits. 12 | * 13 | */ 14 | 15 | 16 | /** 17 | * Parses the number of qubits to allocate from args and attempts to create a 18 | * quantum register with that number of qubits. 19 | * @param args A string representing the number of qubits to allocate (integer 0..inf) 20 | * @return 0 Success\n 21 | * >0 Error/Warning with message to STDERR. 22 | * 23 | * __side effect WARNING__!! Operates on a global wavefunction variable named (@ref psi1) 24 | */ 25 | unsigned long qumalloc(std::string args); 26 | 27 | 28 | /** 29 | * Free a qHiPSTER quantum register (wavefunction). 30 | * @param args Unused...can set to NULL. 31 | * @return 0 Success\n 32 | * >0 Error/Warning with message to STDERR. 33 | * 34 | * __side effect WARNING__!! Operates on a global wavefunction variable named (@ref psi1) 35 | */ 36 | unsigned long qufree(std::string args); 37 | 38 | /** @}*/ 39 | -------------------------------------------------------------------------------- /interface/include/interface_api_qasm.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | /** 4 | * \addtogroup interface 5 | * @{ 6 | */ 7 | 8 | /** 9 | * @file interface_api_qasm.h 10 | * 11 | * This file contains the interface to the QASM command handler function. The QASM 12 | * operation is broken up into a command token and an args token. The command is 13 | * mapped to a hash table of functions designed to handle the QASM op and then the 14 | * function is invoked and a result returned. 15 | * 16 | */ 17 | 18 | /** 19 | * Handle the execution of a QASM instruction in qHiPSTER. 20 | * @param op The QASM operation we wish to execute. 21 | * @param args The operands, if any, for the operation. 22 | * @return 0 Success - Op Handled\n 23 | * >0 Failure - Op not handled or error. 24 | */ 25 | unsigned long ExecuteHandler(std::string op, std::string args); 26 | 27 | /** @}*/ 28 | -------------------------------------------------------------------------------- /interface/include/interface_api_qubitid.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | /** 4 | * \addtogroup interface 5 | * @{ 6 | */ 7 | 8 | /** 9 | * @file interface_api_qubitid.h 10 | * 11 | * This header file contains functions for conveniently handling the assignment 12 | * of qubit identifiers to qubit strings passed in as operands to QASM instructions. 13 | */ 14 | 15 | 16 | /** 17 | * query_qubit_id() 18 | * @param qubit_name The string name passed from the QASM instruction. 19 | * @return An integer representing the the qubit identifier that matches the 20 | * qubit name string. If the qubit name is not found then an id is generated, 21 | * added to an internal tracking table, and the id is returned. 22 | */ 23 | int query_qubit_id(std::string qubit_name); 24 | 25 | /** @}*/ 26 | -------------------------------------------------------------------------------- /interface/include/interface_api_version.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | /** 4 | * \addtogroup interface 5 | * @{ 6 | */ 7 | 8 | /** 9 | * @file interface_api_version.h 10 | * 11 | * This header file contains functions for reporting the version of both the 12 | * QASM interface to qHiPSTER as well as the version of the qHiPSTER library 13 | * that was linked into the interface and in use. 14 | */ 15 | 16 | #define INTERFACE_VERSION_STRING "RC-1.1.0" 17 | 18 | /** 19 | * Print out the QASM interface version string. The format will be 20 | * major.minor.revision. 21 | * @param args Unused. 22 | * @return 0. 23 | */ 24 | unsigned long quiversion(std::string args); 25 | 26 | 27 | /** 28 | * Print out the qHiPSTER library version string. The format will be 29 | * major.minor.revision. 30 | * @param args Unused. 31 | * @return 0. 32 | */ 33 | unsigned long quversion(std::string args); 34 | 35 | /** @} */ 36 | -------------------------------------------------------------------------------- /interface/src/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | set(IQS_INTERFACE_FILES 2 | intelqs_interface_main.cpp 3 | interface_api_memory.cpp 4 | interface_api_qasm.cpp 5 | interface_api_qubitid.cpp 6 | interface_api_version.cpp 7 | CACHE INTERNAL "" FORCE) 8 | 9 | add_executable(iqs_interface.exe ${IQS_INTERFACE_FILES}) 10 | target_link_libraries(iqs_interface.exe iqs) 11 | 12 | set_target_properties( iqs_interface.exe 13 | PROPERTIES 14 | RUNTIME_OUTPUT_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}/../bin" 15 | ) 16 | 17 | 18 | 19 | -------------------------------------------------------------------------------- /interface/src/intelqs_interface_main.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | 7 | #include "../../include/qureg.hpp" 8 | #include "../include/interface_api_qasm.h" 9 | 10 | using namespace std; 11 | 12 | // Global variables related to Psi-function .malloc/.free routines. 13 | using Type = ComplexDP; 14 | iqs::QubitRegister *psi1 = nullptr; 15 | bool fPsiAllocated = false; 16 | 17 | int main(int argc, char*argv[]) 18 | { 19 | iqs::mpi::Environment env(argc, argv); 20 | string line = ""; 21 | string token = ""; 22 | 23 | if (env.IsUsefulRank() == false) 24 | return 0; 25 | 26 | int myid = env.GetStateRank(); 27 | using Type = ComplexDP; 28 | 29 | while(true) { 30 | getline(cin,line); 31 | 32 | if(line.length() >= 1) { 33 | int token_end = line.find_first_of(' '); 34 | unsigned long result = 1; 35 | 36 | token = line.substr(0,token_end); 37 | if(!token.empty()) { 38 | /* 39 | function func = qufun_table[token]; 40 | if(func) { 41 | result = func(line.substr(token_end+1,line.length())); 42 | } 43 | */ 44 | result = ExecuteHandler(token,line.substr(token_end+1,line.length())); 45 | 46 | if (result > 0) { 47 | cerr << "Qasm Op failed - ["< 2 | #include 3 | 4 | #include "../../include/qureg.hpp" 5 | 6 | using namespace std; 7 | 8 | 9 | // Global variables related to Psi-function .malloc/.free routines. 10 | using Type = ComplexDP; 11 | extern iqs::QubitRegister *psi1; 12 | extern bool fPsiAllocated; 13 | 14 | 15 | unsigned long qumalloc(string args) { 16 | 17 | int num_qubits = 0; 18 | 19 | // Check for an attempt at a memory leak. 20 | if (fPsiAllocated) { 21 | cerr << ".malloc called before .free - memory leak detected."< 0) && (num_qubits <= 43)) { 38 | psi1 = new iqs::QubitRegister(num_qubits); 39 | 40 | if (psi1) { 41 | (*psi1)[0] = 1; 42 | fPsiAllocated = true; 43 | cout << "Allocated ["< 2 | #include 3 | 4 | using namespace std; 5 | 6 | /** Qubits are assigned a unique identifier that starts from this base value. */ 7 | #define QUBIT_ID_BASE 100 8 | 9 | /** 10 | * @file interface_api_qubitid.cpp 11 | * 12 | * This file implements unique qubit id assignment and query operations. 13 | * 14 | * Each QASM instruction that comes into the qHiPSTER QASM interface has a 15 | * unique identifier string for the operand: 16 | * 17 | * H qubit0 18 | * CNOT qubit0,qubit1 19 | * ... 20 | * 21 | * qHiPSTER applies qubit operations to a register of qubits that are indexed 22 | * from [0...(N-1)] where N is the total number of qubits. For the QASM snippet 23 | * above, the qubits will be assigned a unique id in the order they are 24 | * encountered in the QASM. To explicitly assign qubit identifiers to qHiPSTER 25 | * register locations you must add the (qubit) instruction to your QASM in the 26 | * right order as follows: 27 | * 28 | * qubit qubit0 29 | * qubit qubit1 30 | * H qubit0 31 | * CNOT qubit0,qubit1 32 | * ... 33 | * 34 | * This ensures that qubit0 -> qreg[0], qubit1 -> qureg[1] in the qHiPSTER 35 | * quantum register space. 36 | * 37 | **/ 38 | 39 | // Hash table mapping unique qubit identifiers to each qubit operand. 40 | unordered_map qubit_id_table; 41 | 42 | // Variable to keep track of the next qubit to assign. 43 | int next_qubit_id = QUBIT_ID_BASE; 44 | 45 | 46 | // See the header file (interface_api_qubitid.h) for the description of the function. 47 | int query_qubit_id(string qubit_name) { 48 | 49 | // Retrieve the qubit_id from the qubit_id_table. 50 | int& qubit_ref = qubit_id_table[qubit_name]; 51 | 52 | // Insert a new qubit_id in the Hash table if we did not get back a valid one. 53 | if(qubit_ref < QUBIT_ID_BASE) 54 | { 55 | qubit_ref = next_qubit_id; 56 | next_qubit_id++; 57 | } 58 | 59 | // Translate the Hash encoded ID to a qHiPSTER API relevant ID and return it. 60 | //cout << "Assigned id: "< 2 | 3 | #include "../include/qureg_version.hpp" 4 | #include "../include/interface_api_version.h" 5 | 6 | unsigned long quiversion(std::string args) { 7 | 8 | std::cout << INTERFACE_VERSION_STRING << std::endl; 9 | 10 | return 0; 11 | } 12 | 13 | 14 | unsigned long quversion(std::string args) { 15 | 16 | std::cout << iqs::GetQhipsterVersion() << std::endl; 17 | 18 | return 0; 19 | } 20 | -------------------------------------------------------------------------------- /notebooks/print_distributed_state.py: -------------------------------------------------------------------------------- 1 | import sys 2 | sys.path.insert(0, '../build/lib') 3 | import intelqs_py as iqs 4 | import numpy as np 5 | 6 | 7 | def run_circuit(num_qubits): 8 | reg = iqs.QubitRegister(num_qubits, 'base', 0, 0) 9 | for i in range(num_qubits): 10 | reg.ApplyHadamard(i) 11 | reg.ApplyRotationZ(i, np.pi/3) 12 | return reg 13 | 14 | 15 | if __name__ == '__main__': 16 | if len(sys.argv) <= 1: 17 | print('Usage: {} '.format(sys.argv[0])) 18 | sys.exit(0) 19 | num_qubits = int(sys.argv[1]) 20 | 21 | iqs.EnvInit() 22 | if iqs.MPIEnvironment.IsUsefulRank()==False: 23 | iqs.EnvFinalize() 24 | exit() 25 | # The simulation of a N-qubit system cannot be divided in more than 2^(N-1) ranks. 26 | if iqs.MPIEnvironment.GetStateSize()>2**(num_qubits-1) or num_qubits<1: 27 | if iqs.MPIEnvironment.GetRank()==0: 28 | print("No more than 2^(N-1) useful ranks for a N-qubit state.") 29 | iqs.EnvFinalize() 30 | exit() 31 | 32 | reg = run_circuit(num_qubits) 33 | state_vector = np.array(reg, copy=False) 34 | 35 | rank = iqs.MPIEnvironment.GetRank() 36 | if num_qubits<7: 37 | print('\nFinal state at rank {}: {}'.format(rank, state_vector)) 38 | elif rank==0: 39 | print('\nState too large to be printed, try 4 qubits :-)\n') 40 | 41 | iqs.EnvFinalize() 42 | 43 | # SAMPLE RUNS: 44 | 45 | ## Single-Process: 46 | ''' 47 | python python_mpi.py 4 48 | [|s0>: 0] world_rank: 0 , state_rank: 0 (state 0 of 1) my_node_id: 0 , num_nodes: 1 , ranks/node: 1 , threads/rank: 72 --useful 49 | 50 | Final state at rank 0: [0.21650635-0.125j 0.21650635-0.125j 0.21650635-0.125j 0.21650635-0.125j 51 | 0.21650635-0.125j 0.21650635-0.125j 0.21650635-0.125j 0.21650635-0.125j 52 | 0.21650635+0.125j 0.21650635+0.125j 0.21650635+0.125j 0.21650635+0.125j 53 | 0.21650635+0.125j 0.21650635+0.125j 0.21650635+0.125j 0.21650635+0.125j] 54 | ''' 55 | 56 | ## Multi-Process: 57 | ''' 58 | mpiexec.hydra -n 2 python python_mpi.py 4 59 | [|s0>: 0] world_rank: 0 , state_rank: 0 (state 0 of 1) my_node_id: 0 , num_nodes: 1 , ranks/node: 2 , threads/rank: 36 --useful 60 | [|s0>: 1] world_rank: 1 , state_rank: 1 (state 0 of 1) my_node_id: 0 , num_nodes: 1 , ranks/node: 2 , threads/rank: 36 --useful 61 | 62 | Final state at rank 0: [0.21650635-0.125j 0.21650635-0.125j 0.21650635-0.125j 0.21650635-0.125j 63 | 0.21650635-0.125j 0.21650635-0.125j 0.21650635-0.125j 0.21650635-0.125j] 64 | 65 | Final state at rank 1: [0.21650635+0.125j 0.21650635+0.125j 0.21650635+0.125j 0.21650635+0.125j 66 | 0.21650635+0.125j 0.21650635+0.125j 0.21650635+0.125j 0.21650635+0.125j] 67 | ''' 68 | -------------------------------------------------------------------------------- /pybind11/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | ################################################################################ 2 | # Build the Python library for the IQS wrapper. 3 | 4 | find_package(pybind11 REQUIRED) 5 | 6 | if (NOT IqsMPI) 7 | set(NAME_PY_LIB intelqs_py) 8 | else() 9 | set(NAME_PY_LIB intelqs_py) 10 | endif() 11 | 12 | pybind11_add_module(${NAME_PY_LIB} SHARED 13 | intelqs_py.cpp 14 | ../src/chi_matrix.cpp 15 | ../src/qaoa_features.cpp) 16 | 17 | target_link_libraries(${NAME_PY_LIB} PRIVATE iqs) 18 | 19 | set_target_properties(${NAME_PY_LIB} 20 | PROPERTIES 21 | LIBRARY_OUTPUT_DIRECTORY "${PROJECT_BINARY_DIR}/lib" 22 | ) 23 | 24 | ################################################################################ 25 | -------------------------------------------------------------------------------- /src/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | ################################################################################ 2 | # Construction of IQS as a shared library 3 | ################################################################################ 4 | 5 | if (IqsNoise) 6 | # Download and unpack eigen library at configure time. 7 | cmake_minimum_required(VERSION 3.12.0) 8 | include(ExternalProject) 9 | ExternalProject_Add(deps-eigen 10 | GIT_REPOSITORY https://gitlab.com/libeigen/eigen.git 11 | PREFIX "${CMAKE_BINARY_DIR}/deps/eigen-prefix/" 12 | CONFIGURE_COMMAND "" 13 | BUILD_COMMAND "" 14 | INSTALL_COMMAND "" 15 | GIT_SHALLOW 1 16 | ) 17 | message(STATUS "Eigen library is downloaded in: ${PROJECT_BINARY_DIR}/deps/eigen-prefix/src/eigen/") 18 | endif() 19 | 20 | ################################################################################ 21 | 22 | set(IQS_FILES 23 | chi_matrix.cpp 24 | highperfkernels.cpp 25 | spec_kernels.cpp 26 | qureg_apply1qubitgate.cpp 27 | qureg_apply2qubitgate.cpp 28 | qureg_applyctrl1qubitgate.cpp 29 | qureg_applydiag.cpp 30 | qureg_apply_channel.cpp 31 | qureg_applyswap.cpp 32 | qureg_applytoffoli.cpp 33 | qureg_expectval.cpp 34 | qureg_fusion.cpp 35 | qureg_init.cpp 36 | qureg_measure.cpp 37 | qureg_noisysimul.cpp 38 | qureg_permute.cpp 39 | qureg_utils.cpp 40 | qureg_version.cpp 41 | mpi_env.cpp 42 | mpi_exception.cpp 43 | utils.cpp 44 | rng_utils.cpp 45 | gate_spec.cpp 46 | CACHE INTERNAL "" FORCE) 47 | 48 | if(IqsBuildAsStatic) 49 | add_library(iqs STATIC ${IQS_FILES}) 50 | else() 51 | add_library(iqs SHARED ${IQS_FILES}) 52 | endif() 53 | 54 | target_include_directories(iqs PUBLIC ../include) 55 | target_include_directories(iqs INTERFACE $) 56 | 57 | if (IqsNoise) 58 | add_dependencies(iqs deps-eigen) 59 | target_include_directories(iqs PUBLIC ${CMAKE_BINARY_DIR}/deps/eigen-prefix/src/deps-eigen/Eigen) 60 | # When using ICC, there is a verbose warning from the external library 'eigen'. Disable the warning: 61 | if(CMAKE_CXX_COMPILER_ID MATCHES Intel) 62 | target_compile_options(iqs PUBLIC -wd2196) 63 | endif() 64 | endif() 65 | 66 | set_target_properties(iqs 67 | PROPERTIES 68 | ARCHIVE_OUTPUT_DIRECTORY "${PROJECT_BINARY_DIR}/lib" 69 | LIBRARY_OUTPUT_DIRECTORY "${PROJECT_BINARY_DIR}/lib" 70 | POSITION_INDEPENDENT_CODE 1 71 | ) 72 | 73 | #add_subdirectory(interface) 74 | -------------------------------------------------------------------------------- /src/gate_spec.cpp: -------------------------------------------------------------------------------- 1 | #include "../include/gate_spec.hpp" 2 | using iqs::GateSpec1Q; 3 | using iqs::GateSpec2Q; 4 | 5 | GateSpec1Q iqs::ConvertSpec2to1(GateSpec2Q spec) 6 | { 7 | switch (spec) 8 | { 9 | case GateSpec2Q::CHadamard: 10 | return GateSpec1Q::Hadamard; 11 | case GateSpec2Q::CRotationX: 12 | return GateSpec1Q::RotationX; 13 | case GateSpec2Q::CRotationY: 14 | return GateSpec1Q::RotationY; 15 | case GateSpec2Q::CRotationZ: 16 | return GateSpec1Q::RotationZ; 17 | case GateSpec2Q::CPauliX: 18 | return GateSpec1Q::PauliX; 19 | case GateSpec2Q::CPauliY: 20 | return GateSpec1Q::PauliY; 21 | case GateSpec2Q::CPauliZ: 22 | return GateSpec1Q::PauliZ; 23 | default: 24 | return GateSpec1Q::None; 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /src/mpi_exception.cpp: -------------------------------------------------------------------------------- 1 | // Copyright (C) 2016 Theoretical Physics, ETHZ Zurich 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | /// @file mpi_env.cpp 16 | /// 17 | /// This header implements MPI support functionality 18 | 19 | #ifdef INTELQS_HAS_MPI 20 | #include 21 | #endif 22 | 23 | #include 24 | #include 25 | 26 | #include "../include/mpi_exception.hpp" 27 | 28 | ///////////////////////////////////////////////////////////////////////////////////////// 29 | 30 | namespace iqs { 31 | 32 | namespace mpi { 33 | 34 | ///////////////////////////////////////////////////////////////////////////////////////// 35 | 36 | Exception::Exception(const char* routine, int error_code) 37 | : routine_(routine), error_code_(error_code) 38 | { 39 | #ifndef INTELQS_HAS_MPI 40 | assert(0); 41 | #else 42 | // Get the error message from the MPI implementation. 43 | char buffer[MPI_MAX_ERROR_STRING]; 44 | int len; 45 | MPI_Error_string(error_code, buffer, &len); 46 | 47 | if (routine!=nullptr) 48 | description_ = std::string(routine) + ": " + std::string(buffer); 49 | else 50 | description_ = "Error in exception handling since 'routine' or 'buffer' are NULL"; 51 | #endif 52 | } 53 | 54 | Exception::~Exception() throw() {} 55 | 56 | ///////////////////////////////////////////////////////////////////////////////////////// 57 | 58 | } // end namespace mpi 59 | } // end namespace iqs 60 | 61 | ///////////////////////////////////////////////////////////////////////////////////////// 62 | -------------------------------------------------------------------------------- /src/qureg_apply2qubitgate.cpp: -------------------------------------------------------------------------------- 1 | /// @file qureg_apply2qubitgate.cpp 2 | /// @brief Define the @c QubitRegister method corresponding to the application of arbitrary two-qubit gates. 3 | 4 | #include "../include/qureg.hpp" 5 | #include "../include/highperfkernels.hpp" 6 | 7 | namespace iqs { 8 | 9 | ///////////////////////////////////////////////////////////////////////////////////////// 10 | /// @brief Arbitrary two-qubit gate. 11 | /// @param qubit_high index of the first qubit 12 | /// @param qubit_low index of the second qubit 13 | /// @param m 4x4 matrix corresponding to the quantum gate 14 | template 15 | void QubitRegister::Apply2QubitGate(unsigned const qubit_high, unsigned const qubit_low, 16 | TM4x4 const&m) 17 | { 18 | unsigned myrank=0, nprocs=1, log2_nprocs=0; 19 | myrank = iqs::mpi::Environment::GetStateRank(); 20 | nprocs = iqs::mpi::Environment::GetStateSize(); 21 | 22 | // TODO: The general case has not been implemented yet for distributed computation. 23 | assert(nprocs == 1); 24 | 25 | std::size_t n = GlobalSize(); 26 | assert(iqs::isPowerOf2(n)); 27 | assert(qubit_low < iqs::highestBit(n)); 28 | assert(qubit_high < iqs::highestBit(n)); 29 | assert(qubit_low != qubit_high); 30 | 31 | unsigned position_high = (*qubit_permutation)[qubit_high]; 32 | unsigned position_low = (*qubit_permutation)[qubit_low ]; 33 | assert(position_high < num_qubits); 34 | assert(position_low < num_qubits); 35 | assert(position_low != position_high); 36 | 37 | std::size_t dh = 1UL << position_high; 38 | std::size_t dl = 1UL << position_low; 39 | 40 | // It is easier if the qubit indices are ordered, meaning that: 41 | // qubit_high > qubit_low 42 | // if not, we take this into account with the variable 'invert'. 43 | bool const invert = qubit_low > qubit_high; 44 | 45 | // Does the compiler pull out the if-statements and thus perform the 46 | // branching outside of the loops when optimizing? 47 | for (std::size_t i = 0; i < n; i += 2 * (invert ? dl : dh)) 48 | { 49 | for (std::size_t j = 0; j < (invert ? dl : dh); j += 2 * (invert ? dh : dl)) 50 | { 51 | for (std::size_t k = 0; k < (invert ? dh : dl); ++k) 52 | { 53 | auto tmp = i + j + k; 54 | std::size_t idx[] = {tmp, tmp + dl, tmp + dh, tmp + dh + dl}; 55 | 56 | auto uu = state[idx[0]]; // 00 57 | auto ud = state[idx[1]]; // 01 58 | auto du = state[idx[2]]; // 10 59 | auto dd = state[idx[3]]; // 11 60 | 61 | for (unsigned t = 0; t < 4; ++t) 62 | state[idx[t]] = m[t][0] * uu + m[t][1] * ud + m[t][2] * du + m[t][3] * dd; 63 | } 64 | } 65 | } 66 | 67 | // Update counter of the statistics. 68 | if (gate_counter != nullptr) 69 | { 70 | // IQS count the gates acting on specific program qubits. 71 | gate_counter->TwoQubitIncrement(qubit_high, qubit_low); 72 | } 73 | } 74 | 75 | template class QubitRegister; 76 | template class QubitRegister; 77 | 78 | } // end namespace iqs 79 | -------------------------------------------------------------------------------- /src/qureg_applytoffoli.cpp: -------------------------------------------------------------------------------- 1 | //TODO("The Toffoli gate creates problem to the unit test in github workflow.") 2 | 3 | #include "../include/qureg.hpp" 4 | #include "../include/highperfkernels.hpp" 5 | 6 | /// \addtogroup qureg 7 | /// @{ 8 | 9 | /// @file qureg_applytoffoli.cpp 10 | /// @brief Define the @c QubitRegister method for the application of the Toffoli gate. 11 | 12 | namespace iqs { 13 | 14 | ///////////////////////////////////////////////////////////////////////////////////////// 15 | /// @brief Apply the Toffoli gate. 16 | /// @param control_1 index of the 1st control qubit 17 | /// @param control_2 index of the 2nd control qubit 18 | /// @param target index of the target qubit 19 | /// 20 | /// Implemented by decomposing the Toffoli gate in 5 two-qubit gates. 21 | /// Courtesy of Sonika Johri. 22 | /// If both control qubits are in state |1\>, then the target qubit is flipped. 23 | template 24 | void QubitRegister::ApplyToffoli(unsigned const control_1, 25 | unsigned const control_2, 26 | unsigned const target) 27 | { 28 | iqs::TinyMatrix V; 29 | V(0,0)={1.0/2.0,-1.0/2.0}; 30 | V(0,1)={1.0/2.0,1.0/2.0}; 31 | V(1,0)={1.0/2.0,1.0/2.0}; 32 | V(1,1)={1.0/2.0,-1.0/2.0}; 33 | 34 | iqs::TinyMatrix V_dag; 35 | V_dag(0,0)={1.0/2.0,1.0/2.0}; 36 | V_dag(0,1)={1.0/2.0,-1.0/2.0}; 37 | V_dag(1,0)={1.0/2.0,-1.0/2.0}; 38 | V_dag(1,1)={1.0/2.0,1.0/2.0}; 39 | 40 | ApplyControlled1QubitGate( control_1, target, V ); 41 | ApplyCPauliX( control_2, control_1 ); 42 | ApplyControlled1QubitGate( control_1, target, V_dag ); 43 | ApplyCPauliX( control_2, control_1 ); 44 | ApplyControlled1QubitGate( control_2, target, V ); 45 | 46 | return; 47 | } 48 | 49 | template class QubitRegister; 50 | template class QubitRegister; 51 | 52 | } // end namespace iqs 53 | 54 | /// @} 55 | -------------------------------------------------------------------------------- /src/qureg_fusion.cpp: -------------------------------------------------------------------------------- 1 | #include "../include/qureg.hpp" 2 | 3 | /// \addtogroup qureg 4 | /// @{ 5 | 6 | /// @file qureg_fusion.cpp 7 | /// @brief Define the @c QubitRegister methods related to an optimization called 'fusion'. 8 | 9 | namespace iqs { 10 | 11 | ///////////////////////////////////////////////////////////////////////////////////////// 12 | template 13 | void QubitRegister::TurnOnFusion(unsigned log2llc) 14 | { 15 | unsigned myrank=0, nprocs=1, log2_nprocs=0; 16 | #ifdef INTELQS_HAS_MPI 17 | myrank = iqs::mpi::Environment::GetStateRank(); 18 | nprocs = iqs::mpi::Environment::GetStateSize(); 19 | log2_nprocs = iqs::ilog2(nprocs); 20 | #endif 21 | unsigned M = num_qubits - log2_nprocs; 22 | 23 | if (log2llc >= M) { 24 | if (!myrank) printf("Fusion is not enabled: num_qubits (%lu) is too small\n", num_qubits); 25 | fusion = false; 26 | } else { 27 | if (!myrank) printf("Fusion is enabled: log2llc = %u num_qubits = %lu\n", log2llc, num_qubits); 28 | this->log2llc = log2llc; 29 | fusion = true; 30 | } 31 | } 32 | 33 | 34 | ///////////////////////////////////////////////////////////////////////////////////////// 35 | template 36 | void QubitRegister::TurnOffFusion() 37 | { 38 | if (fwindow.size()) 39 | { 40 | ApplyFusedGates(); 41 | } 42 | fusion = false; 43 | } 44 | 45 | 46 | ///////////////////////////////////////////////////////////////////////////////////////// 47 | template 48 | bool QubitRegister::IsFusionEnabled() 49 | { 50 | return fusion; 51 | } 52 | 53 | 54 | ///////////////////////////////////////////////////////////////////////////////////////// 55 | template 56 | void QubitRegister::ApplyFusedGates() 57 | { 58 | #if 0 59 | std::size_t myrank = iqs::mpi::Environment::GetStateRank(); 60 | if ( myrank==0 && fwindow.size() > 1) { 61 | printf("fused: "); 62 | for (auto &f : fwindow) { 63 | std::string &type = std::get<0>(f); 64 | unsigned qubit1 = std::get<2>(f); 65 | unsigned qubit2 = std::get<3>(f); 66 | if (type == "sqg") 67 | printf("[%s %u] ", type.c_str(), qubit1); 68 | else 69 | printf("[%s %u %u] ", type.c_str(), qubit1, qubit2); 70 | } 71 | printf("\n"); 72 | } 73 | #endif 74 | 75 | size_t blocksize = (fwindow.size() == 1) ? LocalSize() : (1L << UL(log2llc)); 76 | for (size_t l = 0; l < LocalSize(); l += blocksize) { 77 | for (auto &f : fwindow) { 78 | // check if work has been done 79 | std::string &type = std::get<0>(f); 80 | TM2x2 &m = std::get<1>(f); 81 | std::size_t qubit1 = std::get<2>(f); 82 | std::size_t qubit2 = std::get<3>(f); 83 | if (type == "sqg") { 84 | Apply1QubitGate_helper(qubit1, m, l, l + blocksize); 85 | } else if (type == "cqg") { 86 | ApplyControlled1QubitGate_helper(qubit1, qubit2, m, l, l + blocksize); 87 | } else { 88 | assert(0); // not yet implemented 89 | } 90 | 91 | } 92 | } 93 | fwindow.resize(0); 94 | } 95 | 96 | template class QubitRegister; 97 | template class QubitRegister; 98 | 99 | } // end namespace iqs 100 | 101 | /// @} 102 | -------------------------------------------------------------------------------- /src/qureg_noisysimul.cpp: -------------------------------------------------------------------------------- 1 | #include "../include/qureg.hpp" 2 | 3 | /// \addtogroup qureg 4 | /// @{ 5 | 6 | /// @file qureg_noisysimul.cpp 7 | /// @brief Define the @c QubitRegister methods related to implementing simulations 8 | /// in presence of noise. 9 | 10 | namespace iqs { 11 | 12 | ///////////////////////////////////////////////////////////////////////////////////////// 13 | /// @brief Set the timescale of dissipation and decoherence. 14 | /// @param T1 dissipation time 15 | /// @param T1 decoherence time 16 | 17 | template 18 | void QubitRegister::SetNoiseTimescales (BaseType T1, BaseType T2) 19 | { 20 | // Physically, dissipation also causes decoherence to enforce the positivity of the 21 | // density matrix. In particular, T2 >= T1/2; 22 | assert(T2 >= T1/2.); 23 | // Set internal variables of the Qubit Register. 24 | T_1_ = T1; 25 | T_2_ = T2; 26 | T_phi_ = 1./( 1./T2 - 1./(2.*T1) ); 27 | } 28 | 29 | ///////////////////////////////////////////////////////////////////////////////////////// 30 | /// @brief Apply stochastic noise gate. 31 | /// @param qubit the index of the involved qubit 32 | 33 | template 34 | void QubitRegister::ApplyNoiseGate(unsigned qubit, BaseType duration) 35 | { 36 | assert (rng_ptr_ != nullptr); 37 | if (duration==0) return; 38 | 39 | BaseType p_X , p_Y , p_Z ; 40 | p_X = (1. - std::exp(-duration/T_1_) )/4.; 41 | p_Y = (1. - std::exp(-duration/T_1_) )/4.; 42 | p_Z = (1. - std::exp(-duration/T_2_) )/2. + (1. - std::exp(-duration/T_1_) )/4.; 43 | assert( p_X>0 && p_Y>0 && p_Z>0 ); 44 | 45 | // Computation of the standard deviations for the noise gate parameters 46 | BaseType s_X , s_Y , s_Z ; 47 | s_X = std::sqrt( -std::log(1.-p_X) ); 48 | s_Y = std::sqrt( -std::log(1.-p_Y) ); 49 | s_Z = std::sqrt( -std::log(1.-p_Z) ); 50 | 51 | // Generate angle and direction of Pauli rotation for Pauli-twirl noise channel. 52 | // Each random number is shared between the ranks of the same quantum state. 53 | BaseType v_X , v_Y , v_Z; 54 | rng_ptr_->GaussianRandomNumbers(&v_X, 1, "state"); 55 | v_X *= s_X /2.; 56 | rng_ptr_->GaussianRandomNumbers(&v_Y, 1, "state"); 57 | v_Y *= s_Y /2.; 58 | rng_ptr_->GaussianRandomNumbers(&v_Z, 1, "state"); 59 | v_Z *= s_Z /2.; 60 | 61 | // Direct construction of the 2x2 matrix corresponding to the noise gate 62 | // U_noise = exp(-i v_X X) * exp(-i v_Y Y) * exp(-i v_Z Z) 63 | // Helpful quantities: 64 | // (A) = cos v_z -i sin v_z 65 | // (B) = cos v_x * cos v_Y -i sin v_X * sin v_Y 66 | // (C) = cos v_x * sin v_Y -i sin v_X * cos v_Y 67 | // Then : 68 | // | A*B -A'*C' | 69 | // U_noise = | | 70 | // | A*C A'*B' | 71 | 72 | Type A , B , C ; 73 | A = { std::cos(v_Z) , -std::sin(v_Z) }; 74 | B = { std::cos(v_X)*std::cos(v_Y) , -std::sin(v_X)*std::sin(v_Y) }; 75 | C = { std::cos(v_X)*std::sin(v_Y) , -std::sin(v_X)*std::cos(v_Y) }; 76 | 77 | iqs::TinyMatrix U_noise; 78 | U_noise(0, 0) = A*B; 79 | U_noise(0, 1) = -std::conj(A)*std::conj(C); 80 | U_noise(1, 0) = A*C; 81 | U_noise(1, 1) = std::conj(A)*std::conj(B); 82 | 83 | // Apply the noise gate 84 | QubitRegister::Apply1QubitGate(qubit,U_noise); 85 | } 86 | 87 | ///////////////////////////////////////////////////////////////////////////////////////// 88 | ///////////////////////////////////////////////////////////////////////////////////////// 89 | 90 | template class QubitRegister; 91 | template class QubitRegister; 92 | 93 | } // end namespace iqs 94 | 95 | /// @} 96 | -------------------------------------------------------------------------------- /src/qureg_version.cpp: -------------------------------------------------------------------------------- 1 | #include "../include/qureg_version.hpp" 2 | 3 | namespace iqs { 4 | 5 | std::string GetQhipsterVersion( ) { 6 | return QHIPSTER_VERSION_STRING; 7 | } 8 | 9 | } // close namespace iqs 10 | -------------------------------------------------------------------------------- /src/utils.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | #include "../include/timer.hpp" 5 | 6 | namespace iqs { 7 | 8 | ///////////////////////////////////////////////////////////////////////////////////////// 9 | 10 | double time_in_seconds(void) 11 | { 12 | struct timeval tv; 13 | gettimeofday(&tv, NULL); 14 | return (double)tv.tv_sec + (double)tv.tv_usec / 1000000.0; 15 | } 16 | 17 | ///////////////////////////////////////////////////////////////////////////////////////// 18 | 19 | void WhatCompileDefinitions() 20 | { 21 | std::cout << "Compiler flags:\n" 22 | 23 | #ifdef INTELQS_HAS_MPI 24 | << " INTELQS_HAS_MPI --> [YES]\n" 25 | #else 26 | << " INTELQS_HAS_MPI --> [ NO]\n" 27 | #endif 28 | 29 | #ifdef USE_MKL 30 | << " USE_MKL --> [YES]\n" 31 | #else 32 | << " USE_MKL --> [ NO]\n" 33 | #endif 34 | 35 | #ifdef _OPENMP 36 | << " _OPENMP --> [YES]\n" 37 | #else 38 | << " _OPENMP --> [ NO]\n" 39 | #endif 40 | 41 | #ifdef __INTEL_COMPILER 42 | << " __INTEL_COMPILER --> [YES]\n" 43 | #else 44 | << " __INTEL_COMPILER --> [ NO]\n" 45 | #endif 46 | 47 | #ifdef __ICC 48 | << " __ICC --> [YES]\n" 49 | #else 50 | << " __ICC --> [ NO]\n" 51 | #endif 52 | 53 | #ifdef USE_MM_MALLOC 54 | << " USE_MM_MALLOC --> [YES]\n" 55 | #else 56 | << " USE_MM_MALLOC --> [ NO]\n" 57 | #endif 58 | 59 | #ifdef STANDALONE 60 | << " STANDALONE --> [YES]\n" 61 | #else 62 | << " STANDALONE --> [ NO]\n" 63 | #endif 64 | 65 | #ifdef NDEBUG 66 | << " NDEBUG --> [YES]\n" 67 | #else 68 | << " NDEBUG --> [ NO]\n" 69 | #endif 70 | 71 | #ifdef __ONLY_NORMALIZED_STATES 72 | << " __ONLY_NORMALIZED_STATES --> [YES]\n"; 73 | #else 74 | << " __ONLY_NORMALIZED_STATES --> [ NO]\n"; 75 | #endif 76 | } 77 | 78 | ///////////////////////////////////////////////////////////////////////////////////////// 79 | 80 | } // close namespace iqs 81 | -------------------------------------------------------------------------------- /tutorials/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | add_executable(get_started_with_IQS.exe get_started_with_IQS.cpp) 2 | target_link_libraries(get_started_with_IQS.exe PRIVATE iqs) 3 | 4 | add_executable(get_started_with_noisy_IQS.exe get_started_with_noisy_IQS.cpp) 5 | target_link_libraries(get_started_with_noisy_IQS.exe iqs) 6 | 7 | set_target_properties( get_started_with_IQS.exe 8 | get_started_with_noisy_IQS.exe 9 | PROPERTIES 10 | RUNTIME_OUTPUT_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}/bin" 11 | ) 12 | -------------------------------------------------------------------------------- /unit_test/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | include_directories(../include) 2 | 3 | # Build the suite of unit-tests for the project. 4 | # Approach suggested in: 5 | # https://github.com/google/googletest/blob/master/googletest/README.md 6 | 7 | # Download and unpack googletest at configure time. 8 | configure_file(../cmake/gtest.cmake.in googletest-download/CMakeLists.txt) 9 | execute_process(COMMAND ${CMAKE_COMMAND} -G "${CMAKE_GENERATOR}" . 10 | RESULT_VARIABLE result 11 | WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/googletest-download ) 12 | if(result) 13 | message(FATAL_ERROR "CMake step for googletest failed: ${result}") 14 | endif() 15 | execute_process(COMMAND ${CMAKE_COMMAND} --build . 16 | RESULT_VARIABLE result 17 | WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/googletest-download ) 18 | if(result) 19 | message(FATAL_ERROR "Build step for googletest failed: ${result}") 20 | endif() 21 | 22 | # Prevent overriding the parent project's compiler/linker settings on Windows. 23 | set(gtest_force_shared_crt ON CACHE BOOL "" FORCE) 24 | 25 | # Add googletest directly to our build. This defines the gtest and gtest_main targets. 26 | add_subdirectory(${CMAKE_CURRENT_BINARY_DIR}/googletest-src 27 | ${CMAKE_CURRENT_BINARY_DIR}/googletest-build 28 | EXCLUDE_FROM_ALL) 29 | 30 | ################################################################################ 31 | 32 | # Link against gtest or gtest_main as needed. 33 | add_executable(utest suite_of_tests.cpp 34 | ../src/qaoa_features.cpp) 35 | target_include_directories(utest PRIVATE include) 36 | target_link_libraries(utest PRIVATE iqs gtest_main) 37 | 38 | add_executable(mpi_env_test.exe mpi_env_test.cpp 39 | ../src/mpi_env.cpp 40 | ../src/mpi_exception.cpp) 41 | target_link_libraries(mpi_env_test.exe iqs) 42 | 43 | add_executable(mpi_speedup_test.exe mpi_speedup_test.cpp 44 | ../src/mpi_env.cpp 45 | ../src/mpi_exception.cpp) 46 | target_link_libraries(mpi_speedup_test.exe iqs) 47 | 48 | add_executable(openmp_test.exe openmp_test.cpp) 49 | 50 | ################################################################################ 51 | 52 | set_target_properties( utest 53 | mpi_env_test.exe 54 | mpi_speedup_test.exe 55 | openmp_test.exe 56 | PROPERTIES 57 | RUNTIME_OUTPUT_DIRECTORY "${PROJECT_BINARY_DIR}/bin" 58 | ) 59 | 60 | ################################################################################ 61 | -------------------------------------------------------------------------------- /unit_test/import_iqs.py: -------------------------------------------------------------------------------- 1 | # Python script to test the successful import of the full stack library 2 | 3 | import sys 4 | sys.path.insert(0, "../build/lib/") 5 | import intelqs_py as iqs 6 | 7 | iqs.EnvInit() 8 | rank = iqs.MPIEnvironment.GetRank() 9 | 10 | print("Creation of a 2-qubit state at rank {}",format(rank)); 11 | 12 | psi = iqs.QubitRegister(2, "base", 0, 0); 13 | 14 | print("The IQS library was successfully imported and initialized.") 15 | 16 | iqs.EnvFinalize() 17 | -------------------------------------------------------------------------------- /unit_test/include/compiler_flags_test.hpp: -------------------------------------------------------------------------------- 1 | #ifndef COMPILER_FLAG_TEST_HPP 2 | #define COMPILER_FLAG_TEST_HPP 3 | 4 | ////////////////////////////////////////////////////////////////////////////// 5 | // Test fixture class: compiler flags 6 | ////////////////////////////////////////////////////////////////////////////// 7 | 8 | class CompileFlagTest : public ::testing::Test 9 | { 10 | protected: 11 | 12 | CompileFlagTest() 13 | { } 14 | 15 | void SetUp() override 16 | { 17 | // All tests are skipped if the rank is dummy. 18 | if (iqs::mpi::Environment::IsUsefulRank() == false) 19 | GTEST_SKIP(); 20 | } 21 | }; 22 | 23 | ////////////////////////////////////////////////////////////////////////////// 24 | // Test macros: 25 | 26 | TEST_F(CompileFlagTest, AllFlags) 27 | { 28 | if (iqs::mpi::Environment::GetPoolRank() == 0) 29 | { 30 | std::cout << " |----------------------------|----------|\n" 31 | << " | Compiler Flag | defined? |\n" 32 | << " |----------------------------|----------|\n"; 33 | #ifdef INTELQS_HAS_MPI 34 | std::cout << " | INTELQS_HAS_MPI | X |\n"; 35 | #else 36 | std::cout << " | INTELQS_HAS_MPI | |\n"; 37 | #endif 38 | // 39 | #ifdef IQS_WITH_NOISE 40 | std::cout << " | IQS_WITH_NOISE | X |\n"; 41 | #else 42 | std::cout << " | IQS_WITH_NOISE | |\n"; 43 | #endif 44 | // 45 | #ifdef USE_MKL 46 | std::cout << " | USE_MKL | X |\n"; 47 | #else 48 | std::cout << " | USE_MKL | |\n"; 49 | #endif 50 | // 51 | #ifdef _OPENMP 52 | std::cout << " | _OPENMP | X |\n"; 53 | #else 54 | std::cout << " | _OPENMP | |\n"; 55 | #endif 56 | // 57 | #ifdef __INTEL_COMPILER 58 | std::cout << " | __INTEL_COMPILER | X |\n"; 59 | #else 60 | std::cout << " | __INTEL_COMPILER | |\n"; 61 | #endif 62 | // 63 | #ifdef __ICC 64 | std::cout << " | __ICC | X |\n"; 65 | #else 66 | std::cout << " | __ICC | |\n"; 67 | #endif 68 | // 69 | #ifdef USE_MM_MALLOC 70 | std::cout << " | USE_MM_MALLOC | X |\n"; 71 | #else 72 | std::cout << " | USE_MM_MALLOC | |\n"; 73 | #endif 74 | // 75 | #ifdef STANDALONE 76 | std::cout << " | STANDALONE | X |\n"; 77 | #else 78 | std::cout << " | STANDALONE | |\n"; 79 | #endif 80 | // 81 | #ifdef NDEBUG 82 | std::cout << " | NDEBUG | X |\n"; 83 | #else 84 | std::cout << " | NDEBUG | |\n"; 85 | #endif 86 | // 87 | #ifdef __ONLY_NORMALIZED_STATES__ 88 | std::cout << " | __ONLY_NORMALIZED_STATES__ | X |\n"; 89 | #else 90 | std::cout << " | __ONLY_NORMALIZED_STATES__ | |\n"; 91 | #endif 92 | std::cout << " |----------------------------|----------|\n"; 93 | } 94 | iqs::mpi::PoolBarrier(); 95 | } 96 | 97 | ////////////////////////////////////////////////////////////////////////////// 98 | 99 | #endif // header guard COMPILER_FLAG_TEST_HPP 100 | -------------------------------------------------------------------------------- /unit_test/include/conversion_test.hpp: -------------------------------------------------------------------------------- 1 | #ifndef CONVERSION_TEST_HPP 2 | #define CONVERSION_TEST_HPP 3 | 4 | #include "../../include/conversion.hpp" 5 | 6 | #include 7 | 8 | ////////////////////////////////////////////////////////////////////////////// 9 | // Test fixture class: compiler flags 10 | ////////////////////////////////////////////////////////////////////////////// 11 | 12 | class ConversionTest : public ::testing::Test 13 | { 14 | protected: 15 | 16 | ConversionTest() 17 | { } 18 | 19 | void SetUp() override 20 | { 21 | // All tests are skipped if the rank is dummy. 22 | if (iqs::mpi::Environment::IsUsefulRank() == false) 23 | GTEST_SKIP(); 24 | } 25 | }; 26 | 27 | ////////////////////////////////////////////////////////////////////////////// 28 | // Test macros: 29 | 30 | TEST_F(ConversionTest, BasicUse) 31 | { 32 | ASSERT_TRUE(iqs::toString(1) =="1"); 33 | ASSERT_TRUE(iqs::toString('a')=="a"); 34 | int var = 25; 35 | ASSERT_TRUE(iqs::toString(var)=="25"); 36 | std::string s = "I have 2 apples"; 37 | ASSERT_EQ(iqs::toString(s), s); 38 | } 39 | 40 | ////////////////////////////////////////////////////////////////////////////// 41 | 42 | #endif // header guard CONVERSION_TEST_HPP 43 | -------------------------------------------------------------------------------- /unit_test/include/measure_test.hpp: -------------------------------------------------------------------------------- 1 | #ifndef MEASURE_TEST_HPP 2 | #define MEASURE_TEST_HPP 3 | 4 | #include 5 | 6 | #include "../../include/qureg.hpp" 7 | 8 | ////////////////////////////////////////////////////////////////////////////// 9 | // Test fixture class. 10 | 11 | class MeasureTest : public ::testing::Test 12 | { 13 | protected: 14 | 15 | MeasureTest() 16 | { } 17 | 18 | // just after the 'constructor' 19 | void SetUp() override 20 | { 21 | // All tests are skipped if the rank is dummy. 22 | if (iqs::mpi::Environment::IsUsefulRank() == false) 23 | GTEST_SKIP(); 24 | 25 | // All tests are skipped if the 4-qubit state is distributed in more than 8 ranks. 26 | if (iqs::mpi::Environment::GetStateSize() > 8) 27 | GTEST_SKIP() << "INFO: small state distributed among too many ranks."; 28 | } 29 | 30 | const std::size_t num_qubits_ = 4; 31 | double accepted_error_ = 1e-14; 32 | }; 33 | 34 | ////////////////////////////////////////////////////////////////////////////// 35 | // Test macros: 36 | 37 | TEST_F(MeasureTest, GetProbability) 38 | { 39 | iqs::QubitRegister psi (num_qubits_,"base",10); 40 | psi.ApplyHadamard(2); 41 | psi.ApplyHadamard(3); 42 | // |psi> = |01+-> = H2.H3|"2+8"> 43 | ASSERT_DOUBLE_EQ(psi.GetProbability(0), 0.); 44 | ASSERT_DOUBLE_EQ(psi.GetProbability(1), 1.); 45 | ASSERT_DOUBLE_EQ(psi.GetProbability(2), 0.5); 46 | ASSERT_DOUBLE_EQ(psi.GetProbability(3), 0.5); 47 | 48 | psi.Initialize("base",0); 49 | psi.ApplyRotationX(0,-M_PI/2.); 50 | // |psi> = |y+>|000> 51 | ASSERT_DOUBLE_EQ(psi.GetProbability(0), 0.5); 52 | 53 | psi.Initialize("base",0); 54 | psi.ApplyRotationX(0, M_PI/2.); 55 | // |psi> = |y->|000> 56 | ASSERT_DOUBLE_EQ(psi.GetProbability(0), 0.5); 57 | } 58 | 59 | ////////////////////////////////////////////////////////////////////////////// 60 | 61 | #endif // header guard MEASURE_TEST_HPP 62 | -------------------------------------------------------------------------------- /unit_test/include/one_qubit_register_test.hpp: -------------------------------------------------------------------------------- 1 | #ifndef ONE_QUBIT_REGISTER_TEST_HPP 2 | #define ONE_QUBIT_REGISTER_TEST_HPP 3 | 4 | #include "../../include/qureg.hpp" 5 | 6 | ////////////////////////////////////////////////////////////////////////////// 7 | // Test fixture class. 8 | 9 | class OneQubitRegisterTest : public ::testing::Test 10 | { 11 | protected: 12 | 13 | OneQubitRegisterTest() 14 | { } 15 | 16 | // just after the 'constructor' 17 | void SetUp() override 18 | { 19 | // All tests are skipped if the rank is dummy. 20 | if (iqs::mpi::Environment::IsUsefulRank() == false) 21 | GTEST_SKIP(); 22 | 23 | // All tests are skipped if the 1-qubit state is distributed in more than 1 rank. 24 | // In fact the MPI version needs to allocate half-the-local-storage for communication. 25 | // If the local storage is a single amplitude, this cannot be further divided. 26 | if (iqs::mpi::Environment::GetStateSize() > 1) 27 | GTEST_SKIP(); 28 | } 29 | 30 | // just before the 'destructor' 31 | // void TearDown() override {} 32 | 33 | const std::size_t num_qubits_ = 1; 34 | double accepted_error_ = 1e-15; 35 | }; 36 | 37 | ////////////////////////////////////////////////////////////////////////////// 38 | // Test macros: 39 | 40 | TEST_F(OneQubitRegisterTest, InitializeInComputationalBasis) 41 | { 42 | ComplexDP amplitude; 43 | 44 | iqs::QubitRegister psi_0 (num_qubits_,"base",0); 45 | // |psi_0> = |0> 46 | amplitude = psi_0.GetGlobalAmplitude(0); 47 | ASSERT_DOUBLE_EQ(amplitude.real(), 1.); 48 | ASSERT_DOUBLE_EQ(amplitude.imag(), 0.); 49 | amplitude = psi_0.GetGlobalAmplitude(1); 50 | ASSERT_DOUBLE_EQ(amplitude.real(), 0.); 51 | ASSERT_DOUBLE_EQ(amplitude.imag(), 0.); 52 | 53 | iqs::QubitRegister psi_1 (num_qubits_,"base",1); 54 | // |psi_1> = |1> 55 | amplitude = psi_1.GetGlobalAmplitude(0); 56 | ASSERT_DOUBLE_EQ(amplitude.real(), 0.); 57 | ASSERT_DOUBLE_EQ(amplitude.imag(), 0.); 58 | amplitude = psi_1.GetGlobalAmplitude(1); 59 | ASSERT_DOUBLE_EQ(amplitude.real(), 1.); 60 | ASSERT_DOUBLE_EQ(amplitude.imag(), 0.); 61 | } 62 | 63 | // FIXME until the RNG issues are solved. 64 | #if 0 65 | TEST_F(OneQubitRegisterTest, InitializeRandomly) 66 | { 67 | psi_0_.Initialize("rand",1321); 68 | psi_1_.Initialize("rand",1157); 69 | 70 | ASSERT_LE( std::abs(psi_0_.ComputeNorm()-1) , accepted_error_ ); 71 | ASSERT_LE( std::abs(psi_1_.ComputeNorm()-1) , accepted_error_ ); 72 | } 73 | #endif 74 | 75 | TEST_F(OneQubitRegisterTest, GetCorrectProbability) 76 | { 77 | iqs::QubitRegister psi_0 (num_qubits_,"base",0); 78 | ASSERT_DOUBLE_EQ(psi_0.GetProbability(0), 0.); 79 | psi_0.ApplyHadamard(0); 80 | // |psi_0> = |+> 81 | ASSERT_LE( std::abs(psi_0.GetProbability(0)-0.5) , accepted_error_ ); 82 | 83 | iqs::QubitRegister psi_1 (num_qubits_,"base",1); 84 | ASSERT_DOUBLE_EQ(psi_1.GetProbability(0), 1.); 85 | psi_1.ApplyPauliX(0); 86 | // |psi_1> = |0> 87 | ASSERT_DOUBLE_EQ(psi_1.GetProbability(0), 0.); 88 | // |psi_1> = exp(-i theta X/2)|0> = cos(theta/2) |0> -i sin(theta/2)|1> 89 | double theta = 1.1; 90 | psi_1.ApplyRotationX(0,theta); 91 | ASSERT_LE( std::abs(psi_1.GetProbability(0)-std::sin(theta/2)*std::sin(theta/2)), 92 | accepted_error_ ); 93 | } 94 | 95 | ////////////////////////////////////////////////////////////////////////////// 96 | 97 | #endif // header guard ONE_QUBIT_REGISTER_TEST_HPP 98 | -------------------------------------------------------------------------------- /unit_test/mpi_speedup_test.cpp: -------------------------------------------------------------------------------- 1 | /// @file mpi_speedup_test.cpp 2 | /// 3 | /// Tests for the speedup of the MPI environment of IQS. 4 | 5 | #include 6 | #include 7 | #include 8 | #include 9 | 10 | #include "../include/mpi_env.hpp" 11 | #include "../include/qureg.hpp" 12 | 13 | //#define MPI_WITHOUT_IQS_ENV 14 | 15 | ///////////////////////////////////////////////////////////////////////////////////////// 16 | 17 | int main(int argc, char** argv) 18 | { 19 | int pool_rank; 20 | int pool_size; 21 | #ifdef MPI_WITHOUT_IQS_ENV 22 | MPI_Init(NULL, NULL); 23 | MPI_Comm_size(MPI_COMM_WORLD, &pool_size); 24 | MPI_Comm_rank(MPI_COMM_WORLD, &pool_rank); 25 | if (!pool_rank) 26 | std::cout << "\n-- Without using the MPI environment of IQS --\n"; 27 | #else 28 | // Initialize the MPI environment (verbose mode), if MPI exists. 29 | iqs::mpi::Environment env(argc, argv, true); 30 | // These should work even without MPI. 31 | pool_rank = iqs::mpi::Environment::GetPoolRank(); 32 | pool_size = iqs::mpi::Environment::GetPoolSize(); 33 | if (!pool_rank) 34 | std::cout << "\n-- Using the MPI environment of IQS --\n"; 35 | #endif 36 | 37 | std::size_t power_of_2 = 32; 38 | std::size_t global_value = 1L << power_of_2; 39 | std::size_t local_value = global_value/std::size_t(pool_size); 40 | 41 | if (!pool_rank) 42 | std::cout << "\nQuick test of MPI parallel speedup:\n" 43 | << "Count to 2^" << std::log2(global_value) 44 | << " in groups of 2^" << std::log2(local_value) << "\n"; 45 | 46 | struct timeval time; 47 | double start, end; 48 | std::size_t dumb_counter=0; 49 | 50 | // Start the timer. 51 | gettimeofday(&time, (struct timezone*)0); 52 | start = time.tv_sec + time.tv_usec * 1.0e-6; 53 | 54 | for (std::size_t j=0; j, " 76 | << "and perform a single 1-qubit-gate per qubit.\n"; 77 | 78 | iqs::mpi::StateBarrier(); 79 | 80 | iqs::QubitRegister psi(num_qubits, "base", 0); 81 | 82 | iqs::mpi::StateBarrier(); 83 | if (!pool_rank) std::cout << "\nInitialization of the qubit register.\n"; 84 | iqs::mpi::StateBarrier(); 85 | 86 | psi.TurnOnSpecialize(); 87 | psi.EnableStatistics(); 88 | for(int qubit = 0; qubit < num_qubits; qubit++) 89 | psi.ApplyHadamard(qubit); 90 | psi.GetStatistics(); 91 | psi.DisableStatistics(); 92 | #endif 93 | #else 94 | MPI_Finalize(); 95 | #endif 96 | 97 | return 0; 98 | } 99 | -------------------------------------------------------------------------------- /unit_test/openmp_test.cpp: -------------------------------------------------------------------------------- 1 | /// @file openmp_test.cpp 2 | /// 3 | /// Tests for the OpenMP settings. 4 | 5 | #include 6 | #include 7 | #include // for constant M_PI 8 | #include 9 | #include 10 | #include 11 | 12 | #ifdef _OPENMP 13 | #include 14 | #endif 15 | 16 | ///////////////////////////////////////////////////////////////////////////////////////// 17 | 18 | void PrintHelloWorld(int thread_id) 19 | { 20 | printf("Hello World from thread [%d]\n", thread_id); 21 | } 22 | 23 | ///////////////////////////////////////////////////////////////////////////////////////// 24 | 25 | int main(int argc, char **argv) 26 | { 27 | int num_threads = 1; 28 | #ifdef _OPENMP 29 | num_threads = omp_get_num_threads(); 30 | 31 | ////////////////////////////////////////////////////////////////////////////// 32 | // First of all, print to screen from each and every thread (in random order). 33 | #pragma omp parallel 34 | { 35 | int id = omp_get_thread_num(); 36 | PrintHelloWorld(id); 37 | } 38 | 39 | ////////////////////////////////////////////////////////////////////////////// 40 | // Second, we want to compute the delta_x of an integral. 41 | double integral_start = 0.0, 42 | integral_end = 1.0; 43 | unsigned long num_intervals = 4000000000; 44 | 45 | // Compute delta_x of the integral. 46 | double delta_x = (integral_end - integral_start) / num_intervals; 47 | double pi = 0.0; 48 | 49 | // Start performance check. 50 | auto start = std::chrono::steady_clock::now(); 51 | double sum = 0.0; 52 | 53 | #pragma omp parallel 54 | { 55 | int id = omp_get_thread_num(); 56 | printf("Thread [%d]\n", id); 57 | // Compute the Riemann sum for the approximate integral. 58 | #pragma omp for reduction(+:sum) 59 | for(unsigned long i=0; i(diff).count()); 75 | #else 76 | printf("This program was compiled for execution without OpenMP.\n"); 77 | #endif 78 | 79 | return 0; 80 | } 81 | 82 | ///////////////////////////////////////////////////////////////////////////////////////// 83 | -------------------------------------------------------------------------------- /util/BigMPI/.gitignore: -------------------------------------------------------------------------------- 1 | *.a 2 | *.o 3 | *.x 4 | *~ 5 | Makefile.in 6 | aclocal.m4 7 | autom4te.cache/ 8 | configure 9 | src/bigmpiconf.h.in 10 | -------------------------------------------------------------------------------- /util/BigMPI/.travis.yml: -------------------------------------------------------------------------------- 1 | sudo: false 2 | language: c 3 | os: 4 | - linux 5 | - osx 6 | compiler: 7 | - gcc 8 | - clang 9 | matrix: 10 | allow_failures: 11 | - env: MPI_IMPL=openmpi 12 | env: 13 | - MPI_IMPL=mpich 14 | - MPI_IMPL=openmpi 15 | before_install: 16 | - export TRAVIS_ROOT=$HOME/travis 17 | - mkdir -p $TRAVIS_ROOT 18 | - sh ./travis/install-autotools.sh $TRAVIS_ROOT 19 | - export PATH=$TRAVIS_ROOT/bin:$PATH 20 | install: 21 | - sh ./travis/install-mpi.sh $TRAVIS_ROOT $MPI_IMPL 22 | script: 23 | - sh ./travis/build-run.sh $TRAVIS_ROOT $MPI_IMPL 24 | after_failure: 25 | - find . -name config.log -exec grep -L "configure: exit 0" {} ";" | xargs cat 26 | -------------------------------------------------------------------------------- /util/BigMPI/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 2.6.4 FATAL_ERROR) 2 | 3 | set(PACKAGE_NAME BigMPI) 4 | find_package(MPI) 5 | 6 | # generic function to add user-configurable options. 7 | function(add_config_option name help_message default) 8 | if(NOT DEFINED ${name}) 9 | set(${name} "${default}") 10 | set(${name} "${default}" CACHE STRING "${help_message}" FORCE) 11 | endif() 12 | 13 | set(OPTIONS_LIST "${OPTIONS_LIST}\n\n * ${name}=\"${${name}}\",\n default=\"${default}\"\n ${help_message}" PARENT_SCOPE) 14 | endfunction(add_config_option) 15 | 16 | add_config_option(BIGMPI_MAX_INT "Determines which element count BigMPI will assume to be safe." 1000000) 17 | add_config_option(BIGMPI_VCOLLS "Selects which flavor should be used for the implementation of vector collectives (valid options: RMA, P2P, NBHD_ALLTOALLW)" RMA) 18 | add_config_option(LIB_LINKAGE_TYPE "Controls which type of library to build. Suggested: SHARED on Linux (creates a shared object \"bigmpi.so\"), STATIC should work for builds on Cray and Windows." "SHARED" false) 19 | add_config_option(TEST_COVERAGE_VERBOSITY "Sets the verbosity of the test coverage reoprt (0 = off, 1 = summary, 2 = verbose listing)" 1) 20 | 21 | message("-- The following options have been configured:") 22 | message(${OPTIONS_LIST}) 23 | message("") 24 | 25 | if (BIGMPI_MAX_INT) 26 | add_definitions(-DBIGMPI_MAX_INT=${BIGMPI_MAX_INT}) 27 | endif() 28 | 29 | add_definitions(-DBIGMPI_VCOLLS_${BIGMPI_VCOLLS}) 30 | 31 | set(CMAKE_C_FLAGS "-std=c99") 32 | 33 | include_directories("${CMAKE_CURRENT_SOURCE_DIR}/include") 34 | add_definitions(${MPI_COMPILE_FLAGS}) 35 | include_directories(${MPI_INCLUDE_PATH}) 36 | 37 | add_custom_target(test echo "Tests passed.") 38 | 39 | add_subdirectory(src) 40 | add_subdirectory(test) 41 | 42 | 43 | # compute test coverage: 44 | 45 | # will search all files matching WILDCARD for occurences of MPIX_Foo() 46 | function(list_mpix_functions WILDCARD RESULT) 47 | file(GLOB files "${WILDCARD}") 48 | set(akku ) 49 | 50 | foreach(file ${files}) 51 | file(READ "${file}" file_content) 52 | string(REPLACE ";" "" result1 "${file_content}") 53 | string(REGEX MATCH "MPIX_[A-Za-z0-9_]+" matches "${result1}") 54 | 55 | if(matches) 56 | set(len_old "A") 57 | set(len_new "B") 58 | 59 | while(NOT (len_old EQUAL len_new)) 60 | string(REGEX REPLACE "(.*)(MPIX_[A-Za-z0-9_]+)(.+)" "\\2;\\1 " result2 "${result1}") 61 | set(result1 "${result2}") 62 | 63 | set(len_old "${len_new}") 64 | string(LENGTH "${result1}" len_new ) 65 | endwhile() 66 | 67 | list(APPEND akku "${result1}") 68 | endif() 69 | endforeach() 70 | 71 | list(REMOVE_DUPLICATES akku) 72 | list(SORT akku) 73 | set("${RESULT}" "${akku}" PARENT_SCOPE) 74 | endfunction() 75 | 76 | list_mpix_functions("src/bigmpi.h" all_mpix_functions) 77 | list_mpix_functions("test/*.c" tested_mpix_functions) 78 | list(LENGTH all_mpix_functions num_all_mpix_functions) 79 | list(LENGTH tested_mpix_functions num_tested_mpix_functions) 80 | 81 | set(message_level STATUS) 82 | if(num_all_mpix_functions GREATER num_tested_mpix_functions) 83 | set(message_level WARNING) 84 | endif() 85 | 86 | if(TEST_COVERAGE_VERBOSITY GREATER 0) 87 | message("${message_level}" "Test coverage: ${num_tested_mpix_functions}/${num_all_mpix_functions} functions.") 88 | endif() 89 | 90 | if(TEST_COVERAGE_VERBOSITY STREQUAL 2) 91 | foreach(func ${all_mpix_functions}) 92 | list(FIND tested_mpix_functions "${func}" found) 93 | 94 | if(found EQUAL -1) 95 | message(STATUS "${func}() UNTESTED") 96 | endif() 97 | endforeach() 98 | endif() 99 | -------------------------------------------------------------------------------- /util/BigMPI/INSTALL.md: -------------------------------------------------------------------------------- 1 | # Setup 2 | 3 | ## Autotools 4 | ``` 5 | cd $(BIGMPI_SOURCE_DIR) && ./autogen.sh 6 | cd $(BIGMPI_BUILD_DIR) && $(BIGMPI_SOURCE_DIR)/configure CC=mpicc 7 | ``` 8 | (add `--prefix` if you want to `make install` somewhere) 9 | 10 | ## CMake 11 | ``` 12 | cmake $(BIGMPI_SOURCE_DIR) -DCMAKE_C_COMPILER=mpicc 13 | ``` 14 | 15 | # Build 16 | 17 | ``` 18 | make 19 | make check 20 | ``` 21 | -------------------------------------------------------------------------------- /util/BigMPI/LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2013, 2014 Argonne National Laboratory 4 | Copyright (c) 2014 Friedrich-Alexander-Universitaet Erlangen-Nuernberg 5 | Copyright (c) 2014 Intel Corporation 6 | 7 | Permission is hereby granted, free of charge, to any person obtaining a copy 8 | of this software and associated documentation files (the "Software"), to deal 9 | in the Software without restriction, including without limitation the rights 10 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 11 | copies of the Software, and to permit persons to whom the Software is 12 | furnished to do so, subject to the following conditions: 13 | 14 | The above copyright notice and this permission notice shall be included in 15 | all copies or substantial portions of the Software. 16 | 17 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 18 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 19 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 20 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 21 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 22 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 23 | THE SOFTWARE. 24 | -------------------------------------------------------------------------------- /util/BigMPI/Mac-MPI-Accelerate.cmake: -------------------------------------------------------------------------------- 1 | # MPI wrappers assumed to be in path 2 | set(COMPILER_DIR ) 3 | set(CMAKE_C_COMPILER ${COMPILER_DIR}mpicc) 4 | set(CMAKE_CXX_COMPILER ${COMPILER_DIR}mpicxx) 5 | set(CMAKE_Fortran_COMPILER ${COMPILER_DIR}mpif90) 6 | 7 | set(MPI_C_COMPILER ${CMAKE_C_COMPILER}) 8 | set(MPI_CXX_COMPILER ${CMAKE_CXX_COMPILER}) 9 | set(MPI_Fortran_COMPILER ${CMAKE_Fortran_COMPILER}) 10 | 11 | if(CMAKE_BUILD_TYPE MATCHES PureDebug OR 12 | CMAKE_BUILD_TYPE MATCHES HybridDebug) 13 | set(C_FLAGS "-g") 14 | set(CXX_FLAGS "-g") 15 | else() 16 | set(C_FLAGS "-O3") 17 | set(CXX_FLAGS "-O3") 18 | endif() 19 | 20 | set(OpenMP_CXX_FLAGS "-fopenmp") 21 | 22 | set(MATH_LIBS "-framework Accelerate") 23 | set(CMAKE_FIND_LIBRARY_SUFFIXES .a ${CMAKE_FIND_LIBRARY_SUFFIXES}) 24 | set(BUILD_SHARED_LIBS ON) 25 | set(CMAKE_EXE_LINKER_FLAGS "") 26 | -------------------------------------------------------------------------------- /util/BigMPI/Makefile.am: -------------------------------------------------------------------------------- 1 | # 2 | # Copyright (C) 2014. See LICENSE in top-level directory. 3 | # 4 | 5 | ACLOCAL_AMFLAGS = -I m4 6 | AM_CPPFLAGS = -I$(top_srcdir)/src 7 | 8 | lib_LTLIBRARIES = libbigmpi.la 9 | 10 | noinst_LTLIBRARIES = libbigmpii.la 11 | 12 | libbigmpi_la_SOURCES = src/collectives_x.c \ 13 | src/vcollectives_x.c \ 14 | src/neighborhood_collectives_x.c \ 15 | src/reductions_x.c \ 16 | src/rma_x.c \ 17 | src/sendrecv_x.c \ 18 | src/fileio_x.c \ 19 | src/type_contiguous_x.c \ 20 | src/type_hindexed_x.c \ 21 | src/utils.c 22 | 23 | libbigmpi_la_LDFLAGS = -version-info $(libbigmpi_abi_version) 24 | 25 | libbigmpii_la_SOURCES = $(libbigmpi_la_SOURCES) 26 | libbigmpii_la_LDFLAGS = $(libbigmpi_abi_version) 27 | 28 | include_HEADERS = src/bigmpi.h src/bigmpi_impl.h 29 | 30 | bin_PROGRAMS = 31 | check_PROGRAMS = 32 | TESTS = 33 | XFAIL_TESTS = 34 | 35 | MPIEXEC = mpiexec -n 2 36 | TESTS_ENVIRONMENT = $(MPIEXEC) 37 | 38 | include test/Makefile.mk 39 | 40 | .PHONY: checkprogs 41 | checkprogs: $(check_PROGRAMS) 42 | -------------------------------------------------------------------------------- /util/BigMPI/VERSION: -------------------------------------------------------------------------------- 1 | # Version 2 | BIGMPI_VERSION=0.1 3 | 4 | # For libtool ABI versioning rules see: 5 | # http://www.nondot.org/sabre/Mirrored/libtool-2.1a/libtool_6.html#SEC36 6 | 7 | # 1. If the library source code has changed at all since the last 8 | # update, then increment revision (`c:r:a' becomes `c:r+1:a'). 9 | # 10 | # 2. If any interfaces have been added, removed, or changed since 11 | # the last update, increment current, and set revision to 0. 12 | # 13 | # 3. If any interfaces have been added since the last public 14 | # release, then increment age. 15 | # 16 | # 4. If any interfaces have been removed since the last public 17 | # release, then set age to 0. 18 | 19 | libbigmpi_abi_version=1:0:0 20 | -------------------------------------------------------------------------------- /util/BigMPI/autogen.sh: -------------------------------------------------------------------------------- 1 | #! /bin/sh 2 | autoreconf=${AUTORECONF:-autoreconf} 3 | $autoreconf ${autoreconf_args:-"-vif"} 4 | -------------------------------------------------------------------------------- /util/BigMPI/m4/aclocal_am.m4: -------------------------------------------------------------------------------- 1 | dnl AM_IGNORE is an extension that tells (a patched) automake not to 2 | dnl include the specified AC_SUBST variable in the Makefile.in that 3 | dnl automake generates. We don't use AC_DEFUN, since aclocal will 4 | dnl then complain that AM_IGNORE is a duplicate (if you are using the 5 | dnl patched automake/aclocal). 6 | m4_ifdef([AM_IGNORE],[],[m4_define([AM_IGNORE],[])]) 7 | -------------------------------------------------------------------------------- /util/BigMPI/m4/aclocal_bugfix.m4: -------------------------------------------------------------------------------- 1 | dnl This internal macro fails to work properly with OTHER internal macros. 2 | dnl Basically, if the prologue is [], then no message should be generated. 3 | dnl This macro is in autoconf 2.52 4 | m4_define([AC_LANG_PROGRAM(Fortran 77)], 5 | [m4_if([$1],[[[]]],,[m4_ifval([$1], 6 | [m4_warn([syntax], [$0: ignoring PROLOGUE: $1])])])dnl 7 | program main 8 | $2 9 | end]) 10 | 11 | 12 | dnl/*D 13 | dnl PAC_PROG_CHECK_INSTALL_WORKS - Check whether the install program in INSTALL 14 | dnl works. 15 | dnl 16 | dnl Synopsis: 17 | dnl PAC_PROG_CHECK_INSTALL_WORKS 18 | dnl 19 | dnl Output Effect: 20 | dnl Sets the variable 'INSTALL' to the value of 'ac_sh_install' if 21 | dnl a file cannot be installed into a local directory with the 'INSTALL' 22 | dnl program 23 | dnl 24 | dnl Notes: 25 | dnl The 'AC_PROG_INSTALL' scripts tries to avoid broken versions of 26 | dnl install by avoiding directories such as '/usr/sbin' where some 27 | dnl systems are known to have bad versions of 'install'. Unfortunately, 28 | dnl this is exactly the sort of test-on-name instead of test-on-capability 29 | dnl that 'autoconf' is meant to eliminate. The test in this script 30 | dnl is very simple but has been adequate for working around problems 31 | dnl on Solaris, where the '/usr/sbin/install' program (known by 32 | dnl autoconf to be bad because it is in /usr/sbin) is also reached by a 33 | dnl soft link through /bin, which autoconf believes is good. 34 | dnl 35 | dnl No variables are cached to ensure that we do not make a mistake in 36 | dnl our choice of install program. 37 | dnl 38 | dnl The Solaris configure requires the directory name to immediately 39 | dnl follow the '-c' argument, rather than the more common 40 | dnl.vb 41 | dnl args sourcefiles destination-dir 42 | dnl.ve 43 | dnl D*/ 44 | AC_DEFUN([PAC_PROG_CHECK_INSTALL_WORKS],[ 45 | if test -z "$INSTALL" ; then 46 | AC_MSG_RESULT([No install program available]) 47 | else 48 | # first make any "confdb/install-sh -c" into an absolute path 49 | # this is a hack, but it's still much cleaner than anything else I could 50 | # come up with (see tt#1007) [goodell@] 51 | AS_CASE(["$INSTALL"], 52 | [/*],[:], 53 | [*install-sh*],[INSTALL="$master_top_srcdir/$INSTALL"]) 54 | 55 | # Check that this install really works 56 | rm -f conftest 57 | echo "Test file" > conftest 58 | if test ! -d .conftest ; then mkdir .conftest ; fi 59 | AC_MSG_CHECKING([whether install works]) 60 | if $INSTALL conftest .conftest >/dev/null 2>&1 ; then 61 | installOk=yes 62 | else 63 | installOk=no 64 | fi 65 | rm -rf .conftest conftest 66 | AC_MSG_RESULT($installOk) 67 | if test "$installOk" = no ; then 68 | if test -n "$ac_install_sh" ; then 69 | INSTALL=$ac_install_sh 70 | else 71 | AC_MSG_ERROR([Unable to find working install]) 72 | fi 73 | fi 74 | fi 75 | ]) 76 | -------------------------------------------------------------------------------- /util/BigMPI/m4/aclocal_f77new.m4: -------------------------------------------------------------------------------- 1 | dnl /*D 2 | dnl PAC_F77_WORKS_WITH_CPP 3 | dnl 4 | dnl Checks if Fortran 77 compiler works with C preprocessor 5 | dnl 6 | dnl Most systems allow the Fortran compiler to process .F and .F90 files 7 | dnl using the C preprocessor. However, some systems either do not 8 | dnl allow this or have serious bugs (OSF Fortran compilers have a bug 9 | dnl that generates an error message from cpp). The following test 10 | dnl checks to see if .F works, and if not, whether "cpp -P -C" can be used 11 | dnl D*/ 12 | AC_DEFUN([PAC_F77_WORKS_WITH_CPP],[ 13 | AC_REQUIRE([AC_PROG_CPP]) 14 | AC_MSG_CHECKING([whether Fortran 77 compiler processes .F files with C preprocessor]) 15 | AC_LANG_PUSH([Fortran 77]) 16 | saved_f77_ext=${ac_ext} 17 | ac_ext="F" 18 | saved_FFLAGS="$FFLAGS" 19 | FFLAGS="$FFLAGS $CPPFLAGS" 20 | AC_LANG_CONFTEST([ 21 | AC_LANG_SOURCE([ 22 | program main 23 | #define ASIZE 10 24 | integer a(ASIZE) 25 | end 26 | ]) 27 | ]) 28 | AC_COMPILE_IFELSE([],[ 29 | pac_cv_f77_accepts_F=yes 30 | ifelse([$1],[],[],[$1=""]) 31 | ],[ 32 | pac_cv_f77_accepts_F=no 33 | ifelse([$1],[],[:],[$1="false"]) 34 | ]) 35 | # Restore Fortran 77's ac_ext but not FFLAGS 36 | ac_ext="$saved_f77_ext" 37 | 38 | if test "$pac_cv_f77_accepts_F" != "yes" ; then 39 | pac_cpp_f77="$ac_cpp -C -P conftest.F > conftest.$ac_ext" 40 | PAC_RUNLOG_IFELSE([$pac_cpp_f77],[ 41 | if test -s conftest.${ac_ext} ; then 42 | AC_COMPILE_IFELSE([],[ 43 | pac_cv_f77_accepts_F="no, use cpp" 44 | ifelse([$1],[],[],[$1="$CPP -C -P"]) 45 | ],[]) 46 | rm -f conftest.${ac_ext} 47 | fi 48 | ],[]) 49 | fi 50 | FFLAGS="$saved_FFLAGS" 51 | rm -f conftest.F 52 | AC_LANG_POP([Fortran 77]) 53 | AC_MSG_RESULT([$pac_cv_f77_accepts_F]) 54 | ]) 55 | -------------------------------------------------------------------------------- /util/BigMPI/m4/aclocal_libs.m4: -------------------------------------------------------------------------------- 1 | 2 | dnl PAC_SET_HEADER_LIB_PATH(with_option) 3 | dnl This macro looks for the --with-xxx=, --with-xxx-include and --with-xxx-lib= 4 | dnl options and sets the library and include paths. 5 | AC_DEFUN([PAC_SET_HEADER_LIB_PATH],[ 6 | AC_ARG_WITH($1, 7 | AC_HELP_STRING([--with-$1=path], 8 | [specify path where $1 include directory and lib directory can be found]), 9 | if test "${with_$1}" != "yes" -a "${with_$1}" != "no" ; then 10 | # is adding lib64 by default really the right thing to do? What if 11 | # we are on a 32-bit host that happens to have both lib dirs available? 12 | LDFLAGS="$LDFLAGS -L${with_$1}/lib64 -L${with_$1}/lib" 13 | CPPFLAGS="$CPPFLAGS -I${with_$1}/include" 14 | WRAPPER_CFLAGS="$WRAPPER_CFLAGS -I${with_$1}/include" 15 | fi, 16 | ) 17 | AC_ARG_WITH($1-include, 18 | AC_HELP_STRING([--with-$1-include=path], 19 | [specify path where $1 include directory can be found]), 20 | if test "${with_$1_include}" != "yes" -a "${with_$1_include}" != "no" ; then 21 | CPPFLAGS="$CPPFLAGS -I${with_$1_include}" 22 | WRAPPER_CFLAGS="$WRAPPER_CFLAGS -I${with_$1_include}" 23 | fi, 24 | ) 25 | AC_ARG_WITH($1-lib, 26 | AC_HELP_STRING([--with-$1-lib=path], 27 | [specify path where $1 lib directory can be found]), 28 | if test "${with_$1_lib}" != "yes" -a "${with_$1_lib}" != "no" ; then 29 | LDFLAGS="$LDFLAGS -L${with_$1_lib}" 30 | fi, 31 | ) 32 | ]) 33 | 34 | 35 | dnl PAC_CHECK_HEADER_LIB(with_option, header.h, libname, function, action-if-yes, action-if-no) 36 | dnl This macro checks for a header and lib. It is assumed that the 37 | dnl user can specify a path to the includes and libs using --with-xxx=. 38 | dnl The xxx is specified in the "with_option" parameter. 39 | AC_DEFUN([PAC_CHECK_HEADER_LIB],[ 40 | failure=no 41 | AC_CHECK_HEADER([$2],,failure=yes) 42 | AC_CHECK_LIB($3,$4,,failure=yes) 43 | if test "$failure" = "no" ; then 44 | $5 45 | else 46 | $6 47 | fi 48 | ]) 49 | 50 | dnl PAC_CHECK_HEADER_LIB_FATAL(with_option, header.h, libname, function) 51 | dnl Similar to PAC_CHECK_HEADER_LIB, but errors out on failure 52 | AC_DEFUN([PAC_CHECK_HEADER_LIB_FATAL],[ 53 | PAC_CHECK_HEADER_LIB($1,$2,$3,$4,success=yes,success=no) 54 | if test "$success" = "no" ; then 55 | AC_MSG_ERROR(['$2 or lib$3 library not found. Did you specify --with-$1= or --with-$1-include= or --with-$1-lib=?']) 56 | fi 57 | ]) 58 | -------------------------------------------------------------------------------- /util/BigMPI/m4/aclocal_runlog.m4: -------------------------------------------------------------------------------- 1 | dnl 2 | dnl PAC_RUN_LOG mimics _AC_RUN_LOG which is autoconf internal routine. 3 | dnl We also make sure PAC_RUN_LOG can be used in AS_IF, so the last 4 | dnl test command should have terminating ]), i.e. without newline before ]). 5 | dnl 6 | AC_DEFUN([PAC_RUNLOG],[ 7 | { AS_ECHO(["$as_me:$LINENO: $1"]) >&AS_MESSAGE_LOG_FD 8 | (eval $1) 2>&AS_MESSAGE_LOG_FD 9 | ac_status=$? 10 | AS_ECHO(["$as_me:$LINENO: \$? = $ac_status"]) >&AS_MESSAGE_LOG_FD 11 | test $ac_status = 0; }]) 12 | dnl 13 | dnl PAC_COMMAND_IFELSE is written to replace AC_TRY_EVAL with added logging 14 | dnl to config.log, i.e. AC_TRY_EVAL does not log anything to config.log. 15 | dnl If autoconf provides AC_COMMAND_IFELSE or AC_EVAL_IFELSE, 16 | dnl AC_COMMAND_IFELSE dnl should be replaced by the official autoconf macros. 17 | dnl 18 | dnl PAC_COMMAND_IFELSE(COMMMAND,[ACTION-IF-RUN-OK],[ACTION-IF-RUN-FAIL]) 19 | dnl 20 | AC_DEFUN([PAC_COMMAND_IFELSE],[ 21 | dnl Should use _AC_DO_TOKENS but use AC_RUN_LOG instead 22 | dnl because _AC_XX is autoconf's undocumented macro. 23 | AS_IF([PAC_RUNLOG([$1])],[ 24 | $2 25 | ],[ 26 | AS_ECHO(["$as_me: program exited with status $ac_status"]) >&AS_MESSAGE_LOG_FD 27 | m4_ifvaln([$3],[ 28 | (exit $ac_status) 29 | $3 30 | ]) 31 | ]) 32 | ]) 33 | dnl 34 | dnl 35 | dnl 36 | AC_DEFUN([PAC_EVAL_IFELSE],[ 37 | dnl Should use _AC_DO_TOKENS but use AC_RUN_LOG instead 38 | dnl because _AC_XX is autoconf's undocumented macro. 39 | AS_IF([PAC_RUNLOG([$$1])],[ 40 | $2 41 | ],[ 42 | AS_ECHO(["$as_me: program exited with status $ac_status"]) >&AS_MESSAGE_LOG_FD 43 | m4_ifvaln([$3],[ 44 | (exit $ac_status) 45 | $3 46 | ]) 47 | ]) 48 | ]) 49 | dnl 50 | dnl 51 | dnl 52 | AC_DEFUN([PAC_RUNLOG_IFELSE],[ 53 | dnl pac_TESTLOG is the internal temporary logfile for this macro. 54 | pac_TESTLOG="pac_test.log" 55 | rm -f $pac_TESTLOG 56 | PAC_COMMAND_IFELSE([$1 > $pac_TESTLOG],[ 57 | ifelse([$2],[],[],[$2]) 58 | ],[ 59 | AS_ECHO(["*** $1 :"]) >&AS_MESSAGE_LOG_FD 60 | cat $pac_TESTLOG >&AS_MESSAGE_LOG_FD 61 | ifelse([$3],[],[],[$3]) 62 | ]) 63 | rm -f $pac_TESTLOG 64 | ]) 65 | -------------------------------------------------------------------------------- /util/BigMPI/m4/ax_tls.m4: -------------------------------------------------------------------------------- 1 | # =========================================================================== 2 | # http://www.nongnu.org/autoconf-archive/ax_tls.html 3 | # =========================================================================== 4 | # 5 | # SYNOPSIS 6 | # 7 | # AX_TLS 8 | # 9 | # DESCRIPTION 10 | # 11 | # Provides a test for the compiler support of thread local storage (TLS) 12 | # extensions. Defines TLS if it is found. Currently only knows about GCC 13 | # and MSVC. I think SunPro uses the same as GCC, and Borland apparently 14 | # supports either. 15 | # 16 | # LICENSE 17 | # 18 | # Copyright (c) 2008 Alan Woodland 19 | # 20 | # This program is free software: you can redistribute it and/or modify it 21 | # under the terms of the GNU General Public License as published by the 22 | # Free Software Foundation, either version 3 of the License, or (at your 23 | # option) any later version. 24 | # 25 | # This program is distributed in the hope that it will be useful, but 26 | # WITHOUT ANY WARRANTY; without even the implied warranty of 27 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General 28 | # Public License for more details. 29 | # 30 | # You should have received a copy of the GNU General Public License along 31 | # with this program. If not, see . 32 | # 33 | # As a special exception, the respective Autoconf Macro's copyright owner 34 | # gives unlimited permission to copy, distribute and modify the configure 35 | # scripts that are the output of Autoconf when processing the Macro. You 36 | # need not follow the terms of the GNU General Public License when using 37 | # or distributing such scripts, even though portions of the text of the 38 | # Macro appear in them. The GNU General Public License (GPL) does govern 39 | # all other use of the material that constitutes the Autoconf Macro. 40 | # 41 | # This special exception to the GPL applies to versions of the Autoconf 42 | # Macro released by the Autoconf Archive. When you make and distribute a 43 | # modified version of the Autoconf Macro, you may extend this special 44 | # exception to the GPL to apply to your modified version as well. 45 | 46 | AC_DEFUN([AX_TLS], [ 47 | AC_MSG_CHECKING(for thread local storage specifier) 48 | AC_CACHE_VAL(ac_cv_tls, [ 49 | ax_tls_keywords="__thread __declspec(thread) none" 50 | for ax_tls_keyword in $ax_tls_keywords; do 51 | case $ax_tls_keyword in 52 | none) ac_cv_tls=none ; break ;; 53 | *) 54 | # MPICH2 modification: This was an AC_TRY_COMPILE before, but 55 | # Darwin with non-standard compilers will accept __thread at 56 | # compile time but fail to link due to an undefined 57 | # "__emutls_get_address" symbol unless -lgcc_eh is added to the 58 | # link line. 59 | AC_LINK_IFELSE( 60 | [AC_LANG_PROGRAM([$ax_tls_keyword int bar = 5;],[++bar;])], 61 | [ac_cv_tls=$ax_tls_keyword ; break], 62 | [ac_cv_tls=none]) 63 | esac 64 | done 65 | ]) 66 | 67 | if test "$ac_cv_tls" != "none"; then 68 | # MPICH2 modification: this was "TLS" before instead of 69 | # "MPIU_TLS_SPECIFIER", but TLS had a reasonably high chance of conflicting 70 | # with a system library. 71 | AC_DEFINE_UNQUOTED([MPIU_TLS_SPECIFIER], $ac_cv_tls, [If the compiler supports a TLS storage class define it to that here]) 72 | fi 73 | AC_MSG_RESULT($ac_cv_tls) 74 | ]) 75 | -------------------------------------------------------------------------------- /util/BigMPI/src/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | add_custom_command( 2 | OUTPUT "${CMAKE_CURRENT_SOURCE_DIR}/bigmpiconf.h" 3 | COMMAND "./autogen.sh" 4 | COMMAND "./configure" 5 | WORKING_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}/..") 6 | 7 | file(GLOB SOURCES "${CMAKE_CURRENT_SOURCE_DIR}/*.c") 8 | add_library(bigmpi ${LIB_LINKAGE_TYPE} ${SOURCES} "bigmpiconf.h") 9 | -------------------------------------------------------------------------------- /util/BigMPI/src/bigmpi_impl.h: -------------------------------------------------------------------------------- 1 | #ifndef BIGMPI_IMPL_H 2 | #define BIGMPI_IMPL_H 3 | 4 | #include "bigmpiconf.h" 5 | 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | 14 | #include 15 | 16 | #include "bigmpi.h" 17 | 18 | #include "likely.h" 19 | 20 | #ifdef BIGMPI_MAX_INT 21 | static const MPI_Count bigmpi_int_max = BIGMPI_MAX_INT; 22 | static const MPI_Count bigmpi_count_max = (MPI_Count)BIGMPI_MAX_INT*BIGMPI_MAX_INT; 23 | #else 24 | #include 25 | #include 26 | static const MPI_Count bigmpi_int_max = INT_MAX; 27 | /* SIZE_MAX corresponds to size_t, which should be what MPI_Aint is. */ 28 | static const MPI_Count bigmpi_count_max = SIZE_MAX; 29 | #endif 30 | 31 | void BigMPI_Error_impl(const char *file, const int line, const char *func, const char *msg, ...); 32 | 33 | #define BigMPI_Error(...) BigMPI_Error_impl(__FILE__,__LINE__,__func__,__VA_ARGS__) 34 | 35 | void BigMPI_Convert_vectors(int num, 36 | int splat_old_count, 37 | const MPI_Count oldcount, 38 | const MPI_Count oldcounts[], 39 | int splat_old_type, 40 | const MPI_Datatype oldtype, 41 | const MPI_Datatype oldtypes[], 42 | int zero_new_displs, 43 | const MPI_Aint olddispls[], 44 | int newcounts[], 45 | MPI_Datatype newtypes[], 46 | MPI_Aint newdispls[]); 47 | 48 | #endif // BIGMPI_IMPL_H 49 | -------------------------------------------------------------------------------- /util/BigMPI/src/likely.h: -------------------------------------------------------------------------------- 1 | /* Likely/Unlikely macros borrowed from MPICH via ARMCI-MPI */ 2 | 3 | /* These likely/unlikely macros provide static branch prediction hints to the 4 | * compiler, if such hints are available. Simply wrap the relevant expression in 5 | * the macro, like this: 6 | * 7 | * if (unlikely(ptr == NULL)) { 8 | * // ... some unlikely code path ... 9 | * } 10 | * 11 | * They should be used sparingly, especially in upper-level code. It's easy to 12 | * incorrectly estimate branching likelihood, while the compiler can often do a 13 | * decent job if left to its own devices. 14 | * 15 | * These macros are not namespaced because the namespacing is cumbersome. 16 | */ 17 | 18 | /* safety guard for now, add a configure check in the future */ 19 | #if ( defined(__GNUC__) && (__GNUC__ >= 3) ) || defined(__IBMC__) || defined(__INTEL_COMPILER) || defined(__clang__) 20 | # define unlikely(x_) __builtin_expect(!!(x_),0) 21 | # define likely(x_) __builtin_expect(!!(x_),1) 22 | #else 23 | # define unlikely(x_) (x_) 24 | # define likely(x_) (x_) 25 | #endif 26 | 27 | 28 | -------------------------------------------------------------------------------- /util/BigMPI/src/type_hindexed_x.c: -------------------------------------------------------------------------------- 1 | #include "bigmpi_impl.h" 2 | 3 | /* 4 | * Synopsis 5 | * 6 | * a version of MPI_Type_create_hvector, except the array_of_blocklengths can 7 | * be larger than 32 bits 8 | * 9 | * int MPIX_Type_create_hvector_x(MPI_Count count, 10 | * MPI_Count array_of_blocklengths[], 11 | * MPI_Aint array_of_displacements[], 12 | * MPI_Datatype oldtype, 13 | * MPI_Datatype * newtype) 14 | * 15 | * Input Parameters 16 | * 17 | * count number of blocks -- also number of entries in 18 | * array_of_displacements and array_of_blocklengths 19 | * (non-negative integer) 20 | * 21 | * array_of_blocklengths number of elements in each block (array of 22 | * non-negative integers) 23 | * 24 | * array_of_displacements byte displacement of each block (array of 25 | * integers) 26 | * 27 | * oldtype old datatype (handle) 28 | * 29 | * Output Parameter 30 | * 31 | * newtype new datatype (handle) 32 | * 33 | */ 34 | int MPIX_Type_create_hvector_x(int count, 35 | MPI_Count array_of_blocklengths[], MPI_Aint array_of_displacements[], 36 | MPI_Datatype oldtype, MPI_Datatype * newtype) 37 | { 38 | int i, ret; 39 | MPI_Datatype *types; 40 | int *blocklens; 41 | 42 | /* The count has to fit into MPI_Aint for BigMPI to work. */ 43 | if ((uint64_t)count>(uint64_t)bigmpi_count_max) { 44 | printf("count (%lld) exceeds bigmpi_count_max (%lld)\n", 45 | (long long unsigned)count, (long long unsigned)bigmpi_count_max); 46 | fflush(stdout); 47 | } 48 | 49 | types = malloc(count*sizeof(*types)); 50 | blocklens = malloc(count*sizeof(*blocklens)); 51 | 52 | for (i=0; i 2 | #include 3 | #include 4 | 5 | #include 6 | 7 | int main(int argc, char * argv[]) 8 | { 9 | printf("INT_MAX = %d\n", INT_MAX); 10 | 11 | int a = (int)INT_MAX*100; 12 | MPI_Aint b = (MPI_Aint)INT_MAX*100; 13 | int64_t c = (int64_t)INT_MAX*100; 14 | uint64_t d = (uint64_t)INT_MAX*100; 15 | 16 | printf("a = %d\n", a); 17 | printf("b = %zu\n", b); 18 | printf("c = %lld\n", c); 19 | printf("d = %llu\n", d); 20 | 21 | int a2 = 100; 22 | MPI_Aint b2 = 100; 23 | int64_t c2 = 100; 24 | uint64_t d2 = 100; 25 | 26 | a2 *= INT_MAX; 27 | b2 *= INT_MAX; 28 | c2 *= INT_MAX; 29 | d2 *= INT_MAX; 30 | 31 | printf("a2 = %d\n", a2); 32 | printf("b2 = %zu\n", b2); 33 | printf("c2 = %lld\n", c2); 34 | printf("d2 = %llu\n", d2); 35 | 36 | return 0; 37 | } 38 | -------------------------------------------------------------------------------- /util/BigMPI/test/devel/in_place_user_def_reduce.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | void printer(void * invec, void * inoutvec, int * len, MPI_Datatype * type) 5 | { 6 | int rank; 7 | MPI_Comm_rank(MPI_COMM_WORLD, &rank); 8 | printf("%d: invec = %p inoutvec = %p len = %d \n", rank, invec, inoutvec, *len); 9 | return; 10 | } 11 | 12 | int main(int argc, char* argv[]) 13 | { 14 | MPI_Init(&argc, &argv); 15 | 16 | int rank, size; 17 | MPI_Comm_rank(MPI_COMM_WORLD, &rank); 18 | MPI_Comm_size(MPI_COMM_WORLD, &size); 19 | 20 | int commute = 1; 21 | MPI_Op myop; 22 | MPI_Op_create(printer, commute, &myop); 23 | 24 | int in[8] = {1,2,3,4,5,6,7,8}; 25 | int out[8] = {-1,-2,-3,-4,-5,-6,-7,-8}; 26 | 27 | printf("%d: MPI_IN_PLACE = %p in = %p out = %p \n", rank, MPI_IN_PLACE, in, out); 28 | 29 | MPI_Barrier(MPI_COMM_WORLD); 30 | fflush(stdout); 31 | MPI_Barrier(MPI_COMM_WORLD); 32 | 33 | if (rank==0) printf("out-of-place Allreduce \n"); 34 | MPI_Allreduce(in, out, 8, MPI_INT, myop, MPI_COMM_WORLD); 35 | MPI_Barrier(MPI_COMM_WORLD); 36 | fflush(stdout); 37 | MPI_Barrier(MPI_COMM_WORLD); 38 | 39 | if (rank==0) printf("in-place Allreduce \n"); 40 | MPI_Allreduce(MPI_IN_PLACE, out, 8, MPI_INT, myop, MPI_COMM_WORLD); 41 | MPI_Barrier(MPI_COMM_WORLD); 42 | fflush(stdout); 43 | MPI_Barrier(MPI_COMM_WORLD); 44 | 45 | MPI_Op_free(&myop); 46 | MPI_Finalize(); 47 | return 0; 48 | } 49 | -------------------------------------------------------------------------------- /util/BigMPI/test/devel/preprocessor.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | #define SUM 0x1 4 | 5 | void Bar(int a) { return; }; 6 | 7 | #define MAKE_FOO(OP) void FOO_##OP##_fn(){ Bar(MPI_##OP);\ 8 | return; } 9 | 10 | MAKE_FOO(SUM); 11 | 12 | int main(void) 13 | { 14 | return 0; 15 | } 16 | -------------------------------------------------------------------------------- /util/BigMPI/test/devel/rounding.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | int main(int argc, char * argv[]) 4 | { 5 | printf("7/3 = %d\n",7/3); 6 | printf("8/3 = %d\n",8/3); 7 | return 0; 8 | } 9 | 10 | -------------------------------------------------------------------------------- /util/BigMPI/test/devel/type_create_struct.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | int main(int argc, char* argv[]) 5 | { 6 | MPI_Init(&argc, &argv); 7 | 8 | MPI_Finalize(); 9 | return 0; 10 | } 11 | -------------------------------------------------------------------------------- /util/BigMPI/test/mpi/Makefile.mk: -------------------------------------------------------------------------------- 1 | # 2 | # Copyright (C) 2014. See LICENSE in top-level directory. 3 | # 4 | 5 | check_PROGRAMS += test/mpi/reduce_scatter \ 6 | test/mpi/scatterv \ 7 | # end 8 | 9 | TESTS += test/mpi/reduce_scatter \ 10 | test/mpi/scatterv \ 11 | # end 12 | 13 | -------------------------------------------------------------------------------- /util/BigMPI/test/mpi/README.md: -------------------------------------------------------------------------------- 1 | These tests are to verify the behavior of MPI itself, such as to make 2 | sure various functions are count-safe and that the datatype functions 3 | work as desired. 4 | -------------------------------------------------------------------------------- /util/BigMPI/test/mpi/bcast.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | 8 | #include 9 | 10 | int MPIX_Type_contiguous_x(MPI_Count count, MPI_Datatype oldtype, MPI_Datatype * newtype) 11 | { 12 | const MPI_Count bigmpi_int_max = (MPI_Count)INT_MAX; 13 | 14 | MPI_Count c = count/bigmpi_int_max; 15 | MPI_Count r = count%bigmpi_int_max; 16 | 17 | assert(c1) ? atol(argv[1]) : 1L<<31; 51 | if (rank==0) { 52 | printf("Test: %zu bytes\n",n); 53 | } 54 | 55 | char * ptr = NULL; 56 | MPI_Alloc_mem(n,MPI_INFO_NULL,&ptr); 57 | 58 | if (rank==0) { 59 | memset(ptr,255,n); 60 | } else { 61 | memset(ptr,0,n); 62 | } 63 | 64 | MPI_Datatype bigtype; 65 | MPIX_Type_contiguous_x(n,MPI_CHAR,&bigtype); 66 | MPI_Type_commit(&bigtype); 67 | 68 | if (0 && n<(size_t)INT_MAX) { 69 | if (rank==0) printf("Not using a contiguous datatype\n"); 70 | MPI_Bcast(ptr,(int)n,MPI_CHAR,0,MPI_COMM_WORLD); 71 | } else { 72 | if (rank==0) printf("Using a contiguous datatype\n"); 73 | MPI_Bcast(ptr,1,bigtype,0,MPI_COMM_WORLD); 74 | } 75 | 76 | size_t errors = 0; 77 | for (size_t i=0; i0) { 82 | printf("%d: There were %zu errors!\n", rank, errors); 83 | for (size_t i=0; i 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | 9 | #include 10 | 11 | const unsigned int bignum = 3*1073741824; /* 3*2^30 < 2^32 */ 12 | 13 | int main(int argc, char* argv[]) 14 | { 15 | MPI_Init(&argc, &argv); 16 | 17 | int rank, size; 18 | MPI_Comm_rank(MPI_COMM_WORLD, &rank); 19 | MPI_Comm_size(MPI_COMM_WORLD, &size); 20 | 21 | if (size<2) { 22 | printf("Use more than 1 process for this test\n"); 23 | MPI_Finalize(); 24 | return 1; 25 | } 26 | 27 | int * counts = malloc(size*sizeof(int)); 28 | int * displs = malloc(size*sizeof(int)); 29 | 30 | for (int i=0; i0); 34 | } 35 | 36 | char * sendbuf = malloc(bignum); 37 | char * recvbuf = malloc(bignum/size); 38 | 39 | memset(sendbuf, rank==0 ? 1 : 0, bignum); 40 | memset(recvbuf, 0, bignum/size); 41 | 42 | MPI_Scatterv(sendbuf, counts, displs, MPI_CHAR, 43 | recvbuf, (int)(bignum/size), MPI_CHAR, 44 | 0, MPI_COMM_WORLD); 45 | 46 | free(counts); 47 | free(displs); 48 | 49 | free(sendbuf); 50 | free(recvbuf); 51 | 52 | MPI_Finalize(); 53 | 54 | return 0; 55 | } 56 | -------------------------------------------------------------------------------- /util/BigMPI/test/perf/Makefile: -------------------------------------------------------------------------------- 1 | CC = mpicc 2 | CFLAGS = -O2 -Wall -std=c99 3 | 4 | TESTS = reductions typecontig typepiggy 5 | 6 | all: $(TESTS) 7 | 8 | %: %.c 9 | $(CC) $(CFLAGS) $< -o $@ 10 | 11 | clean: 12 | -rm -f $(TESTS) 13 | 14 | -------------------------------------------------------------------------------- /util/BigMPI/test/perf/typecontig.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | 9 | const int bigmpi_int_max = INT_MAX; 10 | 11 | int MPIX_Type_contiguous_x(MPI_Count count, MPI_Datatype oldtype, MPI_Datatype * newtype) 12 | { 13 | MPI_Count c = count/bigmpi_int_max; 14 | MPI_Count r = count%bigmpi_int_max; 15 | 16 | MPI_Datatype chunks; 17 | MPI_Type_vector(c, bigmpi_int_max, bigmpi_int_max, oldtype, &chunks); 18 | 19 | MPI_Datatype remainder; 20 | MPI_Type_contiguous(r, oldtype, &remainder); 21 | 22 | MPI_Aint lb /* unused */, extent; 23 | MPI_Type_get_extent(oldtype, &lb, &extent); 24 | 25 | MPI_Aint remdisp = (MPI_Aint)c*bigmpi_int_max*extent; 26 | int blocklengths[2] = {1,1}; 27 | MPI_Aint displacements[2] = {0,remdisp}; 28 | MPI_Datatype types[2] = {chunks,remainder}; 29 | MPI_Type_create_struct(2, blocklengths, displacements, types, newtype); 30 | 31 | MPI_Type_free(&chunks); 32 | MPI_Type_free(&remainder); 33 | 34 | return MPI_SUCCESS; 35 | } 36 | 37 | int main(int argc, char* argv[]) 38 | { 39 | int rank=0, size=1; 40 | MPI_Init(&argc, &argv); 41 | MPI_Comm_rank(MPI_COMM_WORLD, &rank); 42 | MPI_Comm_size(MPI_COMM_WORLD, &size); 43 | 44 | int n = (argc>1) ? atoi(argv[1]) : 10000; 45 | //MPI_Datatype * dtout = malloc(n*sizeof(MPI_Datatype)); 46 | MPI_Datatype dtout; 47 | double t0 = MPI_Wtime(); 48 | for (int i=0; i 2 | #include 3 | #include 4 | 5 | int piggysize = 8; 6 | MPI_Datatype piggytype = MPI_CHAR; 7 | char piggybuf[8] = "01234567"; 8 | 9 | int MPIX_Type_piggy_x(int count, MPI_Datatype oldtype, MPI_Datatype * newtype) 10 | { 11 | int size; 12 | MPI_Type_size(oldtype,&size); 13 | 14 | int blocklengths[2] = {count,piggysize}; 15 | MPI_Aint displacements[2] = {0,(MPI_Aint)count * (MPI_Aint)size}; 16 | MPI_Datatype types[2] = {oldtype,piggytype}; 17 | MPI_Type_create_struct(2, blocklengths, displacements, types, newtype); 18 | 19 | return MPI_SUCCESS; 20 | } 21 | 22 | int main(int argc, char* argv[]) 23 | { 24 | int rank=0, size=1; 25 | MPI_Init(&argc, &argv); 26 | MPI_Comm_rank(MPI_COMM_WORLD, &rank); 27 | MPI_Comm_size(MPI_COMM_WORLD, &size); 28 | 29 | int n = (argc>1) ? atoi(argv[1]) : 10000; 30 | //MPI_Datatype * dtout = malloc(n*sizeof(MPI_Datatype)); 31 | MPI_Datatype dtout; 32 | double t0 = MPI_Wtime(); 33 | for (int i=0; i 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | 8 | #include 9 | #include "bigmpi.h" 10 | #include "verify_buffer.h" 11 | 12 | /* Yes, it is technically unsafe to cast MPI_Count to MPI_Aint or size_t without checking, 13 | * given that MPI_Count might be 128b and MPI_Aint and size_t might be 64b, but BigMPI 14 | * does not aspire to support communication of more than 8 EiB messages at a time. */ 15 | 16 | int main(int argc, char * argv[]) 17 | { 18 | const MPI_Count test_int_max = BigMPI_Get_max_int(); 19 | 20 | MPI_Init(&argc, &argv); 21 | 22 | int rank, size; 23 | MPI_Comm_rank(MPI_COMM_WORLD, &rank); 24 | MPI_Comm_size(MPI_COMM_WORLD, &size); 25 | 26 | if (size<1) { 27 | printf("Use 1 or more processes. \n"); 28 | MPI_Finalize(); 29 | return 1; 30 | } 31 | 32 | int l = (argc > 1) ? atoi(argv[1]) : 2; 33 | int m = (argc > 2) ? atoi(argv[2]) : 17777; 34 | MPI_Count n = l * test_int_max + m; 35 | 36 | char * buf_send = NULL; 37 | char * buf_recv = NULL; 38 | 39 | MPI_Alloc_mem((MPI_Aint)n * 1, MPI_INFO_NULL, &buf_send); 40 | assert(buf_send!=NULL); 41 | MPI_Alloc_mem((MPI_Aint)n * size, MPI_INFO_NULL, &buf_recv); 42 | assert(buf_recv!=NULL); 43 | 44 | for (MPI_Count j = 0; j < n; ++j) { 45 | buf_send[j] = (unsigned char)rank; 46 | } 47 | memset(buf_recv, -1, (size_t)n); 48 | 49 | /* collective communication */ 50 | MPIX_Allgather_x(buf_send, n, MPI_CHAR, 51 | buf_recv, n, MPI_CHAR, 52 | MPI_COMM_WORLD); 53 | 54 | size_t errors = 0; 55 | for (int i = 0; i < size; ++i) { 56 | errors += verify_buffer(buf_recv + i * n, n, i); 57 | } 58 | 59 | MPI_Free_mem(buf_send); 60 | MPI_Free_mem(buf_recv); 61 | 62 | if (rank==0 && errors==0) { 63 | printf("SUCCESS\n"); 64 | } 65 | 66 | MPI_Finalize(); 67 | 68 | int rc = (errors > 0) ? 1 : 0; 69 | return rc; 70 | } 71 | -------------------------------------------------------------------------------- /util/BigMPI/test/test_allreduce_x.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | 7 | #include 8 | #include "bigmpi.h" 9 | #include "verify_buffer.h" 10 | 11 | /* Yes, it is technically unsafe to cast MPI_Count to MPI_Aint or size_t without checking, 12 | * given that MPI_Count might be 128b and MPI_Aint and size_t might be 64b, but BigMPI 13 | * does not aspire to support communication of more than 8 EiB messages at a time. */ 14 | 15 | int main(int argc, char * argv[]) 16 | { 17 | const MPI_Count test_int_max = BigMPI_Get_max_int(); 18 | 19 | MPI_Init(&argc, &argv); 20 | 21 | int rank, size; 22 | MPI_Comm_rank(MPI_COMM_WORLD, &rank); 23 | MPI_Comm_size(MPI_COMM_WORLD, &size); 24 | 25 | if (size<1) { 26 | printf("Use 1 or more processes. \n"); 27 | MPI_Finalize(); 28 | return 1; 29 | } 30 | 31 | int l = (argc > 1) ? atoi(argv[1]) : 2; 32 | int m = (argc > 2) ? atoi(argv[2]) : 17777; 33 | MPI_Count n = l * test_int_max + m; 34 | 35 | double * sbuf = NULL; 36 | double * rbuf = NULL; 37 | 38 | MPI_Aint bytes = n*sizeof(double); 39 | MPI_Alloc_mem(bytes, MPI_INFO_NULL, &sbuf); 40 | MPI_Alloc_mem(bytes, MPI_INFO_NULL, &rbuf); 41 | 42 | for (MPI_Count i=0; i 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | 8 | #include 9 | #include "bigmpi.h" 10 | #include "verify_buffer.h" 11 | 12 | /* Yes, it is technically unsafe to cast MPI_Count to MPI_Aint or size_t without checking, 13 | * given that MPI_Count might be 128b and MPI_Aint and size_t might be 64b, but BigMPI 14 | * does not aspire to support communication of more than 8 EiB messages at a time. */ 15 | 16 | int main(int argc, char * argv[]) 17 | { 18 | const MPI_Count test_int_max = BigMPI_Get_max_int(); 19 | 20 | MPI_Init(&argc, &argv); 21 | 22 | int rank, size; 23 | MPI_Comm_rank(MPI_COMM_WORLD, &rank); 24 | MPI_Comm_size(MPI_COMM_WORLD, &size); 25 | 26 | if (size<1) { 27 | printf("Use 1 or more processes. \n"); 28 | MPI_Finalize(); 29 | return 1; 30 | } 31 | 32 | int l = (argc > 1) ? atoi(argv[1]) : 2; 33 | int m = (argc > 2) ? atoi(argv[2]) : 17777; 34 | MPI_Count n = l * test_int_max + m; 35 | 36 | char * buf_send = NULL; 37 | char * buf_recv = NULL; 38 | 39 | MPI_Alloc_mem((MPI_Aint)n * size, MPI_INFO_NULL, &buf_send); 40 | assert(buf_send!=NULL); 41 | MPI_Alloc_mem((MPI_Aint)n * size, MPI_INFO_NULL, &buf_recv); 42 | assert(buf_recv!=NULL); 43 | 44 | for (int i = 0; i < size; ++i) { 45 | for (MPI_Count j = 0; j < n; ++j) { 46 | buf_send[i*n+j] = (unsigned char)i; 47 | } 48 | } 49 | memset(buf_recv, -1, (size_t)n); 50 | 51 | /* collective communication */ 52 | MPIX_Alltoall_x(buf_send, n, MPI_CHAR, 53 | buf_recv, n, MPI_CHAR, 54 | MPI_COMM_WORLD); 55 | 56 | size_t errors = verify_buffer(buf_recv, n, rank); 57 | 58 | MPI_Free_mem(buf_send); 59 | MPI_Free_mem(buf_recv); 60 | 61 | if (rank==0 && errors==0) { 62 | printf("SUCCESS\n"); 63 | } 64 | 65 | MPI_Finalize(); 66 | 67 | int rc = (errors > 0) ? 1 : 0; 68 | return rc; 69 | } 70 | -------------------------------------------------------------------------------- /util/BigMPI/test/test_assert_x.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2014. See LICENSE in top-level directory. 3 | */ 4 | 5 | #include 6 | #include 7 | #include 8 | 9 | #include 10 | #include "bigmpi.h" 11 | 12 | int main(int argc, char ** argv) 13 | { 14 | MPI_Init(&argc, &argv); 15 | assert(0); 16 | MPI_Finalize(); 17 | return 0; 18 | } 19 | -------------------------------------------------------------------------------- /util/BigMPI/test/test_bcast_x.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | 7 | #include 8 | #include "bigmpi.h" 9 | #include "verify_buffer.h" 10 | 11 | /* Yes, it is technically unsafe to cast MPI_Count to MPI_Aint or size_t without checking, 12 | * given that MPI_Count might be 128b and MPI_Aint and size_t might be 64b, but BigMPI 13 | * does not aspire to support communication of more than 8 EiB messages at a time. */ 14 | 15 | int main(int argc, char * argv[]) 16 | { 17 | const MPI_Count test_int_max = BigMPI_Get_max_int(); 18 | 19 | MPI_Init(&argc, &argv); 20 | 21 | int rank, size; 22 | MPI_Comm_rank(MPI_COMM_WORLD, &rank); 23 | MPI_Comm_size(MPI_COMM_WORLD, &size); 24 | 25 | if (size<1) { 26 | printf("Use 1 or more processes. \n"); 27 | MPI_Finalize(); 28 | return 1; 29 | } 30 | 31 | int l = (argc > 1) ? atoi(argv[1]) : 2; 32 | int m = (argc > 2) ? atoi(argv[2]) : 17777; 33 | MPI_Count n = l * test_int_max + m; 34 | 35 | char * buf = NULL; 36 | 37 | MPI_Alloc_mem((MPI_Aint)n, MPI_INFO_NULL, &buf); 38 | 39 | memset(buf, rank==0 ? size : 0, (size_t)n); 40 | 41 | /* collective communication */ 42 | MPIX_Bcast_x(buf, n, MPI_CHAR, 0 /* root */, MPI_COMM_WORLD); 43 | 44 | size_t errors = verify_buffer(buf, n, size); 45 | if (errors > 0) { 46 | printf("There were %zu errors!", errors); 47 | for (size_t i=0; i<(size_t)n; i++) { 48 | printf("buf[%zu] = %d (expected %d)\n", i, buf[i], size); 49 | } 50 | } 51 | if (rank==0 && errors==0) { 52 | printf("SUCCESS\n"); 53 | } 54 | 55 | MPI_Free_mem(buf); 56 | 57 | MPI_Finalize(); 58 | 59 | return 0; 60 | } 61 | -------------------------------------------------------------------------------- /util/BigMPI/test/test_contig_x.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include "bigmpi.h" 7 | 8 | 9 | static void print_typename(MPI_Datatype type) 10 | { 11 | char * name; 12 | if (type==MPI_CHAR ) name="MPI_CHAR "; 13 | else if (type==MPI_SIGNED_CHAR ) name="MPI_SIGNED_CHAR "; 14 | else if (type==MPI_UNSIGNED_CHAR ) name="MPI_UNSIGNED_CHAR "; 15 | else if (type==MPI_BYTE ) name="MPI_BYTE "; 16 | else if (type==MPI_WCHAR ) name="MPI_WCHAR "; 17 | else if (type==MPI_SHORT ) name="MPI_SHORT "; 18 | else if (type==MPI_UNSIGNED_SHORT ) name="MPI_UNSIGNED_SHORT "; 19 | else if (type==MPI_INT ) name="MPI_INT "; 20 | else if (type==MPI_UNSIGNED ) name="MPI_UNSIGNED "; 21 | else if (type==MPI_LONG ) name="MPI_LONG "; 22 | else if (type==MPI_UNSIGNED_LONG ) name="MPI_UNSIGNED_LONG "; 23 | else if (type==MPI_FLOAT ) name="MPI_FLOAT "; 24 | else if (type==MPI_DOUBLE ) name="MPI_DOUBLE "; 25 | else if (type==MPI_LONG_DOUBLE ) name="MPI_LONG_DOUBLE "; 26 | else if (type==MPI_LONG_LONG_INT ) name="MPI_LONG_LONG_INT "; 27 | else if (type==MPI_LONG_LONG ) name="MPI_LONG_LONG "; 28 | else if (type==MPI_UNSIGNED_LONG_LONG) name="MPI_UNSIGNED_LONG_LONG"; 29 | else name="NOT_PREDEFINED_TYPE "; 30 | printf("type = %s\n", name); 31 | return; 32 | } 33 | 34 | int main(int argc, char* argv[]) 35 | { 36 | const int e = 60; 37 | 38 | const MPI_Count test_int_max = BigMPI_Get_max_int(); 39 | 40 | MPI_Init(&argc, &argv); 41 | 42 | int rank, size; 43 | MPI_Comm_rank(MPI_COMM_WORLD, &rank); 44 | MPI_Comm_size(MPI_COMM_WORLD, &size); 45 | 46 | MPI_Count n = 1; 47 | int errors = 0; 48 | for (int i=0; iINT_MAX || n>=(test_int_max*test_int_max) ) { 76 | MPI_Finalize(); 77 | return errors; 78 | } 79 | } 80 | } 81 | MPI_Finalize(); 82 | return errors; 83 | } 84 | -------------------------------------------------------------------------------- /util/BigMPI/test/test_factorize.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | 9 | #ifdef __x86_64__ 10 | static inline unsigned long long rdtsc(void) 11 | { 12 | unsigned hi, lo; 13 | __asm__ __volatile__ ("rdtsc" : "=a"(lo), "=d"(hi)); 14 | return ( (unsigned long long)lo)|( ((unsigned long long)hi)<<32 ); 15 | } 16 | #endif 17 | 18 | /* This function is copied from src/type_contiguous_x.c and must be updated 19 | * manually if the implementation changes. It is an internal function so 20 | * it is static and therefore be cannot call the symbol from the library. */ 21 | 22 | /* 23 | * Synopsis 24 | * 25 | * int BigMPI_Factorize_count(MPI_Count c, int * a, int *b) 26 | * 27 | * Input Parameter 28 | * 29 | * c large count 30 | * 31 | * Output Parameters 32 | * 33 | * a, b integers such that c=a*b and a,blo; g--) { 44 | size_t rem = in%g; 45 | if (rem==0) { 46 | *a = (int)g; 47 | *b = (int)(in/g); 48 | return 0; 49 | } 50 | } 51 | *a = -1; 52 | *b = -1; 53 | return 1; 54 | } 55 | 56 | #define TIMING 57 | #define DEBUG 58 | 59 | int main(int argc, char* argv[]) 60 | { 61 | int rank=0, size=1; 62 | #ifdef PARALLEL 63 | MPI_Init(&argc, &argv); 64 | MPI_Comm_rank(MPI_COMM_WORLD, &rank); 65 | MPI_Comm_size(MPI_COMM_WORLD, &size); 66 | #endif 67 | MPI_Count max = (argc>1) ? atol(argv[1]) : 1LL<<60; 68 | MPI_Count inc = size; /* Incremement by nproc to distribute test work. */ 69 | 70 | #ifdef TIMING 71 | #ifdef PARALLEL 72 | double t0 = MPI_Wtime(); 73 | #else 74 | unsigned long long t0 = rdtsc(); 75 | #endif 76 | #endif 77 | for (MPI_Count count=1; count 2 | #include 3 | #include 4 | #include 5 | #include 6 | 7 | #include 8 | #include "bigmpi.h" 9 | #include "verify_buffer.h" 10 | 11 | /* Yes, it is technically unsafe to cast MPI_Count to MPI_Aint or size_t without checking, 12 | * given that MPI_Count might be 128b and MPI_Aint and size_t might be 64b, but BigMPI 13 | * does not aspire to support communication of more than 8 EiB messages at a time. */ 14 | 15 | int main(int argc, char * argv[]) 16 | { 17 | const MPI_Count test_int_max = BigMPI_Get_max_int(); 18 | 19 | MPI_Init(&argc, &argv); 20 | 21 | int rank, size; 22 | MPI_Comm_rank(MPI_COMM_WORLD, &rank); 23 | MPI_Comm_size(MPI_COMM_WORLD, &size); 24 | 25 | if (size<1) { 26 | printf("Use 1 or more processes. \n"); 27 | MPI_Finalize(); 28 | return 1; 29 | } 30 | 31 | int l = (argc > 1) ? atoi(argv[1]) : 2; 32 | int m = (argc > 2) ? atoi(argv[2]) : 17777; 33 | MPI_Count n = l * test_int_max + m; 34 | 35 | char * buf_send = NULL; 36 | char * buf_recv = NULL; 37 | 38 | MPI_Alloc_mem((MPI_Aint)n, MPI_INFO_NULL, &buf_send); 39 | MPI_Alloc_mem((MPI_Aint)n * size, MPI_INFO_NULL, &buf_recv); 40 | 41 | memset(buf_send, rank, (size_t)n); 42 | memset(buf_recv, -1, (size_t)n * size); 43 | 44 | /* collective communication */ 45 | MPIX_Gather_x(buf_send, n, MPI_CHAR, 46 | buf_recv, n, MPI_CHAR, 47 | 0 /* root */, MPI_COMM_WORLD); 48 | 49 | size_t errors = 0; 50 | if (rank==0) { 51 | for (int i = 0; i < size; ++i) { 52 | errors += verify_buffer(buf_recv + i * n, n, i); 53 | } 54 | } 55 | 56 | /* collective communication */ 57 | MPIX_Allgather_x(buf_send, n, MPI_CHAR, 58 | buf_recv, n, MPI_CHAR, 59 | MPI_COMM_WORLD); 60 | 61 | for (int i = 0; i < size; ++i) { 62 | errors += verify_buffer(buf_recv + i * n, n, i); 63 | } 64 | 65 | MPI_Free_mem(buf_send); 66 | MPI_Free_mem(buf_recv); 67 | 68 | if (rank==0 && errors==0) { 69 | printf("SUCCESS\n"); 70 | } 71 | 72 | MPI_Finalize(); 73 | 74 | return 0; 75 | } 76 | -------------------------------------------------------------------------------- /util/BigMPI/test/test_irsend_irecv_x.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | 7 | #include 8 | #include "bigmpi.h" 9 | #include "verify_buffer.h" 10 | 11 | /* Yes, it is technically unsafe to cast MPI_Count to MPI_Aint or size_t without checking, 12 | * given that MPI_Count might be 128b and MPI_Aint and size_t might be 64b, but BigMPI 13 | * does not aspire to support communication of more than 8 EiB messages at a time. */ 14 | 15 | int main(int argc, char * argv[]) 16 | { 17 | MPI_Init(&argc, &argv); 18 | 19 | int rank, size; 20 | MPI_Comm_rank(MPI_COMM_WORLD, &rank); 21 | MPI_Comm_size(MPI_COMM_WORLD, &size); 22 | 23 | const MPI_Count test_int_max = BigMPI_Get_max_int(); 24 | 25 | if (size<2) { 26 | printf("Use 2 or more processes. \n"); 27 | MPI_Finalize(); 28 | return 1; 29 | } 30 | 31 | int l = (argc > 1) ? atoi(argv[1]) : 2; 32 | int m = (argc > 2) ? atoi(argv[2]) : 17777; 33 | MPI_Count n = l * test_int_max + m; 34 | 35 | char * buf = NULL; 36 | 37 | MPI_Alloc_mem((MPI_Aint)n, MPI_INFO_NULL, &buf); 38 | 39 | memset(buf, rank, (size_t)n); 40 | 41 | size_t errors = 0; 42 | for (int r = 1; r < size; r++) { 43 | 44 | MPI_Request req; 45 | 46 | /* pairwise communication */ 47 | if (rank==r) { 48 | MPIX_Irsend_x(buf, n, MPI_CHAR, 0 /* dst */, r /* tag */, MPI_COMM_WORLD, &req); 49 | } 50 | else if (rank==0) { 51 | MPIX_Irecv_x(buf, n, MPI_CHAR, r /* src */, r /* tag */, MPI_COMM_WORLD, &req); 52 | } 53 | 54 | if (rank == 0 || rank==r) { 55 | MPI_Wait(&req, MPI_STATUS_IGNORE); 56 | } 57 | 58 | if (rank==0) { 59 | errors += verify_buffer(buf, n, r); 60 | if (errors > 0) { 61 | printf("There were %zu errors!", errors); 62 | } 63 | } 64 | } 65 | 66 | MPI_Free_mem(buf); 67 | 68 | if (rank==0 && errors==0) { 69 | printf("SUCCESS\n"); 70 | } 71 | 72 | MPI_Finalize(); 73 | 74 | return 0; 75 | } 76 | -------------------------------------------------------------------------------- /util/BigMPI/test/test_isend_irecv_x.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | 7 | #include 8 | #include "bigmpi.h" 9 | #include "verify_buffer.h" 10 | 11 | /* Yes, it is technically unsafe to cast MPI_Count to MPI_Aint or size_t without checking, 12 | * given that MPI_Count might be 128b and MPI_Aint and size_t might be 64b, but BigMPI 13 | * does not aspire to support communication of more than 8 EiB messages at a time. */ 14 | 15 | int main(int argc, char * argv[]) 16 | { 17 | MPI_Init(&argc, &argv); 18 | 19 | int rank, size; 20 | MPI_Comm_rank(MPI_COMM_WORLD, &rank); 21 | MPI_Comm_size(MPI_COMM_WORLD, &size); 22 | 23 | const MPI_Count test_int_max = BigMPI_Get_max_int(); 24 | 25 | if (size<2) { 26 | printf("Use 2 or more processes. \n"); 27 | MPI_Finalize(); 28 | return 1; 29 | } 30 | 31 | int l = (argc > 1) ? atoi(argv[1]) : 2; 32 | int m = (argc > 2) ? atoi(argv[2]) : 17777; 33 | MPI_Count n = l * test_int_max + m; 34 | 35 | char * buf = NULL; 36 | 37 | MPI_Alloc_mem((MPI_Aint)n, MPI_INFO_NULL, &buf); 38 | 39 | memset(buf, rank, (size_t)n); 40 | 41 | size_t errors = 0; 42 | for (int r = 1; r < size; r++) { 43 | 44 | MPI_Request req; 45 | 46 | /* pairwise communication */ 47 | if (rank==r) { 48 | MPIX_Isend_x(buf, n, MPI_CHAR, 0 /* dst */, r /* tag */, MPI_COMM_WORLD, &req); 49 | } 50 | else if (rank==0) { 51 | MPIX_Irecv_x(buf, n, MPI_CHAR, r /* src */, r /* tag */, MPI_COMM_WORLD, &req); 52 | } 53 | 54 | if (rank == 0 || rank==r) { 55 | MPI_Wait(&req, MPI_STATUS_IGNORE); 56 | } 57 | 58 | if (rank==0) { 59 | errors += verify_buffer(buf, n, r); 60 | if (errors > 0) { 61 | printf("There were %zu errors!", errors); 62 | } 63 | } 64 | } 65 | 66 | MPI_Free_mem(buf); 67 | 68 | if (rank==0 && errors==0) { 69 | printf("SUCCESS\n"); 70 | } 71 | 72 | MPI_Finalize(); 73 | 74 | return 0; 75 | } 76 | -------------------------------------------------------------------------------- /util/BigMPI/test/test_issend_irecv_x.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | 7 | #include 8 | #include "bigmpi.h" 9 | #include "verify_buffer.h" 10 | 11 | /* Yes, it is technically unsafe to cast MPI_Count to MPI_Aint or size_t without checking, 12 | * given that MPI_Count might be 128b and MPI_Aint and size_t might be 64b, but BigMPI 13 | * does not aspire to support communication of more than 8 EiB messages at a time. */ 14 | 15 | int main(int argc, char * argv[]) 16 | { 17 | MPI_Init(&argc, &argv); 18 | 19 | int rank, size; 20 | MPI_Comm_rank(MPI_COMM_WORLD, &rank); 21 | MPI_Comm_size(MPI_COMM_WORLD, &size); 22 | 23 | const MPI_Count test_int_max = BigMPI_Get_max_int(); 24 | 25 | if (size<2) { 26 | printf("Use 2 or more processes. \n"); 27 | MPI_Finalize(); 28 | return 1; 29 | } 30 | 31 | int l = (argc > 1) ? atoi(argv[1]) : 2; 32 | int m = (argc > 2) ? atoi(argv[2]) : 17777; 33 | MPI_Count n = l * test_int_max + m; 34 | 35 | char * buf = NULL; 36 | 37 | MPI_Alloc_mem((MPI_Aint)n, MPI_INFO_NULL, &buf); 38 | 39 | memset(buf, rank, (size_t)n); 40 | 41 | size_t errors = 0; 42 | for (int r = 1; r < size; r++) { 43 | 44 | MPI_Request req; 45 | 46 | /* pairwise communication */ 47 | if (rank==r) { 48 | MPIX_Issend_x(buf, n, MPI_CHAR, 0 /* dst */, r /* tag */, MPI_COMM_WORLD, &req); 49 | } 50 | else if (rank==0) { 51 | MPIX_Irecv_x(buf, n, MPI_CHAR, r /* src */, r /* tag */, MPI_COMM_WORLD, &req); 52 | } 53 | 54 | if (rank == 0 || rank==r) { 55 | MPI_Wait(&req, MPI_STATUS_IGNORE); 56 | } 57 | 58 | if (rank==0) { 59 | errors += verify_buffer(buf, n, r); 60 | if (errors > 0) { 61 | printf("There were %zu errors!", errors); 62 | } 63 | } 64 | } 65 | 66 | MPI_Free_mem(buf); 67 | 68 | if (rank==0 && errors==0) { 69 | printf("SUCCESS\n"); 70 | } 71 | 72 | MPI_Finalize(); 73 | 74 | return 0; 75 | } 76 | -------------------------------------------------------------------------------- /util/BigMPI/test/test_reduce_x.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | 7 | #include 8 | #include "bigmpi.h" 9 | #include "verify_buffer.h" 10 | 11 | /* Yes, it is technically unsafe to cast MPI_Count to MPI_Aint or size_t without checking, 12 | * given that MPI_Count might be 128b and MPI_Aint and size_t might be 64b, but BigMPI 13 | * does not aspire to support communication of more than 8 EiB messages at a time. */ 14 | 15 | int main(int argc, char * argv[]) 16 | { 17 | const MPI_Count test_int_max = BigMPI_Get_max_int(); 18 | 19 | MPI_Init(&argc, &argv); 20 | 21 | int rank, size; 22 | MPI_Comm_rank(MPI_COMM_WORLD, &rank); 23 | MPI_Comm_size(MPI_COMM_WORLD, &size); 24 | 25 | if (size<1) { 26 | printf("Use 1 or more processes. \n"); 27 | MPI_Finalize(); 28 | return 1; 29 | } 30 | 31 | int l = (argc > 1) ? atoi(argv[1]) : 2; 32 | int m = (argc > 2) ? atoi(argv[2]) : 17777; 33 | MPI_Count n = l * test_int_max + m; 34 | 35 | double * sbuf = NULL; 36 | double * rbuf = NULL; 37 | 38 | MPI_Aint bytes = n*sizeof(double); 39 | MPI_Alloc_mem(bytes, MPI_INFO_NULL, &sbuf); 40 | MPI_Alloc_mem(bytes, MPI_INFO_NULL, &rbuf); 41 | 42 | for (MPI_Count i=0; i 2 | #include 3 | #include 4 | #include 5 | #include 6 | 7 | #include 8 | #include "bigmpi.h" 9 | #include "verify_buffer.h" 10 | 11 | /* Yes, it is technically unsafe to cast MPI_Count to MPI_Aint or size_t without checking, 12 | * given that MPI_Count might be 128b and MPI_Aint and size_t might be 64b, but BigMPI 13 | * does not aspire to support communication of more than 8 EiB messages at a time. */ 14 | 15 | int main(int argc, char * argv[]) 16 | { 17 | #if MPI_VERSION >= 3 18 | const MPI_Count test_int_max = BigMPI_Get_max_int(); 19 | 20 | MPI_Init(&argc, &argv); 21 | 22 | int rank, size; 23 | MPI_Comm_rank(MPI_COMM_WORLD, &rank); 24 | MPI_Comm_size(MPI_COMM_WORLD, &size); 25 | 26 | int l = (argc > 1) ? atoi(argv[1]) : 2; 27 | int m = (argc > 2) ? atoi(argv[2]) : 17777; 28 | MPI_Count n = l * test_int_max + m; 29 | MPI_Count c = n/sizeof(double); 30 | 31 | double * baseptr = NULL; 32 | MPI_Win win; 33 | /* Allocate all the window memory on rank 0 */ 34 | MPI_Win_allocate((MPI_Aint)(rank==0 ? n : 0), sizeof(double), MPI_INFO_NULL, MPI_COMM_WORLD, &baseptr, &win); 35 | MPI_Win_lock_all(0, win); 36 | 37 | if (rank==0) { 38 | set_doubles(baseptr, c, 0.0); 39 | MPI_Win_sync(win); 40 | } 41 | MPI_Barrier(MPI_COMM_WORLD); 42 | 43 | double * buf = NULL; 44 | if ((size==1 && rank==0) || rank==1) { 45 | MPI_Alloc_mem((MPI_Aint)n, MPI_INFO_NULL, &buf); 46 | set_doubles(buf, c, 7.0); 47 | MPIX_Put_x(buf, c, MPI_DOUBLE, 0 /* target */, 0 /* disp */, c, MPI_DOUBLE, win); 48 | set_doubles(buf, c, 17.0); 49 | MPIX_Accumulate_x(buf, c, MPI_DOUBLE, 0 /* target */, 0 /* disp */, c, MPI_DOUBLE, MPI_SUM, win); 50 | set_doubles(buf, c, 0.0); 51 | MPIX_Get_x(buf, c, MPI_DOUBLE, 0 /* target */, 0 /* disp */, c, MPI_DOUBLE, win); 52 | 53 | double expected = 7.0 + 17.0; 54 | size_t errors = verify_doubles(buf, c, expected); 55 | if (errors > 0) { 56 | printf("There were %zu errors!", errors); 57 | for (size_t i=0; i<(size_t)c; i++) { 58 | printf("buf[%zu] = %lf (expected %lf)\n", i, buf[i], expected); 59 | } 60 | } 61 | if (errors==0) { 62 | printf("SUCCESS\n"); 63 | } 64 | } 65 | 66 | MPI_Win_unlock_all(win); 67 | MPI_Win_free(&win); 68 | 69 | MPI_Finalize(); 70 | 71 | #endif 72 | 73 | return 0; 74 | } 75 | -------------------------------------------------------------------------------- /util/BigMPI/test/test_rma_x.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | 8 | #include 9 | #include "bigmpi.h" 10 | #include "verify_buffer.h" 11 | 12 | /* Yes, it is technically unsafe to cast MPI_Count to MPI_Aint or size_t without checking, 13 | * given that MPI_Count might be 128b and MPI_Aint and size_t might be 64b, but BigMPI 14 | * does not aspire to support communication of more than 8 EiB messages at a time. */ 15 | 16 | int main(int argc, char * argv[]) 17 | { 18 | const MPI_Count test_int_max = BigMPI_Get_max_int(); 19 | 20 | MPI_Init(&argc, &argv); 21 | 22 | int rank, size; 23 | MPI_Comm_rank(MPI_COMM_WORLD, &rank); 24 | MPI_Comm_size(MPI_COMM_WORLD, &size); 25 | 26 | int l = (argc > 1) ? atoi(argv[1]) : 2; 27 | int m = (argc > 2) ? atoi(argv[2]) : 17777; 28 | MPI_Count n = l * test_int_max + m; 29 | 30 | double * baseptr = NULL; 31 | MPI_Win win; 32 | MPI_Aint winsize = (rank==0 ? n : 0); 33 | #if MPI_VERSION >= 3 34 | /* Allocate all the window memory on rank 0 */ 35 | MPI_Win_allocate(winsize, sizeof(double), MPI_INFO_NULL, MPI_COMM_WORLD, &baseptr, &win); 36 | MPI_Win_lock_all(0, win); 37 | #else 38 | MPI_Alloc_mem(winsize*sizeof(double), MPI_INFO_NULL, &baseptr); 39 | MPI_Win_create(baseptr, size, sizeof(double), MPI_INFO_NULL, MPI_COMM_WORLD, &win); 40 | #endif 41 | 42 | if (rank==0) { 43 | for (size_t i=0; i<(n/sizeof(double)); i++) { 44 | baseptr[i] = 0.0; 45 | } 46 | #if MPI_VERSION >= 3 47 | MPI_Win_sync(win); 48 | #endif 49 | } 50 | MPI_Barrier(MPI_COMM_WORLD); 51 | 52 | double * buf = NULL; 53 | MPI_Alloc_mem((MPI_Aint)n, MPI_INFO_NULL, &buf); 54 | for (size_t i=0; i<(n/sizeof(double)); i++) { 55 | buf[i] = 1.0; 56 | } 57 | 58 | #if MPI_VERSION < 3 59 | MPI_Win_lock(MPI_LOCK_EXCLUSIVE, 0 /* target */, 0 /* assert */, win); 60 | #endif 61 | MPIX_Accumulate_x(buf, n/sizeof(double), MPI_DOUBLE, 62 | 0 /* target */, 0 /* disp */, n/sizeof(double), MPI_DOUBLE, MPI_SUM, win); 63 | #if MPI_VERSION >= 3 64 | MPI_Win_flush(0,win); 65 | #else 66 | MPI_Win_unlock(0,win); 67 | #endif 68 | 69 | MPI_Barrier(MPI_COMM_WORLD); 70 | 71 | if (rank==0) { 72 | #if MPI_VERSION >= 3 73 | MPI_Win_sync(win); 74 | #endif 75 | double expected = size; 76 | size_t errors = verify_doubles(baseptr, n/sizeof(double), expected); 77 | if (errors > 0) { 78 | printf("There were %zu errors!", errors); 79 | for (size_t i=0; i<(n/(sizeof(double))); i++) { 80 | printf("baseptr[%zu] = %lf (expected %lf)\n", i, baseptr[i], expected); 81 | } 82 | } 83 | if (errors==0) { 84 | printf("SUCCESS\n"); 85 | } 86 | } 87 | 88 | #if MPI_VERSION >= 3 89 | MPI_Win_unlock_all(win); 90 | #endif 91 | MPI_Win_free(&win); 92 | #if MPI_VERSION < 3 93 | MPI_Free_mem(baseptr); 94 | #endif 95 | 96 | MPI_Finalize(); 97 | 98 | return 0; 99 | } 100 | -------------------------------------------------------------------------------- /util/BigMPI/test/test_rsend_recv_x.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | 7 | #include 8 | #include "bigmpi.h" 9 | #include "verify_buffer.h" 10 | 11 | /* Yes, it is technically unsafe to cast MPI_Count to MPI_Aint or size_t without checking, 12 | * given that MPI_Count might be 128b and MPI_Aint and size_t might be 64b, but BigMPI 13 | * does not aspire to support communication of more than 8 EiB messages at a time. */ 14 | 15 | int main(int argc, char * argv[]) 16 | { 17 | MPI_Init(&argc, &argv); 18 | 19 | int rank, size; 20 | MPI_Comm_rank(MPI_COMM_WORLD, &rank); 21 | MPI_Comm_size(MPI_COMM_WORLD, &size); 22 | 23 | const MPI_Count test_int_max = BigMPI_Get_max_int(); 24 | 25 | if (size<2) { 26 | printf("Use 2 or more processes. \n"); 27 | MPI_Finalize(); 28 | return 1; 29 | } 30 | 31 | int l = (argc > 1) ? atoi(argv[1]) : 2; 32 | int m = (argc > 2) ? atoi(argv[2]) : 17777; 33 | MPI_Count n = l * test_int_max + m; 34 | 35 | char * buf = NULL; 36 | 37 | MPI_Alloc_mem((MPI_Aint)n, MPI_INFO_NULL, &buf); 38 | 39 | memset(buf, rank, (size_t)n); 40 | 41 | size_t errors = 0; 42 | for (int r = 1; r < size; r++) { 43 | 44 | /* pairwise communication */ 45 | if (rank==r) { 46 | MPIX_Rsend_x(buf, n, MPI_CHAR, 0 /* dst */, r /* tag */, MPI_COMM_WORLD); 47 | } 48 | else if (rank==0) { 49 | MPIX_Recv_x(buf, n, MPI_CHAR, r /* src */, r /* tag */, MPI_COMM_WORLD, MPI_STATUS_IGNORE); 50 | 51 | errors += verify_buffer(buf, n, r); 52 | if (errors > 0) { 53 | printf("There were %zu errors!", errors); 54 | } 55 | } 56 | } 57 | 58 | MPI_Free_mem(buf); 59 | 60 | if (rank==0 && errors==0) { 61 | printf("SUCCESS\n"); 62 | } 63 | 64 | MPI_Finalize(); 65 | 66 | return 0; 67 | } 68 | -------------------------------------------------------------------------------- /util/BigMPI/test/test_scatter_x.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | 8 | #include 9 | #include "bigmpi.h" 10 | #include "verify_buffer.h" 11 | 12 | /* Yes, it is technically unsafe to cast MPI_Count to MPI_Aint or size_t without checking, 13 | * given that MPI_Count might be 128b and MPI_Aint and size_t might be 64b, but BigMPI 14 | * does not aspire to support communication of more than 8 EiB messages at a time. */ 15 | 16 | int main(int argc, char * argv[]) 17 | { 18 | const MPI_Count test_int_max = BigMPI_Get_max_int(); 19 | 20 | MPI_Init(&argc, &argv); 21 | 22 | int rank, size; 23 | MPI_Comm_rank(MPI_COMM_WORLD, &rank); 24 | MPI_Comm_size(MPI_COMM_WORLD, &size); 25 | 26 | if (size<1) { 27 | printf("Use 1 or more processes. \n"); 28 | MPI_Finalize(); 29 | return 1; 30 | } 31 | 32 | int l = (argc > 1) ? atoi(argv[1]) : 2; 33 | int m = (argc > 2) ? atoi(argv[2]) : 17777; 34 | MPI_Count n = l * test_int_max + m; 35 | 36 | char * buf_send = NULL; 37 | char * buf_recv = NULL; 38 | 39 | MPI_Alloc_mem((MPI_Aint)n * size, MPI_INFO_NULL, &buf_send); 40 | assert(buf_send!=NULL); 41 | MPI_Alloc_mem((MPI_Aint)n, MPI_INFO_NULL, &buf_recv); 42 | assert(buf_recv!=NULL); 43 | 44 | if (rank==0) { 45 | for (int i = 0; i < size; ++i) { 46 | for (MPI_Count j = 0; j < n; ++j) { 47 | buf_send[i*n+j] = (unsigned char)i; 48 | } 49 | } 50 | } 51 | memset(buf_recv, -1, (size_t)n); 52 | 53 | /* collective communication */ 54 | MPIX_Scatter_x(buf_send, n, MPI_CHAR, 55 | buf_recv, n, MPI_CHAR, 56 | 0 /* root */, MPI_COMM_WORLD); 57 | 58 | size_t errors = verify_buffer(buf_recv, n, rank); 59 | 60 | MPI_Free_mem(buf_send); 61 | MPI_Free_mem(buf_recv); 62 | 63 | if (rank==0 && errors==0) { 64 | printf("SUCCESS\n"); 65 | } 66 | 67 | MPI_Finalize(); 68 | 69 | return 0; 70 | } 71 | -------------------------------------------------------------------------------- /util/BigMPI/test/test_send_recv_x.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | 7 | #include 8 | #include "bigmpi.h" 9 | #include "verify_buffer.h" 10 | 11 | /* Yes, it is technically unsafe to cast MPI_Count to MPI_Aint or size_t without checking, 12 | * given that MPI_Count might be 128b and MPI_Aint and size_t might be 64b, but BigMPI 13 | * does not aspire to support communication of more than 8 EiB messages at a time. */ 14 | 15 | int main(int argc, char * argv[]) 16 | { 17 | MPI_Init(&argc, &argv); 18 | 19 | int rank, size; 20 | MPI_Comm_rank(MPI_COMM_WORLD, &rank); 21 | MPI_Comm_size(MPI_COMM_WORLD, &size); 22 | 23 | const MPI_Count test_int_max = BigMPI_Get_max_int(); 24 | 25 | if (size<2) { 26 | printf("Use 2 or more processes. \n"); 27 | MPI_Finalize(); 28 | return 1; 29 | } 30 | 31 | int l = (argc > 1) ? atoi(argv[1]) : 2; 32 | int m = (argc > 2) ? atoi(argv[2]) : 17777; 33 | MPI_Count n = l * test_int_max + m; 34 | 35 | char * buf = NULL; 36 | 37 | MPI_Alloc_mem((MPI_Aint)n, MPI_INFO_NULL, &buf); 38 | 39 | memset(buf, rank, (size_t)n); 40 | 41 | size_t errors = 0; 42 | for (int r = 1; r < size; r++) { 43 | 44 | /* pairwise communication */ 45 | if (rank==r) { 46 | MPIX_Send_x(buf, n, MPI_CHAR, 0 /* dst */, r /* tag */, MPI_COMM_WORLD); 47 | } 48 | else if (rank==0) { 49 | MPIX_Recv_x(buf, n, MPI_CHAR, r /* src */, r /* tag */, MPI_COMM_WORLD, MPI_STATUS_IGNORE); 50 | 51 | errors += verify_buffer(buf, n, r); 52 | if (errors > 0) { 53 | printf("There were %zu errors!", errors); 54 | } 55 | } 56 | } 57 | 58 | MPI_Free_mem(buf); 59 | 60 | if (rank==0 && errors==0) { 61 | printf("SUCCESS\n"); 62 | } 63 | 64 | MPI_Finalize(); 65 | 66 | return 0; 67 | } 68 | -------------------------------------------------------------------------------- /util/BigMPI/test/test_sendrecv_x.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | 7 | #include 8 | #include "bigmpi.h" 9 | #include "verify_buffer.h" 10 | 11 | /* Yes, it is technically unsafe to cast MPI_Count to MPI_Aint or size_t without checking, 12 | * given that MPI_Count might be 128b and MPI_Aint and size_t might be 64b, but BigMPI 13 | * does not aspire to support communication of more than 8 EiB messages at a time. */ 14 | 15 | int main(int argc, char * argv[]) 16 | { 17 | MPI_Init(&argc, &argv); 18 | 19 | int rank, size; 20 | MPI_Comm_rank(MPI_COMM_WORLD, &rank); 21 | MPI_Comm_size(MPI_COMM_WORLD, &size); 22 | 23 | const MPI_Count test_int_max = BigMPI_Get_max_int(); 24 | 25 | if (size<2) { 26 | printf("Use 2 or more processes. \n"); 27 | MPI_Finalize(); 28 | return 1; 29 | } 30 | 31 | int l = (argc > 1) ? atoi(argv[1]) : 2; 32 | int m = (argc > 2) ? atoi(argv[2]) : 17777; 33 | MPI_Count n = l * test_int_max + m; 34 | 35 | char * buf_send = NULL; 36 | char * buf_recv = NULL; 37 | 38 | MPI_Alloc_mem((MPI_Aint)n, MPI_INFO_NULL, &buf_send); 39 | MPI_Alloc_mem((MPI_Aint)n, MPI_INFO_NULL, &buf_recv); 40 | 41 | memset(buf_send, rank, (size_t)n); 42 | memset(buf_recv, rank, (size_t)n); 43 | 44 | size_t errors = 0; 45 | 46 | for (int r = 1; r < size; r++) { 47 | 48 | /* pairwise communication */ 49 | if (rank==r) { 50 | MPIX_Sendrecv_x(buf_send, n, MPI_CHAR, 0 /* dst */, r /* tag */, 51 | buf_recv, n, MPI_CHAR, 0 /* src */, r /* tag */, 52 | MPI_COMM_WORLD, MPI_STATUS_IGNORE); 53 | 54 | errors = verify_buffer(buf_recv, n, 0); 55 | if (errors > 0) { 56 | printf("There were %zu errors!\n", errors); 57 | for (size_t i=0; i<(size_t)n; i++) { 58 | printf("buf_recv[%zu] = %d (expected %d)\n", i, buf_recv[i], r); 59 | } 60 | } 61 | } 62 | else if (rank==0) { 63 | MPIX_Sendrecv_x(buf_send, n, MPI_CHAR, r /* dst */, r /* tag */, 64 | buf_recv, n, MPI_CHAR, r /* src */, r /* tag */, 65 | MPI_COMM_WORLD, MPI_STATUS_IGNORE); 66 | 67 | errors = verify_buffer(buf_recv, n, r); 68 | if (errors > 0) { 69 | printf("There were %zu errors!\n", errors); 70 | for (size_t i=0; i<(size_t)n; i++) { 71 | printf("buf_recv[%zu] = %d (expected %d)\n", i, buf_recv[i], r); 72 | } 73 | } 74 | } 75 | } 76 | 77 | MPI_Free_mem(buf_send); 78 | MPI_Free_mem(buf_recv); 79 | 80 | if (rank==0 && errors==0) { 81 | printf("SUCCESS\n"); 82 | } 83 | 84 | MPI_Finalize(); 85 | 86 | return 0; 87 | } 88 | -------------------------------------------------------------------------------- /util/BigMPI/test/test_ssend_recv_x.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | 7 | #include 8 | #include "bigmpi.h" 9 | #include "verify_buffer.h" 10 | 11 | /* Yes, it is technically unsafe to cast MPI_Count to MPI_Aint or size_t without checking, 12 | * given that MPI_Count might be 128b and MPI_Aint and size_t might be 64b, but BigMPI 13 | * does not aspire to support communication of more than 8 EiB messages at a time. */ 14 | 15 | int main(int argc, char * argv[]) 16 | { 17 | MPI_Init(&argc, &argv); 18 | 19 | int rank, size; 20 | MPI_Comm_rank(MPI_COMM_WORLD, &rank); 21 | MPI_Comm_size(MPI_COMM_WORLD, &size); 22 | 23 | const MPI_Count test_int_max = BigMPI_Get_max_int(); 24 | 25 | if (size<2) { 26 | printf("Use 2 or more processes. \n"); 27 | MPI_Finalize(); 28 | return 1; 29 | } 30 | 31 | int l = (argc > 1) ? atoi(argv[1]) : 2; 32 | int m = (argc > 2) ? atoi(argv[2]) : 17777; 33 | MPI_Count n = l * test_int_max + m; 34 | 35 | char * buf = NULL; 36 | 37 | MPI_Alloc_mem((MPI_Aint)n, MPI_INFO_NULL, &buf); 38 | 39 | memset(buf, rank, (size_t)n); 40 | 41 | size_t errors = 0; 42 | for (int r = 1; r < size; r++) { 43 | 44 | /* pairwise communication */ 45 | if (rank==r) { 46 | MPIX_Ssend_x(buf, n, MPI_CHAR, 0 /* dst */, r /* tag */, MPI_COMM_WORLD); 47 | } 48 | else if (rank==0) { 49 | MPIX_Recv_x(buf, n, MPI_CHAR, r /* src */, r /* tag */, MPI_COMM_WORLD, MPI_STATUS_IGNORE); 50 | 51 | errors += verify_buffer(buf, n, r); 52 | if (errors > 0) { 53 | printf("There were %zu errors!", errors); 54 | } 55 | } 56 | } 57 | 58 | MPI_Free_mem(buf); 59 | 60 | if (rank==0 && errors==0) { 61 | printf("SUCCESS\n"); 62 | } 63 | 64 | MPI_Finalize(); 65 | 66 | return 0; 67 | } 68 | -------------------------------------------------------------------------------- /util/BigMPI/test/verify_buffer.h: -------------------------------------------------------------------------------- 1 | #ifndef VERIFY_BUFFER_H 2 | #define VERIFY_BUFFER_H 3 | 4 | #include 5 | #include 6 | #include 7 | #include 8 | 9 | #include 10 | 11 | /* This is the generic buffer verification for when char is the 12 | * type and we use memset for assignment. */ 13 | static size_t verify_buffer(char *buf, MPI_Count count, int expected_value) 14 | { 15 | assert(count1.e-4) errors++; 32 | } 33 | return errors; 34 | } 35 | 36 | static void set_doubles(double *buf, MPI_Count count, double value) 37 | { 38 | assert(count, and then modified for Julia 4 | 5 | set -e 6 | set -x 7 | 8 | os=`uname` 9 | MPI_IMPL="$1" 10 | 11 | case "$os" in 12 | Darwin) 13 | echo "Mac" 14 | brew update 15 | case "$MPI_IMPL" in 16 | mpich|mpich3) 17 | brew install mpich 18 | ;; 19 | openmpi) 20 | brew install openmpi 21 | ;; 22 | *) 23 | echo "Unknown MPI implementation: $MPI_IMPL" 24 | exit 10 25 | ;; 26 | esac 27 | ;; 28 | 29 | Linux) 30 | echo "Linux" 31 | sudo apt-get update -q 32 | case "$MPI_IMPL" in 33 | mpich1) 34 | sudo apt-get install -q cmake gfortran mpich-shmem-bin libmpich-shmem1.0-dev 35 | ;; 36 | mpich2) 37 | sudo apt-get install -q cmake gfortran mpich2 libmpich2-3 libmpich2-dev 38 | ;; 39 | mpich|mpich3) 40 | sudo apt-get install -q cmake gfortran libcr0 default-jdk 41 | wget -q http://www.cebacad.net/files/mpich/ubuntu/mpich-3.2b3/mpich_3.2b3-1ubuntu_amd64.deb 42 | sudo dpkg -i ./mpich_3.2b3-1ubuntu_amd64.deb 43 | ;; 44 | openmpi) 45 | sudo apt-get install -q cmake gfortran openmpi-bin openmpi-common libopenmpi-dev 46 | ;; 47 | *) 48 | echo "Unknown MPI implementation: $MPI_IMPL" 49 | exit 20 50 | ;; 51 | esac 52 | ;; 53 | esac 54 | -------------------------------------------------------------------------------- /util/BigMPI/travis/install-mpi.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | # This configuration file was taken originally from the mpi4py project 3 | # , and then modified for Julia 4 | 5 | set -e 6 | set -x 7 | 8 | os=`uname` 9 | TRAVIS_ROOT="$1" 10 | MPI_IMPL="$2" 11 | 12 | # this is where updated Autotools will be for Linux 13 | export PATH=$TRAVIS_ROOT/bin:$PATH 14 | 15 | case "$os" in 16 | Darwin) 17 | echo "Mac" 18 | brew update 19 | case "$MPI_IMPL" in 20 | mpich) 21 | brew info mpich 22 | brew install mpich 23 | ;; 24 | openmpi) 25 | brew info open-mpi 26 | brew install openmpi 27 | ;; 28 | *) 29 | echo "Unknown MPI implementation: $MPI_IMPL" 30 | exit 10 31 | ;; 32 | esac 33 | ;; 34 | 35 | Linux) 36 | echo "Linux" 37 | case "$MPI_IMPL" in 38 | mpich) 39 | if [ ! -d "$TRAVIS_ROOT/mpich" ]; then 40 | wget --no-check-certificate http://www.mpich.org/static/downloads/3.2/mpich-3.2.tar.gz 41 | tar -xzf mpich-3.2.tar.gz 42 | cd mpich-3.2 43 | mkdir build && cd build 44 | ../configure CFLAGS="-w" --prefix=$TRAVIS_ROOT/mpich --disable-fortran --disable-static 45 | make -j2 46 | make install 47 | else 48 | echo "MPICH already installed" 49 | fi 50 | ;; 51 | openmpi) 52 | if [ ! -d "$TRAVIS_ROOT/open-mpi" ]; then 53 | wget --no-check-certificate https://www.open-mpi.org/software/ompi/v2.0/downloads/openmpi-2.0.2.tar.bz2 54 | tar -xjf openmpi-2.0.2.tar.bz2 55 | cd openmpi-2.0.2 56 | mkdir build && cd build 57 | ../configure CFLAGS="-w" --prefix=$TRAVIS_ROOT/open-mpi \ 58 | --without-verbs --without-fca --without-mxm --without-ucx \ 59 | --without-portals4 --without-psm --without-psm2 \ 60 | --without-libfabric --without-usnic \ 61 | --without-udreg --without-ugni --without-xpmem \ 62 | --without-alps --without-munge \ 63 | --without-sge --without-loadleveler --without-tm \ 64 | --without-lsf --without-slurm \ 65 | --without-pvfs2 --without-plfs \ 66 | --without-cuda --disable-oshmem \ 67 | --disable-mpi-fortran --disable-oshmem-fortran \ 68 | --disable-libompitrace \ 69 | --disable-static \ 70 | --enable-mpi-thread-multiple 71 | make -j2 72 | make install 73 | else 74 | echo "Open-MPI already installed" 75 | fi 76 | ;; 77 | *) 78 | echo "Unknown MPI implementation: $MPI_IMPL" 79 | exit 20 80 | ;; 81 | esac 82 | ;; 83 | esac 84 | -------------------------------------------------------------------------------- /util/tests/alignedallocator_test.cpp: -------------------------------------------------------------------------------- 1 | // Copyright (C) 2015 Theoretical Physics, ETH Zurich 2 | 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | // FIXME: namespace changed from openqu to iqs 16 | // FIXME: most of the code is not necessary 17 | 18 | /// @file alignedallocator_test.cpp 19 | /// 20 | /// Tests for alignedallocator.hpp 21 | 22 | #include "alignedallocator.hpp" 23 | #include 24 | 25 | int main() 26 | { 27 | // check for a number of repetitions whether alignment is okay 28 | const unsigned repetitions = 1000; 29 | 30 | using Alloc = iqs::AlignedAllocator; 31 | 32 | Alloc alloc; 33 | 34 | Alloc::pointer pointers[repetitions]; 35 | 36 | for (Alloc::pointer& p : pointers) { 37 | p = alloc.allocate(1); 38 | assert((std::size_t)(p) % 64 == 0); 39 | } 40 | 41 | for (Alloc::pointer p : pointers) alloc.deallocate(p, 1); 42 | 43 | return 0; 44 | } 45 | -------------------------------------------------------------------------------- /util/tests/bitops_btest.cpp: -------------------------------------------------------------------------------- 1 | // Copyright (C) 2015 Theoretical Physics, ETH Zurich 2 | 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | // FIXME: namespace changed from openqu to iqs 16 | // FIXME: most of the code is not necessary 17 | 18 | /// @file bitops_test.cpp 19 | /// 20 | /// Tests for bitops.hpp using Boost.Test 21 | 22 | #if 0 23 | #define BOOST_TEST_DYN_LINK 24 | #define BOOST_TEST_MODULE SImUtilBitops 25 | #include 26 | 27 | #include 28 | #include "bitops.hpp" 29 | 30 | BOOST_AUTO_TEST_CASE(highestBit) 31 | { 32 | BOOST_CHECK(iqs::highestBit(1) == 0); 33 | BOOST_CHECK(iqs::highestBit(2) == 1); 34 | BOOST_CHECK(iqs::highestBit(3) == 1); 35 | BOOST_CHECK(iqs::highestBit(4) == 2); 36 | BOOST_CHECK(iqs::highestBit(std::numeric_limits::max()) == 30); 37 | BOOST_CHECK(iqs::highestBit(std::numeric_limits::max()) == 31); 38 | } 39 | 40 | BOOST_AUTO_TEST_CASE(isPowerOf2) 41 | { 42 | BOOST_CHECK(!iqs::isPowerOf2(0)); 43 | BOOST_CHECK(iqs::isPowerOf2(1)); 44 | BOOST_CHECK(iqs::isPowerOf2(2)); 45 | BOOST_CHECK(!iqs::isPowerOf2(3)); 46 | BOOST_CHECK(iqs::isPowerOf2(4)); 47 | BOOST_CHECK(!iqs::isPowerOf2(std::numeric_limits::max())); 48 | } 49 | #endif 50 | int main(void) { 51 | return 0; 52 | } 53 | -------------------------------------------------------------------------------- /util/tests/bitops_test.cpp: -------------------------------------------------------------------------------- 1 | // Copyright (C) 2015 Theoretical Physics, ETH Zurich 2 | 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | // FIXME: namespace changed from openqu to iqs 16 | // FIXME: most of the code is not necessary 17 | 18 | /// @file bitops_test.cpp 19 | /// Tests for bitops.hpp 20 | 21 | #include "bitops.hpp" 22 | 23 | #include 24 | #include 25 | 26 | int main() 27 | { 28 | assert(iqs::highestBit(1) == 0); 29 | assert(iqs::highestBit(2) == 1); 30 | assert(iqs::highestBit(3) == 1); 31 | assert(iqs::highestBit(4) == 2); 32 | assert(iqs::highestBit(std::numeric_limits::max()) == 30); 33 | assert(iqs::highestBit(std::numeric_limits::max()) == 31); 34 | 35 | assert(iqs::ilog2(1) == 0); 36 | assert(iqs::ilog2(2) == 1); 37 | assert(iqs::ilog2(4) == 2); 38 | 39 | assert(!iqs::isPowerOf2(0)); 40 | assert(iqs::isPowerOf2(1)); 41 | assert(iqs::isPowerOf2(2)); 42 | assert(!iqs::isPowerOf2(3)); 43 | assert(iqs::isPowerOf2(4)); 44 | assert(!iqs::isPowerOf2(std::numeric_limits::max())); 45 | 46 | return 0; 47 | } 48 | -------------------------------------------------------------------------------- /util/tests/blas_test.cpp: -------------------------------------------------------------------------------- 1 | // Copyright (C) 2015 Theoretical Physics, ETH Zurich 2 | 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | #include 16 | #include 17 | 18 | extern "C" { 19 | double ddot_(const int*, const double*, const int*, const double*, const int*); 20 | } 21 | 22 | int main() 23 | { 24 | std::vector values(2, 1.); 25 | 26 | int N = 2; 27 | int one = 1; 28 | 29 | // double norm = ddot_(&N, &values[0], &one, &values[0], &one); 30 | // std::cout << "Norm: " << norm << std::endl; 31 | return 0; 32 | } 33 | -------------------------------------------------------------------------------- /util/tests/naive_integral_base.cpp: -------------------------------------------------------------------------------- 1 | //------------------------------------------------------------------------------ 2 | // Copyright 2017 Intel Corporation 3 | // 4 | // Licensed under the Apache License, Version 2.0 (the "License"); 5 | // you may not use this file except in compliance with the License. 6 | // You may obtain a copy of the License at 7 | // 8 | // http://www.apache.org/licenses/LICENSE-2.0 9 | // 10 | // Unless required by applicable law or agreed to in writing, software 11 | // distributed under the License is distributed on an "AS IS" BASIS, 12 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | // See the License for the specific language governing permissions and 14 | // limitations under the License. 15 | //------------------------------------------------------------------------------ 16 | 17 | /// @file omp_test1.cpp 18 | /// 19 | /// This file tests creation/destruction of an OMP session. 20 | 21 | #include 22 | #include 23 | 24 | #include "openmp_affinity_corei7.hpp" 25 | 26 | int main(int argc, char **argv) 27 | { 28 | double integral_start = 0.0, 29 | integral_end = 1.0; 30 | unsigned long N = 100000; // number of steps. 31 | 32 | // Compute delta_x of the integral. 33 | double delta_x = (integral_end - integral_start) / (double)N; 34 | double sum = 0.0; 35 | double x; 36 | 37 | // Compute the Riemann sum for the approximate integral. 38 | for(unsigned long i=0;i