final first commit
This commit is contained in:
53
qibojit-benchmarks/scripts/README.md
Normal file
53
qibojit-benchmarks/scripts/README.md
Normal file
@@ -0,0 +1,53 @@
|
||||
# Example scripts
|
||||
|
||||
This folder contains example bash scripts that execute the `compare.py` benchmark for different circuit configurations and different libraries.
|
||||
The available circuits are described in the main ``README.md`` of this repository
|
||||
(some of them are presented in Table 1 of the [HyQuas paper](https://dl.acm.org/doi/pdf/10.1145/3447818.3460357)).
|
||||
|
||||
The provided scripts are the following:
|
||||
|
||||
### `qibo.sh`
|
||||
|
||||
Execute a specific circuit with different sizes and different Qibo backends.
|
||||
By default, it executes the circuit with all backends (NumPy, TensorFlow, Qibotf and Qibojit) and with circuit sizes from 3 to 31 (28 for NumPy).
|
||||
If different platforms are available, it will use the default one.
|
||||
It is straightforward to edit the bash script to fine tune the variation ranges and the number of repetitions for each circuit size.
|
||||
A starter code to plot the results is available in ``plots/qibo.ipynb``.
|
||||
Options:
|
||||
- ``circuit``: circuit to execute (default: ``qft``)
|
||||
- ``precision``: ``single`` or ``double`` (default: ``double``)
|
||||
|
||||
### ``qibojit.sh``
|
||||
|
||||
Similar to ``qibo.sh``, but uses only qibojit. Useful to compare the performance across different platforms and different GPUs.
|
||||
A starter code to plot the results is available in ``plots/qibojit.ipynb``.
|
||||
Options:
|
||||
- ``filename``: where to store the logs (default: ``qibojit.dat``)
|
||||
- ``circuit``: circuit to execute (default: ``qft``)
|
||||
- ``precision``: ``single`` or ``double`` (default: ``double``)
|
||||
- ``nreps``: number of repetitions for each circuit size (default: ``10``)
|
||||
- ``platform``: platform to use for simulation (default: ``cupy``)
|
||||
|
||||
### ``qibo_circuits.sh``
|
||||
|
||||
Execute a set of circuits for different circuit sizes, using a specific backend.
|
||||
Useful to plot the breakdown of execution times (starter code in ``plots/qibo.ipynb``).
|
||||
Options:
|
||||
- ``backend``: backend to use for simulation (default: ``qibojit``)
|
||||
- ``precision``: ``single`` or ``double`` (default: ``double``)
|
||||
- ``nreps``: number of repetitions for each circuit and size (default: ``10``)
|
||||
|
||||
### ``library_single.sh``
|
||||
|
||||
Execute a set of circuits for different circuit sizes, using a variety of different libraries.
|
||||
This script focuses on libraries that support single precision simulation.
|
||||
It is straightforward to edit the bash script to change the circuit sizes and the libraries.
|
||||
A starter code to plot the results is available in ``plots/libraries.ipynb``.
|
||||
Options:
|
||||
- ``nreps``: number of repetitions for each circuit size (default: ``10``)
|
||||
|
||||
### ``library_double.sh``
|
||||
|
||||
Same as ``library_single.sh``, but with libraries that support double precision simulation.
|
||||
Options:
|
||||
- ``nreps``: number of repetitions for each circuit size (default: ``10``)
|
||||
1
qibojit-benchmarks/scripts/cu_tensornet_expectation.json
Normal file
1
qibojit-benchmarks/scripts/cu_tensornet_expectation.json
Normal file
@@ -0,0 +1 @@
|
||||
{"MPI_enabled": false, "MPS_enabled": false, "NCCL_enabled": false, "expectation_enabled": true}
|
||||
@@ -0,0 +1 @@
|
||||
{"MPI_enabled": true, "MPS_enabled": false, "NCCL_enabled": false, "expectation_enabled": true}
|
||||
@@ -0,0 +1 @@
|
||||
{"MPI_enabled": false, "MPS_enabled": false, "NCCL_enabled": true, "expectation_enabled": true}
|
||||
33
qibojit-benchmarks/scripts/evolution_dense.sh
Executable file
33
qibojit-benchmarks/scripts/evolution_dense.sh
Executable file
@@ -0,0 +1,33 @@
|
||||
#! /usr/bin/bash
|
||||
# Generates data for the evolution scaling with dt using the dense form of the Hamiltonian
|
||||
|
||||
# Command-line parameters
|
||||
: "${nqubits:=10}"
|
||||
: "${precision:=double}"
|
||||
: "${filename:=evolution.dat}"
|
||||
: "${nreps:=5}"
|
||||
|
||||
|
||||
# GPU backends
|
||||
for dt in 0.1 0.095 0.09 0.085 0.08 0.075 0.07 0.065 0.06 0.055 0.05 0.045 \
|
||||
0.04 0.035 0.03 0.025 0.02 0.015 0.01 0.005
|
||||
do
|
||||
for backend in qibojit tensorflow
|
||||
do
|
||||
CUDA_VISIBLE_DEVICES=0 python evolution.py --nqubits $nqubits --dt $dt --filename $filename --nreps $nreps \
|
||||
--backend $backend --precision $precision --dense
|
||||
echo
|
||||
done
|
||||
done
|
||||
|
||||
# CPU backends
|
||||
for dt in 0.1 0.095 0.09 0.085 0.08 0.075 0.07 0.065 0.06 0.055 0.05 0.045 \
|
||||
0.04 0.035 0.03 0.025 0.02 0.015 0.01 0.005
|
||||
do
|
||||
for backend in numpy tensorflow
|
||||
do
|
||||
CUDA_VISIBLE_DEVICES="" python evolution.py --nqubits $nqubits --dt $dt --filename $filename --nreps $nreps \
|
||||
--backend $backend --precision $precision --dense
|
||||
echo
|
||||
done
|
||||
done
|
||||
45
qibojit-benchmarks/scripts/evolution_trotter.sh
Executable file
45
qibojit-benchmarks/scripts/evolution_trotter.sh
Executable file
@@ -0,0 +1,45 @@
|
||||
#! /usr/bin/bash
|
||||
# Generates data for the evolution scaling with dt using the Trotter decomposition
|
||||
|
||||
# Command-line parameters
|
||||
: "${nqubits:=10}"
|
||||
: "${precision:=double}"
|
||||
: "${filename:=evolution.dat}"
|
||||
: "${nreps:=10}"
|
||||
|
||||
|
||||
# GPU qibojit backend
|
||||
for dt in 0.1 0.095 0.09 0.085 0.08 0.075 0.07 0.065 0.06 0.055 0.05 0.045 \
|
||||
0.04 0.035 0.03 0.025 0.02 0.015 0.01 0.005
|
||||
do
|
||||
for platform in cupy cuquantum
|
||||
do
|
||||
CUDA_VISIBLE_DEVICES="0" python evolution.py --nqubits $nqubits --dt $dt --filename $filename --nreps $nreps \
|
||||
--backend qibojit --platform $platform --precision $precision
|
||||
echo
|
||||
done
|
||||
done
|
||||
|
||||
# GPU tensorflow and qibotf backends
|
||||
for dt in 0.1 0.095 0.09 0.085 0.08 0.075 0.07 0.065 0.06 0.055 0.05 0.045 \
|
||||
0.04 0.035 0.03 0.025 0.02 0.015 0.01 0.005
|
||||
do
|
||||
for backend in qibotf tensorflow
|
||||
do
|
||||
CUDA_VISIBLE_DEVICES="0" python evolution.py --nqubits $nqubits --dt $dt --filename $filename --nreps $nreps \
|
||||
--backend $backend --precision $precision
|
||||
echo
|
||||
done
|
||||
done
|
||||
|
||||
# CPU all backends
|
||||
for dt in 0.1 0.095 0.09 0.085 0.08 0.075 0.07 0.065 0.06 0.055 0.05 0.045 \
|
||||
0.04 0.035 0.03 0.025 0.02 0.015 0.01 0.005
|
||||
do
|
||||
for backend in qibojit qibotf tensorflow numpy
|
||||
do
|
||||
CUDA_VISIBLE_DEVICES="" python evolution.py --nqubits $nqubits --dt $dt --filename $filename --nreps $nreps \
|
||||
--backend $backend --precision $precision
|
||||
echo
|
||||
done
|
||||
done
|
||||
34
qibojit-benchmarks/scripts/fusion.sh
Executable file
34
qibojit-benchmarks/scripts/fusion.sh
Executable file
@@ -0,0 +1,34 @@
|
||||
#! /usr/bin/bash
|
||||
# Generate logs for fusion comparison on different circuits for all qibojit platforms
|
||||
|
||||
# Command-line parameters
|
||||
: "${filename:=qibojit_fusion.dat}"
|
||||
: "${precision:=double}"
|
||||
: "${nqubits:=30}"
|
||||
: "${nreps_cpu:=3}"
|
||||
: "${nreps_gpu:=5}"
|
||||
|
||||
|
||||
for circuit in qft variational supremacy bv qv
|
||||
do
|
||||
CUDA_VISIBLE_DEVICES=0 python compare.py --circuit $circuit --nqubits $nqubits --filename $filename \
|
||||
--library-options backend=qibojit,platform=cupy,max_qubits=2 --nreps $nreps_gpu --precision $precision
|
||||
echo
|
||||
CUDA_VISIBLE_DEVICES=0 python compare.py --circuit $circuit --nqubits $nqubits --filename $filename \
|
||||
--library-options backend=qibojit,platform=cupy --nreps $nreps_gpu --precision $precision
|
||||
echo
|
||||
|
||||
CUDA_VISIBLE_DEVICES=0 python compare.py --circuit $circuit --nqubits $nqubits --filename $filename \
|
||||
--library-options backend=qibojit,platform=cuquantum,max_qubits=2 --nreps $nreps_gpu --precision $precision
|
||||
echo
|
||||
CUDA_VISIBLE_DEVICES=0 python compare.py --circuit $circuit --nqubits $nqubits --filename $filename \
|
||||
--library-options backend=qibojit,platform=cuquantum --nreps $nreps_gpu --precision $precision
|
||||
echo
|
||||
|
||||
CUDA_VISIBLE_DEVICES="" python compare.py --circuit $circuit --nqubits $nqubits --filename $filename \
|
||||
--library-options backend=qibojit,platform=numba,max_qubits=2 --nreps $nreps_cpu --precision $precision
|
||||
echo
|
||||
CUDA_VISIBLE_DEVICES="" python compare.py --circuit $circuit --nqubits $nqubits --filename $filename \
|
||||
--library-options backend=qibojit,platform=numba --nreps $nreps_cpu --precision $precision
|
||||
echo
|
||||
done
|
||||
24
qibojit-benchmarks/scripts/libraries_double.sh
Executable file
24
qibojit-benchmarks/scripts/libraries_double.sh
Executable file
@@ -0,0 +1,24 @@
|
||||
#! /usr/bin/bash
|
||||
# Generates data for the bar plot comparing different libraries in double precision
|
||||
|
||||
: "${nreps:=10}"
|
||||
: "${nqubits:=10}"
|
||||
: "${filename_cpu:=libraries_cpu.dat}"
|
||||
: "${filename_gpu:=libraries_gpu.dat}"
|
||||
|
||||
|
||||
for circuit in qft variational bv supremacy qv
|
||||
do
|
||||
for library in qibo qiskit qulacs projectq hybridq
|
||||
do
|
||||
CUDA_VISIBLE_DEVICES="" python compare.py --circuit $circuit --nqubits $nqubits --filename $filename_cpu \
|
||||
--library $library --nreps $nreps --precision double
|
||||
echo
|
||||
done
|
||||
for library in qibo qiskit-gpu qulacs-gpu hybridq-gpu
|
||||
do
|
||||
CUDA_VISIBLE_DEVICES=0 python compare.py --circuit $circuit --nqubits $nqubits --filename $filename_gpu \
|
||||
--library $library --nreps $nreps --precision double
|
||||
echo
|
||||
done
|
||||
done
|
||||
42
qibojit-benchmarks/scripts/libraries_fusion.sh
Executable file
42
qibojit-benchmarks/scripts/libraries_fusion.sh
Executable file
@@ -0,0 +1,42 @@
|
||||
#! /usr/bin/bash
|
||||
# Generate logs for library comparison on different circuits with gate fusion enabled
|
||||
|
||||
# Command-line parameters
|
||||
: "${filename_cpu:=libraries_fusion_cpu.dat}"
|
||||
: "${filename_gpu:=libraries_fusion_gpu.dat}"
|
||||
: "${precision:=single}"
|
||||
: "${nqubits:=30}"
|
||||
: "${nreps_cpu:=3}"
|
||||
: "${nreps_gpu:=5}"
|
||||
|
||||
|
||||
for circuit in qft variational supremacy bv qv
|
||||
do
|
||||
# GPU benchmarks
|
||||
CUDA_VISIBLE_DEVICES=0 python compare.py --circuit $circuit --nqubits $nqubits --filename $filename_gpu --library qibo \
|
||||
--library-options backend=qibojit,platform=cupy,max_qubits=2 --nreps $nreps_gpu --precision $precision
|
||||
echo
|
||||
CUDA_VISIBLE_DEVICES=0 python compare.py --circuit $circuit --nqubits $nqubits --filename $filename_gpu --library qibo \
|
||||
--library-options backend=qibojit,platform=cuquantum,max_qubits=2 --nreps $nreps_gpu --precision $precision
|
||||
echo
|
||||
CUDA_VISIBLE_DEVICES=0 python compare.py --circuit $circuit --nqubits $nqubits --filename $filename_gpu --library qsim-gpu \
|
||||
--library-options max_qubits=2 --nreps $nreps_gpu --precision $precision
|
||||
echo
|
||||
CUDA_VISIBLE_DEVICES=0 python compare.py --circuit $circuit --nqubits $nqubits --filename $filename_gpu --library qsim-cuquantum \
|
||||
--library-options max_qubits=2 --nreps $nreps_gpu --precision $precision
|
||||
echo
|
||||
CUDA_VISIBLE_DEVICES=0 python compare.py --circuit $circuit --nqubits $nqubits --filename $filename_gpu --library qiskit-gpu \
|
||||
--library-options max_qubits=2 --nreps $nreps_gpu --precision $precision
|
||||
echo
|
||||
|
||||
# CPU benchmarks
|
||||
CUDA_VISIBLE_DEVICES="" python compare.py --circuit $circuit --nqubits $nqubits --filename $filename_cpu --library qibo \
|
||||
--library-options backend=qibojit,platform=numba,max_qubits=2 --nreps $nreps_cpu --precision $precision
|
||||
echo
|
||||
CUDA_VISIBLE_DEVICES="" python compare.py --circuit $circuit --nqubits $nqubits --filename $filename_cpu --library qsim \
|
||||
--library-options max_qubits=2 --nreps $nreps_cpu --precision $precision
|
||||
echo
|
||||
CUDA_VISIBLE_DEVICES="" python compare.py --circuit $circuit --nqubits $nqubits --filename $filename_cpu --library qiskit \
|
||||
--library-options max_qubits=2 --nreps $nreps_cpu --precision $precision
|
||||
echo
|
||||
done
|
||||
24
qibojit-benchmarks/scripts/libraries_single.sh
Executable file
24
qibojit-benchmarks/scripts/libraries_single.sh
Executable file
@@ -0,0 +1,24 @@
|
||||
#! /usr/bin/bash
|
||||
# Generates data for the bar plot comparing different libraries in single precision
|
||||
|
||||
: "${nreps:=10}"
|
||||
: "${nqubits:=20}"
|
||||
: "${filename_cpu:=libraries_cpu.dat}"
|
||||
: "${filename_gpu:=libraries_gpu.dat}"
|
||||
|
||||
|
||||
for circuit in qft variational bv supremacy qv
|
||||
do
|
||||
for library in qibo qiskit qsim hybridq
|
||||
do
|
||||
CUDA_VISIBLE_DEVICES="" python compare.py --circuit $circuit --nqubits $nqubits --filename $filename_cpu \
|
||||
--library $library --nreps $nreps --precision single
|
||||
echo
|
||||
done
|
||||
for library in qibo qiskit-gpu qsim-gpu qsim-cuquantum qcgpu hybridq-gpu
|
||||
do
|
||||
CUDA_VISIBLE_DEVICES=0 python compare.py --circuit $circuit --nqubits $nqubits --filename $filename_gpu \
|
||||
--library $library --nreps $nreps --precision single
|
||||
echo
|
||||
done
|
||||
done
|
||||
34
qibojit-benchmarks/scripts/multigpu.sh
Executable file
34
qibojit-benchmarks/scripts/multigpu.sh
Executable file
@@ -0,0 +1,34 @@
|
||||
# Generates the multigpu bar plot
|
||||
# Assumes a machine with four GPUs
|
||||
|
||||
: "${filename:=multigpu.dat}"
|
||||
: "${precision:=double}"
|
||||
: "${nreps:=1}"
|
||||
|
||||
export CUDA_VISIBLE_DEVICES=0,1,2,3
|
||||
for circuit in qft variational supremacy qv bv
|
||||
do
|
||||
for backend in qibojit qibotf
|
||||
do
|
||||
python compare.py --circuit $circuit --nqubits 32 --filename $filename \
|
||||
--library-options backend=$backend,accelerators=1/GPU:0+1/GPU:1+1/GPU:2+1/GPU:3 \
|
||||
--nreps $nreps --precision $precision
|
||||
echo
|
||||
done
|
||||
|
||||
for backend in qibojit qibotf
|
||||
do
|
||||
python compare.py --circuit $circuit --nqubits 32 --filename $filename \
|
||||
--library-options backend=$backend,accelerators=2/GPU:2+2/GPU:3 \
|
||||
--nreps $nreps --precision $precision
|
||||
echo
|
||||
done
|
||||
|
||||
for backend in qibojit qibotf
|
||||
do
|
||||
python compare.py --circuit $circuit --nqubits 32 --filename $filename \
|
||||
--library-options backend=$backend,accelerators=4/GPU:3 \
|
||||
--nreps $nreps --precision $precision
|
||||
echo
|
||||
done
|
||||
done
|
||||
85
qibojit-benchmarks/scripts/qibo.sh
Executable file
85
qibojit-benchmarks/scripts/qibo.sh
Executable file
@@ -0,0 +1,85 @@
|
||||
#! /usr/bin/bash
|
||||
# Generates data for the scaling plot (vs nqubits) using all qibo backends
|
||||
|
||||
# Command-line parameters
|
||||
: "${circuit:=qft}"
|
||||
: "${precision:=double}"
|
||||
: "${nreps_a:=20}" # for nqubits < 25
|
||||
: "${nreps_b:=3}" # for nqubits >= 25
|
||||
: "${filename_cpu:=qibo_scaling_cpu.dat}"
|
||||
: "${filename_gpu:=qibo_scaling_gpu.dat}"
|
||||
|
||||
|
||||
# Qibojit backend
|
||||
for nqubits in {3..24}
|
||||
do
|
||||
CUDA_VISIBLE_DEVICES=0 python compare.py --circuit $circuit --nqubits $nqubits --filename $filename_gpu \
|
||||
--library-options backend=qibojit,platform=cupy \
|
||||
--nreps $nreps_a --precision $precision
|
||||
echo
|
||||
CUDA_VISIBLE_DEVICES=0 python compare.py --circuit $circuit --nqubits $nqubits --filename $filename_gpu \
|
||||
--library-options backend=qibojit,platform=cuquantum \
|
||||
--nreps $nreps_a --precision $precision
|
||||
echo
|
||||
CUDA_VISIBLE_DEVICES="" python compare.py --circuit $circuit --nqubits $nqubits --filename $filename_cpu \
|
||||
--library-options backend=qibojit,platform=numba \
|
||||
--nreps $nreps_a --precision $precision
|
||||
echo
|
||||
done
|
||||
for nqubits in {25..31}
|
||||
do
|
||||
CUDA_VISIBLE_DEVICES=0 python compare.py --circuit $circuit --nqubits $nqubits --filename $filename_gpu \
|
||||
--library-options backend=qibojit,platform=cupy \
|
||||
--nreps $nreps_b --precision $precision
|
||||
echo
|
||||
CUDA_VISIBLE_DEVICES=0 python compare.py --circuit $circuit --nqubits $nqubits --filename $filename_gpu \
|
||||
--library-options backend=qibojit,platform=cuquantum \
|
||||
--nreps $nreps_b --precision $precision
|
||||
echo
|
||||
CUDA_VISIBLE_DEVICES="" python compare.py --circuit $circuit --nqubits $nqubits --filename $filename_cpu \
|
||||
--library-options backend=qibojit,platform=numba \
|
||||
--nreps $nreps_b --precision $precision
|
||||
echo
|
||||
done
|
||||
|
||||
|
||||
# TensorFlow and QiboTF backends
|
||||
for nqubits in {3..24}
|
||||
do
|
||||
for backend in tensorflow qibotf
|
||||
do
|
||||
CUDA_VISIBLE_DEVICES=0 python compare.py --circuit $circuit --nqubits $nqubits --filename $filename_gpu \
|
||||
--library-options backend=$backend --nreps $nreps_a --precision $precision
|
||||
echo
|
||||
CUDA_VISIBLE_DEVICES="" python compare.py --circuit $circuit --nqubits $nqubits --filename $filename_cpu \
|
||||
--library-options backend=$backend --nreps $nreps_a --precision $precision
|
||||
echo
|
||||
done
|
||||
done
|
||||
for nqubits in {25..31}
|
||||
do
|
||||
for backend in tensorflow qibotf
|
||||
do
|
||||
CUDA_VISIBLE_DEVICES=0 python compare.py --circuit $circuit --nqubits $nqubits --filename $filename_gpu \
|
||||
--library-options backend=$backend --nreps $nreps_b --precision $precision
|
||||
echo
|
||||
CUDA_VISIBLE_DEVICES="" python compare.py --circuit $circuit --nqubits $nqubits --filename $filename_cpu \
|
||||
--library-options backend=$backend --nreps $nreps_b --precision $precision
|
||||
echo
|
||||
done
|
||||
done
|
||||
|
||||
|
||||
# NumPy backend
|
||||
for nqubits in {3..24}
|
||||
do
|
||||
CUDA_VISIBLE_DEVICES="" python compare.py --circuit $circuit --nqubits $nqubits --filename $filename_cpu \
|
||||
--library-options backend=numpy --nreps $nreps_a --precision $precision
|
||||
echo
|
||||
done
|
||||
for nqubits in {25..28}
|
||||
do
|
||||
CUDA_VISIBLE_DEVICES="" python compare.py --circuit $circuit --nqubits $nqubits --filename $filename_cpu \
|
||||
--library-options backend=numpy --nreps $nreps_b --precision $precision
|
||||
echo
|
||||
done
|
||||
23
qibojit-benchmarks/scripts/qibojit.sh
Executable file
23
qibojit-benchmarks/scripts/qibojit.sh
Executable file
@@ -0,0 +1,23 @@
|
||||
#! /usr/bin/bash
|
||||
# Generates data for qibojit breakdown bar plot with dry run vs simulation
|
||||
|
||||
# Command-line parameters
|
||||
: "${filename:=qibojit_breakdown.dat}"
|
||||
: "${precision:=double}"
|
||||
: "${circuit:=supremacy}"
|
||||
: "${nreps_cpu:=5}"
|
||||
: "${nreps_gpu:=10}"
|
||||
|
||||
|
||||
for nqubits in 16 18 20 22 24 26 28
|
||||
do
|
||||
CUDA_VISIBLE_DEVICES=0 python compare.py --circuit $circuit --nqubits $nqubits --filename $filename \
|
||||
--library-options backend=qibojit,platform=cupy --nreps $nreps_gpu --precision $precision
|
||||
echo
|
||||
CUDA_VISIBLE_DEVICES=0 python compare.py --circuit $circuit --nqubits $nqubits --filename $filename \
|
||||
--library-options backend=qibojit,platform=cuquantum --nreps $nreps_gpu --precision $precision
|
||||
echo
|
||||
CUDA_VISIBLE_DEVICES="" python compare.py --circuit $circuit --nqubits $nqubits --filename $filename \
|
||||
--library-options backend=qibojit,platform=numba --nreps $nreps_cpu --precision $precision
|
||||
echo
|
||||
done
|
||||
36
qibojit-benchmarks/scripts/qibotn.sh
Executable file
36
qibojit-benchmarks/scripts/qibotn.sh
Executable file
@@ -0,0 +1,36 @@
|
||||
#! /usr/bin/bash
|
||||
# Script for 2-nodes-4-GPUs (2x4) configuration
|
||||
# Command-line parameters
|
||||
: "${circuit:=variational}"
|
||||
: "${precision:=double}"
|
||||
: "${nreps:=3}"
|
||||
: "${filename:=qibotn_expectation_double_2x4.dat}"
|
||||
|
||||
node_list=/nodelist_2x4 #file containing the IP address of the resources, omit this if it is running on single-node-multi-gpu
|
||||
|
||||
for (nqubits = 10; nqubits <= 8000; nqubits += 100)
|
||||
do
|
||||
#echo '{"MPI_enabled": true, "MPS_enabled": false, "NCCL_enabled": false, "expectation_enabled": true}' > cu_tensornet_mpi_expectation.json #can be pre-generated or can include it in script. Here is using pre-generated.
|
||||
mpirun -np 8 -hostfile $node_list python compare.py --circuit variational --circuit-options nlayers=3 --nqubits 4$nqubits --filename $filename \
|
||||
--library-options backend=qibotn,platform=cutensornet,computation_settings=cu_tensornet_mpi_expectation.json \
|
||||
--nreps $nreps --precision $precision
|
||||
echo
|
||||
#echo '{"MPI_enabled": false, "MPS_enabled": false, "NCCL_enabled": true, "expectation_enabled": true}' > cu_tensornet_nccl_expectation.json
|
||||
mpirun -np 8 -hostfile $node_list python compare.py --circuit variational --circuit-options nlayers=3 --nqubits $nqubits --filename $filename \
|
||||
--library-options backend=qibotn,platform=cutensornet,computation_settings=cu_tensornet_nccl_expectation.json \
|
||||
--nreps $nreps --precision $precision
|
||||
echo
|
||||
#echo '{"MPI_enabled": false, "MPS_enabled": false, "NCCL_enabled": false, "expectation_enabled": true}' > cu_tensornet_expectation.json
|
||||
python compare.py --circuit variational --circuit-options nlayers=3 --nqubits $nqubits --filename $filename \
|
||||
--library-options backend=qibotn,platform=cutensornet,computation_settings=cu_tensornet_expectation.json \
|
||||
--nreps $nreps --precision $precision
|
||||
echo
|
||||
python compare.py --circuit variational --circuit-options nlayers=3 --nqubits $nqubits --filename $filename \
|
||||
--library-options backend=qibojit,platform=numba,expectation="XXXZ" \
|
||||
--nreps $nreps --precision $precision
|
||||
echo
|
||||
done
|
||||
|
||||
: <<'END_COMMENT'
|
||||
|
||||
END_COMMENT
|
||||
56
qibojit-benchmarks/scripts/qibotn_local.sh
Executable file
56
qibojit-benchmarks/scripts/qibotn_local.sh
Executable file
@@ -0,0 +1,56 @@
|
||||
#!/usr/bin/env bash
|
||||
# Lightweight local benchmark script (single node, small sweep)
|
||||
set -euo pipefail
|
||||
|
||||
: "${circuit:=variational}"
|
||||
: "${precision:=complex128}"
|
||||
: "${nreps:=1}"
|
||||
: "${filename:=qibotn_expectation_local.dat}"
|
||||
: "${np:=2}"
|
||||
: "${nlayers:=2}"
|
||||
: "${nqubits_list:=8 12 16}"
|
||||
|
||||
script_dir="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
||||
repo_root="$(cd "${script_dir}/.." && pwd)"
|
||||
cd "${repo_root}"
|
||||
|
||||
# On Prism, Intel MPI may need shared-memory fabric for local runs.
|
||||
if [[ -z "${I_MPI_FABRICS:-}" ]]; then
|
||||
export I_MPI_FABRICS=shm
|
||||
fi
|
||||
|
||||
for nqubits in ${nqubits_list}; do
|
||||
echo "===== nqubits=${nqubits} ====="
|
||||
|
||||
# MPI-enabled cutensornet expectation
|
||||
mpirun -np "${np}" python compare.py \
|
||||
--circuit "${circuit}" \
|
||||
--circuit-options "nlayers=${nlayers}" \
|
||||
--nqubits "${nqubits}" \
|
||||
--filename "${filename}" \
|
||||
--library-options backend=qibotn,platform=cutensornet,computation_settings=scripts/cu_tensornet_mpi_expectation.json \
|
||||
--nreps "${nreps}" \
|
||||
--precision "${precision}"
|
||||
|
||||
# Single-process cutensornet expectation
|
||||
python compare.py \
|
||||
--circuit "${circuit}" \
|
||||
--circuit-options "nlayers=${nlayers}" \
|
||||
--nqubits "${nqubits}" \
|
||||
--filename "${filename}" \
|
||||
--library-options backend=qibotn,platform=cutensornet,computation_settings=scripts/cu_tensornet_expectation.json \
|
||||
--nreps "${nreps}" \
|
||||
--precision "${precision}"
|
||||
|
||||
# qibojit reference
|
||||
python compare.py \
|
||||
--circuit "${circuit}" \
|
||||
--circuit-options "nlayers=${nlayers}" \
|
||||
--nqubits "${nqubits}" \
|
||||
--filename "${filename}" \
|
||||
--library-options backend=qibojit,platform=numba,expectation=XXXZ \
|
||||
--nreps "${nreps}" \
|
||||
--precision "${precision}"
|
||||
|
||||
echo
|
||||
done
|
||||
214
qibojit-benchmarks/scripts/quimb/README.md
Normal file
214
qibojit-benchmarks/scripts/quimb/README.md
Normal file
@@ -0,0 +1,214 @@
|
||||
# Quimb Benchmark Suite
|
||||
|
||||
Local (single-process) tensor network simulation benchmarking using quimb backend.
|
||||
|
||||
## Files
|
||||
|
||||
- **quimb_local.sh** — Main benchmark sweep script (no MPI)
|
||||
- **expectation_mps.json** — Expectation mode with MPS (default for expectation)
|
||||
- **expectation_dense.json** — Expectation mode, dense tensor network
|
||||
- **dense_vector_mps.json** — State extraction with MPS (default for state)
|
||||
- **dense_vector_dense.json** — State extraction, dense tensor network
|
||||
|
||||
## Configuration Files
|
||||
|
||||
### Expectation Modes (computing Hamiltonian expectation values)
|
||||
- **expectation_mps.json**: Uses Matrix Product State (MPS) tensor network ansatz; good for larger systems with limited bond dimension
|
||||
- **expectation_dense.json**: Uses dense tensor network; full contraction without MPS truncation
|
||||
|
||||
### State Modes (full state vector computation)
|
||||
- **dense_vector_mps.json**: Extracts full state using MPS contraction (faster, bounded memory)
|
||||
- **dense_vector_dense.json**: Extracts full state using dense tensor (maximum memory usage)
|
||||
|
||||
## Usage
|
||||
|
||||
```bash
|
||||
cd /ssd_data/tankya2/code/ASC_2026_prism/ASC-2026/qibojit-benchmarks/scripts/quimb
|
||||
|
||||
# Run with defaults (all matching dense_vector*.json and expectation*.json configs)
|
||||
./quimb_local.sh
|
||||
|
||||
# Test only expectation mode, custom qubit sizes
|
||||
modes="expectation" nqubits_list="8 10 12" ./quimb_local.sh
|
||||
|
||||
# Test dense vector only with one explicit config
|
||||
state_cfg=dense_vector_dense.json modes="dense_vector" ./quimb_local.sh
|
||||
|
||||
# Restrict the sweep to a chosen subset of configs
|
||||
EXPECTATION_CONFIGS="expectation_mps.json expectation_dense.json" ./quimb_local.sh
|
||||
|
||||
# Test variational and BV circuits
|
||||
circuits="variational bv" nqubits_list="6 8 10" nreps=3 ./quimb_local.sh
|
||||
```
|
||||
|
||||
## Supported Circuits
|
||||
|
||||
### ✓ Fully Supported (Numerically Validated)
|
||||
|
||||
| Circuit | Alias | Parameters | Status | Notes |
|
||||
|---------|-------|------------|--------|-------|
|
||||
| **qft** | — | none | ✓ Works | Quantum Fourier Transform; aligned with qibojit |
|
||||
| **supremacy** | — | depth, seed | ✓ Works | Verified locally after environment repair; requires Cirq import path to be healthy |
|
||||
| **variational** | — | nlayers | ✓ Works | Parameterized circuit; aligned with qibojit |
|
||||
| **bv** | bernstein-vazirani | none | ✓ Works | Bernstein-Vazirani algorithm; aligned with qibojit |
|
||||
| **hs** | hidden-shift | none | ✓ Works | Hidden-shift problem; aligned with qibojit |
|
||||
| **qaoa** | — | nlayers | ✓ Works | QAOA with RZZ gate support; aligned with qibojit |
|
||||
|
||||
### ❌ Not Supported
|
||||
|
||||
| Circuit | Issue | Notes |
|
||||
|---------|-------|-------|
|
||||
| **qv** | Qiskit API compatibility | quantum-volume uses deprecated qiskit `.qasm()` method (v3.0+); not specific to quimb |
|
||||
|
||||
### Implementation Notes
|
||||
- **RZZ Gate:** Full support for QAOA and algorithms using two-qubit Ising rotations
|
||||
- **cu1 Gate:** Fully supported in expectation value mode (QFT compatible)
|
||||
- **Numerical Alignment:** All benchmarks automatically include qibojit (numba) reference with identical observable for validation
|
||||
|
||||
## Environment Variables
|
||||
|
||||
| Variable | Default | Description |
|
||||
|----------|---------|-------------|
|
||||
| `nqubits_list` | `6 8 10` | Space-separated qubit counts to benchmark |
|
||||
| `circuits` | `supremacy qft variational bv qaoa` | Space-separated circuit names |
|
||||
| `modes` | `dense_vector expectation` | Benchmark modes (dense_vector, expectation) |
|
||||
| `nlayers` | `2` | Layers for layered circuits (variational, qaoa) |
|
||||
| `nreps` | `1` | Repetitions per benchmark |
|
||||
| `filename` | `quimb_benchmark_local.dat` | Output log file |
|
||||
| `precision` | `complex128` | NumPy dtype (complex128 or complex64) |
|
||||
| `exp_cfg` | unset | Optional single expectation config; when unset, all `expectation*.json` files are swept |
|
||||
| `state_cfg` | unset | Optional single dense-vector config; when unset, all `dense_vector*.json` files are swept |
|
||||
| `EXPECTATION_CONFIGS` | unset | Optional space-separated subset of expectation configs to run |
|
||||
| `STATE_CONFIGS` | unset | Optional space-separated subset of dense-vector configs to run |
|
||||
|
||||
## Results
|
||||
|
||||
Results are logged to `/qibojit-benchmarks/benchmarks/results/` with filename `quimb_benchmark_local.dat` (configurable).
|
||||
|
||||
Each benchmark includes:
|
||||
- **import_time** — Backend initialization time
|
||||
- **creation_time** — Circuit creation time
|
||||
- **dry_run_time** — First execution time (warm-up)
|
||||
- **simulation_times** — Execution times for nreps runs
|
||||
- **expectation_result** — Observable expectation values (for expectation mode)
|
||||
|
||||
## Observable
|
||||
|
||||
By default, expectation uses:
|
||||
- **X on qubit 0**, identity on remaining qubits
|
||||
- Configurable via `pauli_pattern` in JSON config (e.g., `"XIIII"` for 5 qubits)
|
||||
|
||||
## Reference Validation
|
||||
|
||||
Each benchmark run automatically includes a **qibojit (numba) reference** with the same observable configuration, enabling direct numerical comparison for validation.
|
||||
|
||||
Example:
|
||||
```
|
||||
[expectation MPI] quimb + qft @ 6q: 0.2019...
|
||||
[qibojit ref] numba + qft @ 6q: 0.2019... ✓ aligned
|
||||
```
|
||||
|
||||
## MPI Support
|
||||
|
||||
For MPI-enabled benchmarking (multiple processes), see the parallel suite in `/scripts/quimb_mpi/`:
|
||||
|
||||
```bash
|
||||
cd /ssd_data/tankya2/code/ASC_2026_prism/ASC-2026/qibojit-benchmarks/scripts/quimb_mpi
|
||||
./quimb_mpi.sh # runs with mpirun -np 2
|
||||
```
|
||||
|
||||
## Tensor Network Options
|
||||
|
||||
Quimb supports both MPS (Matrix Product State) and dense tensor network contractions. By default the script sweeps every matching JSON file in this folder, or you can target individual configs:
|
||||
|
||||
```bash
|
||||
# Compare MPS vs dense at same nqubits
|
||||
exp_cfg=expectation_mps.json nqubits_list="12" ./quimb_local.sh
|
||||
exp_cfg=expectation_dense.json nqubits_list="12" ./quimb_local.sh
|
||||
```
|
||||
|
||||
MPS is typically faster and uses bounded memory, while dense provides full accuracy without truncation.
|
||||
|
||||
## Installation
|
||||
|
||||
Preferred path: create a fresh environment from the benchmark spec.
|
||||
|
||||
```bash
|
||||
cd /ssd_data/tankya2/code/ASC_2026_prism/ASC-2026/qibojit-benchmarks
|
||||
conda env create -f environment.yml
|
||||
conda activate benchmarks
|
||||
```
|
||||
|
||||
If you are using an existing environment instead of recreating it, check that it is aligned with the benchmark stack:
|
||||
|
||||
```bash
|
||||
python -c "import numpy, qibo, qibojit; print('numpy', numpy.__version__); print('qibo', qibo.__version__); print('qibojit', qibojit.__version__)"
|
||||
```
|
||||
|
||||
## Dependency Recovery
|
||||
|
||||
```bash
|
||||
pip install cirq==0.8.2
|
||||
```
|
||||
This is the recovery path that eventually made `./quimb_local.sh` work for `supremacy` in the existing `qibotn-py311-test` environment.
|
||||
|
||||
### Symptom 1: `cirq` failed with `ModuleNotFoundError: No module named 'pkg_resources'`
|
||||
|
||||
Cause:
|
||||
- the existing environment had `setuptools 82.0.1`
|
||||
- that install did not expose `pkg_resources`
|
||||
- the installed `cirq` package still imported `pkg_resources` during startup
|
||||
|
||||
Fix:
|
||||
|
||||
```bash
|
||||
/home/tankya2/miniforge3/envs/qibotn-py311-test/bin/python -m pip install "setuptools<81"
|
||||
```
|
||||
|
||||
Working result:
|
||||
- `setuptools` was changed to `80.10.2`
|
||||
- `import pkg_resources` worked again
|
||||
- the Quimb `supremacy` path could construct the Cirq-generated circuit
|
||||
|
||||
### Symptom 2: `qibojit` reference crashed with `TypeError: asarray() got an unexpected keyword argument 'copy'`
|
||||
|
||||
Cause:
|
||||
- the same environment had `numpy 1.26.4`
|
||||
- but `qibo 0.3.1` requires `numpy >= 2.0.0`
|
||||
- the `qibojit` reference backend was therefore running against an incompatible NumPy version
|
||||
|
||||
Fix:
|
||||
|
||||
```bash
|
||||
/home/tankya2/miniforge3/envs/qibotn-py311-test/bin/python -m pip install numpy==2.2.6
|
||||
```
|
||||
|
||||
Working result:
|
||||
- `numpy` was changed to `2.2.6`
|
||||
- the `qibojit` reference backend started working again
|
||||
- both the Quimb and qibojit sides of the `supremacy` benchmark completed successfully
|
||||
|
||||
### Final verified state
|
||||
|
||||
The existing repaired environment was verified with:
|
||||
|
||||
```bash
|
||||
cd /ssd_data/tankya2/code/ASC_2026_prism/ASC-2026/qibojit-benchmarks/scripts/quimb
|
||||
nqubits_list="6" circuits="supremacy" nreps=1 modes="dense_vector expectation" ./quimb_local.sh
|
||||
```
|
||||
|
||||
That smoke test completed all three stages:
|
||||
- Quimb `dense_vector`
|
||||
- Quimb `expectation`
|
||||
- qibojit reference
|
||||
|
||||
Notes:
|
||||
- `environment.yml` remains the preferred source of truth for a clean install
|
||||
- the repaired environment may still emit a `pkg_resources` deprecation warning from the older Cirq stack, but the benchmark run succeeds
|
||||
- if an environment has drifted far from `environment.yml`, recreating it is usually safer than incremental repair
|
||||
|
||||
## Notes
|
||||
|
||||
- **Intel MPI Fabric:** On Prism cluster, shared-memory fabric (`I_MPI_FABRICS=shm`) is automatically enabled for single-node runs
|
||||
- **QFT Support:** Fixed cu1 gate compatibility in quimb backend; no platform-specific gate limitations
|
||||
- **Bond Dimension:** MPS modes use max_bond_dimension=20 by default; adjust in JSON for memory/accuracy tradeoff
|
||||
1
qibojit-benchmarks/scripts/quimb/dense_vector_dense.json
Normal file
1
qibojit-benchmarks/scripts/quimb/dense_vector_dense.json
Normal file
@@ -0,0 +1 @@
|
||||
{"expectation_enabled": false, "use_mps": false}
|
||||
1
qibojit-benchmarks/scripts/quimb/dense_vector_mps.json
Normal file
1
qibojit-benchmarks/scripts/quimb/dense_vector_mps.json
Normal file
@@ -0,0 +1 @@
|
||||
{"expectation_enabled": false, "use_mps": true, "max_bond_dimension": 20, "svd_cutoff": 1e-10}
|
||||
1
qibojit-benchmarks/scripts/quimb/expectation_dense.json
Normal file
1
qibojit-benchmarks/scripts/quimb/expectation_dense.json
Normal file
@@ -0,0 +1 @@
|
||||
{"expectation_enabled": true, "use_mps": false, "pauli_pattern": "XIIII"}
|
||||
@@ -0,0 +1,6 @@
|
||||
{
|
||||
"expectation_enabled": true,
|
||||
"use_mps": false,
|
||||
"pauli_pattern_auto": true,
|
||||
"pauli_pattern_style": "mixed"
|
||||
}
|
||||
1
qibojit-benchmarks/scripts/quimb/expectation_mps.json
Normal file
1
qibojit-benchmarks/scripts/quimb/expectation_mps.json
Normal file
@@ -0,0 +1 @@
|
||||
{"expectation_enabled": true, "use_mps": true, "max_bond_dimension": 20, "svd_cutoff": 1e-10, "pauli_pattern": "XIIII"}
|
||||
215
qibojit-benchmarks/scripts/quimb/quimb_local.sh
Executable file
215
qibojit-benchmarks/scripts/quimb/quimb_local.sh
Executable file
@@ -0,0 +1,215 @@
|
||||
#!/usr/bin/env bash
|
||||
# Local quimb benchmark sweep.
|
||||
# Tests both dense vector (non-expectation) and expectation across multiple
|
||||
# qubit sizes and circuit types.
|
||||
#
|
||||
# Usage examples:
|
||||
# ./quimb_local.sh
|
||||
# nqubits_list="6 8 10" circuits="variational bv" ./quimb_local.sh
|
||||
# modes="expectation" nreps=3 ./quimb_local.sh
|
||||
# state_cfg=dense_vector_dense.json modes="dense_vector" ./quimb_local.sh
|
||||
set -euo pipefail
|
||||
|
||||
: "${precision:=complex128}"
|
||||
: "${nreps:=3}"
|
||||
: "${filename:=quimb_benchmark_local.dat}"
|
||||
: "${nlayers:=2}"
|
||||
: "${nqubits_list:=6 8 10}"
|
||||
: "${circuits:=supremacy qft variational qaoa}"
|
||||
: "${modes:=dense_vector expectation}"
|
||||
: "${exp_cfg:=}"
|
||||
: "${state_cfg:=}"
|
||||
: "${EXPECTATION_CONFIGS:=}"
|
||||
: "${STATE_CONFIGS:=}"
|
||||
|
||||
script_dir="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
||||
repo_root="$(cd "${script_dir}/../.." && pwd)"
|
||||
cd "${repo_root}"
|
||||
|
||||
config_list_from_prefix() {
|
||||
local prefix="$1"
|
||||
local single_cfg="$2"
|
||||
local override_list="$3"
|
||||
|
||||
if [[ -n "${override_list}" ]]; then
|
||||
for cfg in ${override_list}; do
|
||||
printf '%s\n' "${cfg}"
|
||||
done
|
||||
return
|
||||
fi
|
||||
|
||||
if [[ -n "${single_cfg}" ]]; then
|
||||
printf '%s\n' "${single_cfg}"
|
||||
return
|
||||
fi
|
||||
|
||||
shopt -s nullglob
|
||||
local matches=( "${script_dir}/${prefix}"*.json )
|
||||
shopt -u nullglob
|
||||
|
||||
for path in "${matches[@]}"; do
|
||||
basename "${path}"
|
||||
done
|
||||
}
|
||||
|
||||
require_existing_configs() {
|
||||
local mode="$1"
|
||||
shift
|
||||
|
||||
for cfg in "$@"; do
|
||||
if [[ ! -f "${script_dir}/${cfg}" ]]; then
|
||||
echo "Missing ${mode} config: ${script_dir}/${cfg}" >&2
|
||||
exit 1
|
||||
fi
|
||||
done
|
||||
}
|
||||
|
||||
read_pauli_pattern() {
|
||||
local cfg_path="$1"
|
||||
|
||||
python - "${cfg_path}" <<'PY'
|
||||
import json
|
||||
import sys
|
||||
|
||||
try:
|
||||
with open(sys.argv[1], "r") as f:
|
||||
data = json.load(f)
|
||||
print(data.get("pauli_pattern", ""))
|
||||
except Exception:
|
||||
print("")
|
||||
PY
|
||||
}
|
||||
|
||||
build_ref_pattern() {
|
||||
local base_pauli_pattern="$1"
|
||||
local nqubits="$2"
|
||||
|
||||
python - "${base_pauli_pattern}" "${nqubits}" <<'PY'
|
||||
import sys
|
||||
|
||||
p = sys.argv[1].upper()
|
||||
n = int(sys.argv[2])
|
||||
|
||||
if not p:
|
||||
p = "X" + "I" * max(n - 1, 0)
|
||||
if len(p) < n:
|
||||
p = p + ("I" * (n - len(p)))
|
||||
else:
|
||||
p = p[:n]
|
||||
print(p)
|
||||
PY
|
||||
}
|
||||
|
||||
run_qibojit_reference() {
|
||||
local nqubits="$1"
|
||||
local circuit="$2"
|
||||
local circuit_opts="$3"
|
||||
local exp_cfg_name="$4"
|
||||
local exp_cfg_path="${script_dir}/${exp_cfg_name}"
|
||||
local base_pauli_pattern
|
||||
local ref_pattern
|
||||
|
||||
base_pauli_pattern="$(read_pauli_pattern "${exp_cfg_path}")"
|
||||
ref_pattern="$(build_ref_pattern "${base_pauli_pattern}" "${nqubits}")"
|
||||
|
||||
echo " [qibojit reference] cfg=${exp_cfg_name}"
|
||||
python compare.py \
|
||||
--circuit "${circuit}" \
|
||||
${circuit_opts:+--circuit-options "${circuit_opts}"} \
|
||||
--nqubits "${nqubits}" \
|
||||
--filename "${filename}" \
|
||||
--library-options backend=qibojit,platform=numba,expectation=${ref_pattern} \
|
||||
--nreps "${nreps}" \
|
||||
--precision "${precision}"
|
||||
}
|
||||
|
||||
mapfile -t expectation_cfgs < <(
|
||||
config_list_from_prefix "expectation" "${exp_cfg}" "${EXPECTATION_CONFIGS}"
|
||||
)
|
||||
mapfile -t state_cfgs < <(
|
||||
config_list_from_prefix "dense_vector" "${state_cfg}" "${STATE_CONFIGS}"
|
||||
)
|
||||
|
||||
run_dense_mode=false
|
||||
run_expectation_mode=false
|
||||
|
||||
if echo "${modes}" | grep -Eqw "dense_vector|statevector"; then
|
||||
run_dense_mode=true
|
||||
fi
|
||||
|
||||
if echo "${modes}" | grep -qw "expectation"; then
|
||||
run_expectation_mode=true
|
||||
fi
|
||||
|
||||
if [[ "${run_dense_mode}" == true && ${#state_cfgs[@]} -eq 0 ]]; then
|
||||
echo "No dense-vector JSON configs found in ${script_dir}" >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if [[ "${run_expectation_mode}" == true && ${#expectation_cfgs[@]} -eq 0 ]]; then
|
||||
echo "No expectation JSON configs found in ${script_dir}" >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
require_existing_configs "dense-vector" "${state_cfgs[@]}"
|
||||
require_existing_configs "expectation" "${expectation_cfgs[@]}"
|
||||
|
||||
# On Prism, Intel MPI needs shared-memory fabric for single-node runs.
|
||||
if [[ -z "${I_MPI_FABRICS:-}" ]]; then
|
||||
export I_MPI_FABRICS=shm
|
||||
fi
|
||||
|
||||
echo "Dense-vector configs : ${state_cfgs[*]:-none}"
|
||||
echo "Expectation configs : ${expectation_cfgs[*]:-none}"
|
||||
|
||||
for nqubits in ${nqubits_list}; do
|
||||
for circuit in ${circuits}; do
|
||||
circuit_opts="nlayers=${nlayers}"
|
||||
# These circuits do not use nlayers — omit it to avoid unknown-option errors.
|
||||
if [[ "${circuit}" == "qft" || "${circuit}" == "QFT" || \
|
||||
"${circuit}" == "supremacy" || "${circuit}" == "Supremacy" || \
|
||||
"${circuit}" == "bv" || "${circuit}" == "bernstein-vazirani" || \
|
||||
"${circuit}" == "hs" || "${circuit}" == "hidden-shift" || \
|
||||
"${circuit}" == "qaoa" || "${circuit}" == "qv" || \
|
||||
"${circuit}" == "quantum-volume" ]]; then
|
||||
circuit_opts=""
|
||||
fi
|
||||
|
||||
echo "===== nqubits=${nqubits} circuit=${circuit} ====="
|
||||
|
||||
# dense_vector is the preferred name; statevector is kept as a legacy alias.
|
||||
if [[ "${run_dense_mode}" == true ]]; then
|
||||
for cfg_name in "${state_cfgs[@]}"; do
|
||||
state_cfg_path="${script_dir}/${cfg_name}"
|
||||
echo " [dense_vector] cfg=${cfg_name}"
|
||||
python compare.py \
|
||||
--circuit "${circuit}" \
|
||||
${circuit_opts:+--circuit-options "${circuit_opts}"} \
|
||||
--nqubits "${nqubits}" \
|
||||
--filename "${filename}" \
|
||||
--library-options backend=qibotn,platform=quimb,computation_settings=${state_cfg_path} \
|
||||
--nreps "${nreps}" \
|
||||
--precision "${precision}"
|
||||
done
|
||||
fi
|
||||
|
||||
if [[ "${run_expectation_mode}" == true ]]; then
|
||||
for cfg_name in "${expectation_cfgs[@]}"; do
|
||||
exp_cfg_path="${script_dir}/${cfg_name}"
|
||||
echo " [expectation] cfg=${cfg_name}"
|
||||
python compare.py \
|
||||
--circuit "${circuit}" \
|
||||
${circuit_opts:+--circuit-options "${circuit_opts}"} \
|
||||
--nqubits "${nqubits}" \
|
||||
--filename "${filename}" \
|
||||
--library-options backend=qibotn,platform=quimb,computation_settings=${exp_cfg_path} \
|
||||
--nreps "${nreps}" \
|
||||
--precision "${precision}"
|
||||
|
||||
run_qibojit_reference "${nqubits}" "${circuit}" "${circuit_opts}" "${cfg_name}"
|
||||
done
|
||||
fi
|
||||
|
||||
echo
|
||||
done
|
||||
done
|
||||
167
qibojit-benchmarks/scripts/quimb_mpi/README.md
Normal file
167
qibojit-benchmarks/scripts/quimb_mpi/README.md
Normal file
@@ -0,0 +1,167 @@
|
||||
# Quimb MPI Benchmark Suite
|
||||
|
||||
Demonstrates MPI-enabled tensor network simulation using quimb with 2 MPI processes.
|
||||
|
||||
## Files
|
||||
|
||||
- **quimb_mpi.sh** — Main benchmark sweep script using `mpirun -np 2`
|
||||
- **expectation_mps_mpi.json** — Expectation mode with MPS (default for expectation)
|
||||
- **expectation_dense_mpi.json** — Expectation mode, dense tensor network
|
||||
- **dense_vector_mps_mpi.json** — State extraction with MPS (default for state)
|
||||
- **dense_vector_dense_mpi.json** — State extraction, dense tensor network
|
||||
|
||||
## Key Differences from `/scripts/quimb/`
|
||||
|
||||
- Each `python compare.py` call wrapped with `mpirun -np 2` to enable MPI parallelization
|
||||
- All JSON configs include `"MPI_enabled": true`
|
||||
- Default file names include `_mpi` suffix to distinguish from single-process configs
|
||||
- Filenames in logs clearly show MPI mode (e.g., `expectation_mps_mpi.json`)
|
||||
|
||||
## Configuration Files
|
||||
|
||||
### Expectation Modes (computing Hamiltonian expectation values)
|
||||
- **expectation_mps_mpi.json**: MPI-enabled, uses Matrix Product State (MPS) tensor network ansatz; good for larger systems with limited bond dimension
|
||||
- **expectation_dense_mpi.json**: MPI-enabled, uses dense tensor network; full contraction without MPS truncation
|
||||
|
||||
### State Modes (full state vector computation)
|
||||
- **dense_vector_mps_mpi.json**: MPI-enabled, extracts full state using MPS contraction (faster, bounded memory)
|
||||
- **dense_vector_dense_mpi.json**: MPI-enabled, extracts full state using dense tensor (maximum memory usage)
|
||||
|
||||
## Usage
|
||||
|
||||
```bash
|
||||
cd /ssd_data/tankya2/code/ASC_2026_prism/ASC-2026/qibojit-benchmarks/scripts/quimb_mpi
|
||||
|
||||
# Run with defaults (all matching dense_vector*.json and expectation*.json configs)
|
||||
./quimb_mpi.sh
|
||||
|
||||
# Test only expectation mode, custom qubit sizes
|
||||
modes="expectation" nqubits_list="8 10 12" ./quimb_mpi.sh
|
||||
|
||||
# Test dense vector only with one explicit config
|
||||
state_cfg=dense_vector_dense_mpi.json modes="dense_vector" ./quimb_mpi.sh
|
||||
|
||||
# Restrict the sweep to a chosen subset of configs
|
||||
EXPECTATION_CONFIGS="expectation_mps_mpi.json expectation_dense_mpi.json" ./quimb_mpi.sh
|
||||
|
||||
# Use 4 MPI processes (if testing scalability)
|
||||
np=4 ./quimb_mpi.sh
|
||||
```
|
||||
|
||||
## Supported Circuits
|
||||
|
||||
### ✓ Fully Supported (Numerically Validated)
|
||||
|
||||
| Circuit | Alias | Parameters | Status | Notes |
|
||||
|---------|-------|------------|--------|-------|
|
||||
| **qft** | — | none | ✓ Works | Quantum Fourier Transform; aligned with qibojit |
|
||||
| **variational** | — | nlayers | ✓ Works | Parameterized circuit; aligned with qibojit |
|
||||
| **bv** | bernstein-vazirani | none | ✓ Works | Bernstein-Vazirani algorithm; aligned with qibojit |
|
||||
| **hs** | hidden-shift | none | ✓ Works | Hidden-shift problem; aligned with qibojit |
|
||||
| **qaoa** | — | nlayers | ✓ Works | QAOA with RZZ gate support; aligned with qibojit |
|
||||
|
||||
### ❌ Not Supported
|
||||
|
||||
| Circuit | Issue | Notes |
|
||||
|---------|-------|-------|
|
||||
| **qv** | Qiskit API compatibility | quantum-volume uses deprecated qiskit `.qasm()` method (v3.0+); not specific to quimb |
|
||||
|
||||
## Environment Variables
|
||||
|
||||
| Variable | Default | Description |
|
||||
|----------|---------|-------------|
|
||||
| `nqubits_list` | `6 8 10` | Space-separated qubit counts to benchmark |
|
||||
| `circuits` | `qaoa` | Space-separated circuit names |
|
||||
| `modes` | `dense_vector expectation` | Benchmark modes (dense_vector, expectation) |
|
||||
| `nlayers` | `2` | Layers for layered circuits (variational, qaoa) |
|
||||
| `np` | `2` | Number of MPI processes (mpirun -np) |
|
||||
| `nreps` | `1` | Repetitions per benchmark |
|
||||
| `filename` | `quimb_benchmark_mpi.dat` | Output log file |
|
||||
| `precision` | `complex128` | NumPy dtype (complex128 or complex64) |
|
||||
| `exp_cfg` | unset | Optional single expectation config; when unset, all `expectation*.json` files are swept |
|
||||
| `state_cfg` | unset | Optional single dense-vector config; when unset, all `dense_vector*.json` files are swept |
|
||||
| `EXPECTATION_CONFIGS` | unset | Optional space-separated subset of expectation configs to run |
|
||||
| `STATE_CONFIGS` | unset | Optional space-separated subset of dense-vector configs to run |
|
||||
|
||||
## Results
|
||||
|
||||
Results are stored in `/qibojit-benchmarks/benchmarks/results/` with filename prefix `quimb_benchmark_mpi.dat` by default (configurable via `filename=` env var).
|
||||
|
||||
Each benchmark includes:
|
||||
- **import_time** — Backend initialization time
|
||||
- **creation_time** — Circuit creation time
|
||||
- **dry_run_time** — First execution time (warm-up)
|
||||
- **simulation_times** — Execution times for nreps runs
|
||||
- **expectation_result** — Observable expectation values (for expectation mode)
|
||||
|
||||
## Observable
|
||||
|
||||
By default, expectation uses:
|
||||
- **X on qubit 0**, identity on remaining qubits
|
||||
- Configurable via `pauli_pattern` in JSON config (e.g., `"XIIII"` for 5 qubits)
|
||||
|
||||
## Reference Validation
|
||||
|
||||
Each benchmark run automatically includes a **qibojit (numba) reference** with the same observable configuration, enabling direct numerical comparison for validation.
|
||||
|
||||
Example:
|
||||
```
|
||||
[expectation MPI] quimb + variational @ 6q: 0.2019...
|
||||
[qibojit ref] numba + variational @ 6q: 0.2019... ✓ aligned
|
||||
```
|
||||
|
||||
## Supported Circuits
|
||||
|
||||
### ✓ Fully Supported (Numerically Validated)
|
||||
|
||||
| Circuit | Alias | Parameters | Status | Notes |
|
||||
|---------|-------|------------|--------|-------|
|
||||
| **qft** | — | none | ✓ Works | Quantum Fourier Transform; aligned with qibojit |
|
||||
| **variational** | — | nlayers | ✓ Works | Parameterized circuit; aligned with qibojit |
|
||||
| **bv** | bernstein-vazirani | none | ✓ Works | Bernstein-Vazirani algorithm; aligned with qibojit |
|
||||
| **hs** | hidden-shift | none | ✓ Works | Hidden-shift problem; aligned with qibojit |
|
||||
| **qaoa** | — | nlayers | ✓ Works | QAOA with RZZ gate support; aligned with qibojit |
|
||||
|
||||
### ❌ Not Supported
|
||||
|
||||
| Circuit | Issue | Notes |
|
||||
|---------|-------|-------|
|
||||
| **qv** | Qiskit API compatibility | quantum-volume uses deprecated qiskit `.qasm()` method (v3.0+); not specific to quimb |
|
||||
|
||||
## Notes
|
||||
|
||||
- **Intel MPI Fabric:** On Prism, automatically sets `I_MPI_FABRICS=shm` (shared-memory fabric) for single-node local runs
|
||||
- **Observable:** X on first qubit, identity on rest (configurable via `pauli_pattern` in JSON)
|
||||
- **Reference:** qibojit (numba backend) included automatically with aligned observable for validation
|
||||
- **RZZ Gate:** Full support for QAOA and algorithms using two-qubit Ising rotations
|
||||
- **cu1 Gate:** Fully supported in expectation value mode (QFT compatible)
|
||||
- **Numerical Alignment:** All benchmarks automatically include qibojit reference with identical observable for validation
|
||||
|
||||
## MPI Enable/Disable
|
||||
|
||||
To test without MPI, use configs from `/scripts/quimb/` instead:
|
||||
|
||||
```bash
|
||||
# Compare: MPI vs no MPI
|
||||
./quimb_mpi.sh # with MPI (2 processes)
|
||||
cd ../quimb && ./quimb_local.sh # without MPI (single process)
|
||||
```
|
||||
|
||||
## Tensor Network Options
|
||||
|
||||
Quimb supports both MPS (Matrix Product State) and dense tensor network contractions. By default the script sweeps every matching JSON file in this folder, or you can target individual configs:
|
||||
|
||||
```bash
|
||||
# Compare MPS vs dense at same nqubits with MPI
|
||||
exp_cfg=expectation_mps_mpi.json nqubits_list="12" ./quimb_mpi.sh
|
||||
exp_cfg=expectation_dense_mpi.json nqubits_list="12" ./quimb_mpi.sh
|
||||
```
|
||||
|
||||
MPS is typically faster and uses bounded memory, while dense provides full accuracy without truncation.
|
||||
|
||||
## Additional Notes
|
||||
|
||||
- **Bond Dimension:** MPS modes use max_bond_dimension=20 by default; adjust in JSON for memory/accuracy tradeoff
|
||||
- **SVD Cutoff:** Set to 1e-10 for high accuracy; increase for faster execution with acceptable loss tolerance
|
||||
- **Scaling:** MPI parallelization enables larger systems; test with np=4, np=8, etc. for scaling studies
|
||||
- **Single-Node MPI:** Default `-np 2` demonstrates MPI capability on local machine; for cluster runs, adjust `-np` and node configuration
|
||||
@@ -0,0 +1 @@
|
||||
{"MPI_enabled": true, "expectation_enabled": false, "use_mps": false}
|
||||
@@ -0,0 +1 @@
|
||||
{"MPI_enabled": true, "expectation_enabled": false, "use_mps": true, "max_bond_dimension": 20, "svd_cutoff": 1e-10}
|
||||
@@ -0,0 +1 @@
|
||||
{"MPI_enabled": true, "expectation_enabled": true, "use_mps": false, "pauli_pattern": "XIIII"}
|
||||
@@ -0,0 +1 @@
|
||||
{"MPI_enabled": true, "expectation_enabled": true, "use_mps": true, "max_bond_dimension": 20, "svd_cutoff": 1e-10, "pauli_pattern": "XIIII"}
|
||||
216
qibojit-benchmarks/scripts/quimb_mpi/quimb_mpi.sh
Executable file
216
qibojit-benchmarks/scripts/quimb_mpi/quimb_mpi.sh
Executable file
@@ -0,0 +1,216 @@
|
||||
#!/usr/bin/env bash
|
||||
# MPI-enabled quimb benchmark sweep (2 processes).
|
||||
# Tests both dense vector (non-expectation) and expectation across multiple
|
||||
# qubit sizes and circuit types, using mpirun -np 2 to demonstrate MPI capability.
|
||||
#
|
||||
# Usage examples:
|
||||
# ./quimb_mpi.sh
|
||||
# nqubits_list="6 8 10" circuits="variational bv" ./quimb_mpi.sh
|
||||
# modes="expectation" nreps=3 ./quimb_mpi.sh
|
||||
# state_cfg=dense_vector_dense_mpi.json modes="dense_vector" ./quimb_mpi.sh
|
||||
set -euo pipefail
|
||||
|
||||
: "${precision:=complex128}"
|
||||
: "${nreps:=3}"
|
||||
: "${filename:=quimb_benchmark_mpi.dat}"
|
||||
: "${nlayers:=2}"
|
||||
: "${nqubits_list:=6 8 10}"
|
||||
: "${circuits:=supremacy qft variational qaoa}"
|
||||
: "${modes:=dense_vector expectation}"
|
||||
: "${np:=2}"
|
||||
: "${exp_cfg:=}"
|
||||
: "${state_cfg:=}"
|
||||
: "${EXPECTATION_CONFIGS:=}"
|
||||
: "${STATE_CONFIGS:=}"
|
||||
|
||||
script_dir="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
||||
repo_root="$(cd "${script_dir}/../.." && pwd)"
|
||||
cd "${repo_root}"
|
||||
|
||||
config_list_from_prefix() {
|
||||
local prefix="$1"
|
||||
local single_cfg="$2"
|
||||
local override_list="$3"
|
||||
|
||||
if [[ -n "${override_list}" ]]; then
|
||||
for cfg in ${override_list}; do
|
||||
printf '%s\n' "${cfg}"
|
||||
done
|
||||
return
|
||||
fi
|
||||
|
||||
if [[ -n "${single_cfg}" ]]; then
|
||||
printf '%s\n' "${single_cfg}"
|
||||
return
|
||||
fi
|
||||
|
||||
shopt -s nullglob
|
||||
local matches=( "${script_dir}/${prefix}"*.json )
|
||||
shopt -u nullglob
|
||||
|
||||
for path in "${matches[@]}"; do
|
||||
basename "${path}"
|
||||
done
|
||||
}
|
||||
|
||||
require_existing_configs() {
|
||||
local mode="$1"
|
||||
shift
|
||||
|
||||
for cfg in "$@"; do
|
||||
if [[ ! -f "${script_dir}/${cfg}" ]]; then
|
||||
echo "Missing ${mode} config: ${script_dir}/${cfg}" >&2
|
||||
exit 1
|
||||
fi
|
||||
done
|
||||
}
|
||||
|
||||
read_pauli_pattern() {
|
||||
local cfg_path="$1"
|
||||
|
||||
python - "${cfg_path}" <<'PY'
|
||||
import json
|
||||
import sys
|
||||
|
||||
try:
|
||||
with open(sys.argv[1], "r") as f:
|
||||
data = json.load(f)
|
||||
print(data.get("pauli_pattern", ""))
|
||||
except Exception:
|
||||
print("")
|
||||
PY
|
||||
}
|
||||
|
||||
build_ref_pattern() {
|
||||
local base_pauli_pattern="$1"
|
||||
local nqubits="$2"
|
||||
|
||||
python - "${base_pauli_pattern}" "${nqubits}" <<'PY'
|
||||
import sys
|
||||
|
||||
p = sys.argv[1].upper()
|
||||
n = int(sys.argv[2])
|
||||
|
||||
if not p:
|
||||
p = "X" + "I" * max(n - 1, 0)
|
||||
if len(p) < n:
|
||||
p = p + ("I" * (n - len(p)))
|
||||
else:
|
||||
p = p[:n]
|
||||
print(p)
|
||||
PY
|
||||
}
|
||||
|
||||
run_qibojit_reference() {
|
||||
local nqubits="$1"
|
||||
local circuit="$2"
|
||||
local circuit_opts="$3"
|
||||
local exp_cfg_name="$4"
|
||||
local exp_cfg_path="${script_dir}/${exp_cfg_name}"
|
||||
local base_pauli_pattern
|
||||
local ref_pattern
|
||||
|
||||
base_pauli_pattern="$(read_pauli_pattern "${exp_cfg_path}")"
|
||||
ref_pattern="$(build_ref_pattern "${base_pauli_pattern}" "${nqubits}")"
|
||||
|
||||
echo " [qibojit reference] cfg=${exp_cfg_name}"
|
||||
python compare.py \
|
||||
--circuit "${circuit}" \
|
||||
${circuit_opts:+--circuit-options "${circuit_opts}"} \
|
||||
--nqubits "${nqubits}" \
|
||||
--filename "${filename}" \
|
||||
--library-options backend=qibojit,platform=numba,expectation=${ref_pattern} \
|
||||
--nreps "${nreps}" \
|
||||
--precision "${precision}"
|
||||
}
|
||||
|
||||
mapfile -t expectation_cfgs < <(
|
||||
config_list_from_prefix "expectation" "${exp_cfg}" "${EXPECTATION_CONFIGS}"
|
||||
)
|
||||
mapfile -t state_cfgs < <(
|
||||
config_list_from_prefix "dense_vector" "${state_cfg}" "${STATE_CONFIGS}"
|
||||
)
|
||||
|
||||
run_dense_mode=false
|
||||
run_expectation_mode=false
|
||||
|
||||
if echo "${modes}" | grep -Eqw "dense_vector|statevector"; then
|
||||
run_dense_mode=true
|
||||
fi
|
||||
|
||||
if echo "${modes}" | grep -qw "expectation"; then
|
||||
run_expectation_mode=true
|
||||
fi
|
||||
|
||||
if [[ "${run_dense_mode}" == true && ${#state_cfgs[@]} -eq 0 ]]; then
|
||||
echo "No dense-vector JSON configs found in ${script_dir}" >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if [[ "${run_expectation_mode}" == true && ${#expectation_cfgs[@]} -eq 0 ]]; then
|
||||
echo "No expectation JSON configs found in ${script_dir}" >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
require_existing_configs "dense-vector" "${state_cfgs[@]}"
|
||||
require_existing_configs "expectation" "${expectation_cfgs[@]}"
|
||||
|
||||
# On Prism, Intel MPI needs shared-memory fabric for single-node runs.
|
||||
if [[ -z "${I_MPI_FABRICS:-}" ]]; then
|
||||
export I_MPI_FABRICS=shm
|
||||
fi
|
||||
|
||||
echo "Dense-vector configs : ${state_cfgs[*]:-none}"
|
||||
echo "Expectation configs : ${expectation_cfgs[*]:-none}"
|
||||
|
||||
for nqubits in ${nqubits_list}; do
|
||||
for circuit in ${circuits}; do
|
||||
circuit_opts="nlayers=${nlayers}"
|
||||
# These circuits do not use nlayers — omit it to avoid unknown-option errors.
|
||||
if [[ "${circuit}" == "qft" || "${circuit}" == "QFT" || \
|
||||
"${circuit}" == "supremacy" || "${circuit}" == "Supremacy" || \
|
||||
"${circuit}" == "bv" || "${circuit}" == "bernstein-vazirani" || \
|
||||
"${circuit}" == "hs" || "${circuit}" == "hidden-shift" || \
|
||||
"${circuit}" == "qaoa" || "${circuit}" == "qv" || \
|
||||
"${circuit}" == "quantum-volume" ]]; then
|
||||
circuit_opts=""
|
||||
fi
|
||||
|
||||
echo "===== nqubits=${nqubits} circuit=${circuit} np=${np} ====="
|
||||
|
||||
# dense_vector is the preferred name; statevector is kept as a legacy alias.
|
||||
if [[ "${run_dense_mode}" == true ]]; then
|
||||
for cfg_name in "${state_cfgs[@]}"; do
|
||||
state_cfg_path="${script_dir}/${cfg_name}"
|
||||
echo " [dense_vector MPI] cfg=${cfg_name}"
|
||||
mpirun -np "${np}" python compare.py \
|
||||
--circuit "${circuit}" \
|
||||
${circuit_opts:+--circuit-options "${circuit_opts}"} \
|
||||
--nqubits "${nqubits}" \
|
||||
--filename "${filename}" \
|
||||
--library-options backend=qibotn,platform=quimb,computation_settings=${state_cfg_path} \
|
||||
--nreps "${nreps}" \
|
||||
--precision "${precision}"
|
||||
done
|
||||
fi
|
||||
|
||||
if [[ "${run_expectation_mode}" == true ]]; then
|
||||
for cfg_name in "${expectation_cfgs[@]}"; do
|
||||
exp_cfg_path="${script_dir}/${cfg_name}"
|
||||
echo " [expectation MPI] cfg=${cfg_name}"
|
||||
mpirun -np "${np}" python compare.py \
|
||||
--circuit "${circuit}" \
|
||||
${circuit_opts:+--circuit-options "${circuit_opts}"} \
|
||||
--nqubits "${nqubits}" \
|
||||
--filename "${filename}" \
|
||||
--library-options backend=qibotn,platform=quimb,computation_settings=${exp_cfg_path} \
|
||||
--nreps "${nreps}" \
|
||||
--precision "${precision}"
|
||||
|
||||
run_qibojit_reference "${nqubits}" "${circuit}" "${circuit_opts}" "${cfg_name}"
|
||||
done
|
||||
fi
|
||||
|
||||
echo
|
||||
done
|
||||
done
|
||||
Reference in New Issue
Block a user