A Distributed Quantum Computing emulator for HPC
For a complete and exhaustive explanation and functionality showcase of CUNQA visit the CUNQA documentation.
To get the source code, simply clone the CUNQA repository:
git clone https://github.com/CESGA-Quantum-Spain/cunqa.gitWarning
If SSH cloning fails, you may not have properly linked your environment to GitHub. To do this, run the following commands:
eval "$(ssh-agent -s)"
ssh-add ~/.ssh/SSH_KEYwhere SSH_KEY is the secure key that connects your environment with GitHub, usually stored in the ~/.ssh folder.
Now CUNQA must be built and installed. If you are installing CUNQA in an HPC center other than CESGA, you might need to solve some dependencies or manually define the installation path. If you are installing it in CESGA, the steps in the next dropdown menu can be skipped.
Generic HPC center steps
At build time, CUNQA will look at the STORE environment variable to set the root of the .cunqa folder where configuration and logging files will be stored. If it is not defined in your environment, run:
export STORE=/path/to/your/storeIf you plan to compile CUNQA multiple times, we recommend adding this directive to your .bashrc file to avoid potential issues.
CUNQA has a set of dependencies, as any other platform. The versions listed below are those used during development and are therefore recommended. They are divided into three main groups:
gcc 12.3.0
qiskit 1.2.4
CMake 3.24 (recommended 3.27.6)
python 3.11 (3.11.9 used at CESGA)
pybind11 2.12 (recommended 2.13.6)
MPI 3.1
OpenMP 4.5
Boost 1.85.0
Eigen 5.0.0
CUDA 12.8.0
Cython >= 3.0
Blas -
Lapack -
nlohmann JSON 3.12.0
spdlog 1.16.0
MQT-DDSIM 2.2.0
libzmq 4.3.5
cppzmq 4.11.0
CunqaSimulator 0.1.1
argparse -
qiskit-aer 0.17.2 (modified version)
To build, compile, and install CUNQA, follow the standard three-step CMake workflow:
cmake -B build/ -DCMAKE_INSTALL_PREFIX=/your/installation/path
cmake --build build/ --parallel $(nproc)
cmake --install build/Warning
If CMAKE_INSTALL_PREFIX is not provided, CUNQA will be installed in the directory pointed to by
the HOME environment variable.
Note
To enable GPU execution (only supported by the Aer simulator), configure with -DUSE_GPU=ON. The
target CUDA architecture(s) can optionally be set with -DGPU_ARCH (e.g. 75;80); if omitted, it
defaults to all-major:
cmake -B build/ -DCMAKE_INSTALL_PREFIX=/your/installation/path -DUSE_GPU=ON -DGPU_ARCH="75;80"Equivalently, use the gpu CMake preset:
cmake --preset gpu -DCMAKE_INSTALL_PREFIX=/your/installation/path
cmake --build --preset gpu
cmake --install build/gpuYou can also use Ninja to perform this task:
cmake -G Ninja -B build/ -DCMAKE_INSTALL_PREFIX=/your/installation/path
ninja -C build/ -j $(nproc)
cmake --install build/CUNQA also ships a CMakePresets.json with ready-made dev, release and gpu configurations
(each building into build/<preset>/):
cmake --preset release -DCMAKE_INSTALL_PREFIX=/your/installation/path
cmake --build --preset release
cmake --install build/releaseAlternatively, you can use the configure.sh script, which loads the required modules for the
detected CESGA system (QMIO or FT3) and then configures, builds and installs CUNQA:
source configure.sh /your/installation/pathCUNQA is available as an Lmod module at CESGA. To use it:
-
In QMIO:
module load qmio/hpc gcc/12.3.0 cunqa/3.0.0-python-3.11.9-mpi
-
In FT3:
module load cesga/2022 gcc/system cunqa/3.0.0 # without GPUs module load cesga/2022 gcc/system cunqa/3.0.0-cuda-12.8.0 # with GPUs
Tip
Module names and available versions may change over time. Run module spider cunqa (or
ml av cunqa) to list the exact module strings installed on your system.
If your HPC center is interested in deploying it this way, the EasyBuild files used at CESGA are
available in the easybuild/ folder.
A Make directive is available to uninstall CUNQA if needed:
-
If installed using the standard method:
make uninstall
-
If installed using Ninja:
ninja uninstall
Be sure to execute these commands inside the build/ directory in both cases.
Alternatively, you can run:
cmake --build build/ --target uninstallto abstract from the installation method.
To achieve this, you have two options: a Python–Bash workflow or a Python-only workflow. With the first option, virtual QPUs (vQPUs) can be deployed from the terminal and the employed in the Python executable, while the second allows to deploy, use, and drop the vQPUs within the Python program.
To deploy the vQPUs we use the qraise Bash command.
qraise -n 4 -t 01:00:00 --co-locatedOnce the vQPUs are deployed, we can design and execute quantum tasks:
import os, sys
# Adding path to access CUNQA module
sys.path.append("</your/cunqa/installation/path>")
# Gettting the raised QPUs
from cunqa.qpu import get_QPUs
qpus = get_QPUs(co_located=True)
# Creating a circuit to run in our QPUs
from cunqa.circuit import CunqaCircuit
qc = CunqaCircuit(num_qubits = 2)
qc.h(0)
qc.cx(0,1)
qc.measure_all()
# Submitting the same circuit to all vQPUs
from cunqa.qpu import run
qcs = [qc] * 4
qjobs = run(qcs , qpus, shots = 1000)
# Gathering results
from cunqa.qjob import gather
results = gather(qjobs)
# Getting and printing the counts
counts_list = [result.counts for result in results]
for counts in counts_list:
print(f"Counts: {counts}" ) # Format: {'00':546, '11':454}It is a good practice to relinquish resources when the work is done. This is achieved by the qdrop
command:
qdrop --allHere, the qraise and qdrop steps are integrated into the Python executable.
import os, sys
# Adding path to access CUNQA module
sys.path.append("</your/cunqa/installation/path>")
# Raising the QPUs
from cunqa.qpu import qraise
family = qraise(4, "01:00:00", simulator="Aer", co_located=True)
# Gettting the raised QPUs
from cunqa.qpu import get_QPUs
qpus = get_QPUs(co_located=True)
# Creating a circuit to run in our QPUs
from cunqa.circuit import CunqaCircuit
qc = CunqaCircuit(num_qubits = 2)
qc.h(0)
qc.cx(0,1)
qc.measure_all()
# Submitting the same circuit to all vQPUs
from cunqa.qpu import run
qcs = [qc] * 4
qjobs = run(qcs , qpus, shots = 1000)
# Gathering results
from cunqa.qjob import gather
results = gather(qjobs)
# Getting and printing the counts
counts_list = [result.counts for result in results]
for counts in counts_list:
print(f"Counts: {counts}" ) # Format: {'00':546, '11':454}
# Relinquishing the resources
from cunqa.qpu import qdrop
qdrop(family)This work has been mainly funded by the project QuantumSpain, financed by the Ministerio de Transformación Digital y Función Pública of Spain’s Government through the project call QUANTUM ENIA – Quantum Spain project, and by the European Union through the Plan de Recuperación, Transformación y Resiliencia – NextGenerationEU within the framework of the Agenda España Digital 2026. J. Vázquez-Pérez was supported by the Axencia Galega de Innovación (Xunta de Galicia) through the Programa de axudas á etapa predoutoral (ED481A & IN606A).
Additionally, this research project was made possible through the access granted by the Galician Supercomputing Center (CESGA) to two key parts of its infrastructure. Firstly, its Qmio quantum computing infrastructure with funding from the European Union, through the Operational Programme Galicia 2014-2020 of ERDF_REACT EU, as part of theEuropean Union’s response to the COVID-19 pandemic.
Secondly, The supercomputer FinisTerrae III and its permanent data storage system, which have been funded by the NextGeneration EU 2021 Recovery, Transformation and Resilience Plan, ICT2021-006904, and also from the Pluriregional Operational Programme of Spain 2014-2020 of the European Regional Development Fund (ERDF), ICTS-2019-02-CESGA3, and from the State Programme for the Promotion of Scientific and Technical Research of Excellence of the State Plan for Scientific and Technical Research and Innovation 2013-2016 State subprogramme for scientific and technical infrastructures and equipment of ERDF, CESG15-DE-3114.
When citing the software, please cite the original CUNQA paper:
@misc{vázquezpérez2025cunqadistributedquantumcomputing,
title={CUNQA: a Distributed Quantum Computing emulator for HPC},
author={
Jorge Vázquez-Pérez and
Daniel Expósito-Patiño and
Marta Losada and
Álvaro Carballido and
Andrés Gómez and
Tomás F. Pena},
year={2025},
eprint={2511.05209},
archivePrefix={arXiv},
primaryClass={quant-ph},
url={https://arxiv.org/abs/2511.05209},
}