-
Qiskit
Qiskit
Qiskit on avoimen lähdekoodin ohjelmisto kvanttitietokoneiden kanssa työskentelyyn piirien, pulssien ja algoritmien tasolla. Tämä sivu sisältää tietoa kvanttisimulaatioiden ajamisesta qiskitillä singularity-kontin sisällä. Jos etsit tietoa töiden ajamisesta fyysisillä kvanttitietokoneilla qiskitillä, katso tämä dokumentaatio: Kvanttitöiden ajaminen.
Uutiset
19.02.2025 Asennettiin qiskit/1.3.2 singularity-konttiin LUMIin kaikkien tärkeimpien Qiskit-pakettien kanssa ja
lisättiin tuki monisolmuiselle natiiville Cray MPI GPU -kiihdytykselle, mikä mahdollistaa suorituskykyiset monisolmuiset simulaatiot
jopa 44* kubittiin asti. Qiskit-aer on myös päivitetty versioon 0.16
Saatavilla
Tällä hetkellä tuetut Qiskit-versiot:
| Versio | Moduuli | Puhti | Mahti | LUMI | Huomautukset |
|---|---|---|---|---|---|
| 1.1.1 | qiskit/1.1.1 |
X | X | ||
| 1.3.2 | X | Natiivi Cray MPI GPU-tuella |
Sisältää kaikki tärkeimmät Qiskit-paketit (Terra, Nature, Aer jne.) sekä GPU-kiihdytyksen. Paketit qiskit/1.1.1 ja qiskit/1.3.2 sisältävät հետևavat qiskit-liitännäiset:
Jos huomaat, että jokin paketti puuttuu, voit usein asentaa sen itse komennolla pip install --user.
Katso Pythonin käyttöoppaastamme
lisätietoja siitä, miten voit asentaa paketteja itse. Jos mielestäsi jokin tärkeä
Qiskitiin liittyvä paketti pitäisi sisällyttää CSC:n tarjoamaan moduuliin, ole hyvä ja
ota yhteyttä asiakastukeemme.
Kaikki moduulit perustuvat kontteihin, joissa käytetään Apptaineria (aiemmin tunnettu nimellä Singularity).
Tarjolla on wrapper-skriptejä, jotta yleiset komennot kuten python,
python3, pip ja pip3 toimivat normaalisti. Lisätietoja löytyy kohdasta
CSC:n yleiset ohjeet Apptainer-konttien ajamiseen.
Lisenssi
Qiskit on lisensoitu Apache License 2.0 -lisenssillä.
Käyttö
Oletusversion käyttämiseksi alusta se komennolla:
Jos haluat käyttää tiettyä versiota (katso yllä saatavilla olevat versiot), käytä:
Esimerkki sbatch- ja python-skriptistä - yhden solmun simulaatiot Puhdissa, Mahdissa ja LUMIssa
Esimerkki <sbatch_script_name>.sh-skriptistä yhden GPU:n ja kahden CPU-ytimen varaamiseen yhdellä solmulla Puhdissa ja Mahdissa sekä kaikkien CPU/GPU-resurssien varaamiseen yhdellä solmulla LUMIn standard-g-partitiolla:
#!/bin/bash
#SBATCH --job-name=aer_job
#SBATCH --output=aer_job.o%j
#SBATCH --error=aer_job.e%j
#SBATCH --account=<project>
#SBATCH --partition=gpu
#SBATCH --ntasks=1
#SBATCH --cpus-per-task=2
#SBATCH --mem=8G
#SBATCH --time=1:00:00
#SBATCH --gres=gpu:v100:1
module load qiskit
srun python myprog.py <options>
#!/bin/bash
#SBATCH --job-name=aer_job
#SBATCH --output=aer_job.o%j
#SBATCH --error=aer_job.e%j
#SBATCH --account=<project_id>
#SBATCH --time=2:00:00
#SBATCH --partition=standard-g
#SBATCH --nodes=1
#SBATCH --gpus-per-node=8
#SBATCH --ntasks-per-node=1
#SBATCH --cpus-per-task=56
export LUMI_QISKIT_SINGULARITY_CONTAINER_PATH=/appl/local/quantum/qiskit/qiskit_1.3.2_csc.sif
export WRAPPER_PATH=/appl/local/quantum/qiskit/run-singularity
echo "NODES : ${SLURM_NNODES}"
echo "TASKS PER NODE : ${SLURM_NTASKS_PER_NODE}"
echo "CPUS PER TASK : ${SLURM_CPUS_PER_TASK}"
echo "GPUS PER NODE : ${SLURM_GPUS_PER_NODE}"
echo "GPUS PER TASK : ${SLURM_GPUS_PER_TASK}"
mask=mask_cpu:0xfe000000000000,0xfe00000000000000,0xfe0000,0xfe000000,0xfe,0xfe00,0xfe00000000,0xfe0000000000
export MPICH_GPU_SUPPORT_ENABLED=1
srun --cpu-bind=$mask $WRAPPER_PATH $LUMI_QISKIT_SINGULARITY_CONTAINER_PATH python myprog.py
Esimerkki <myprog>.py-python-skriptistä yhden solmun simulaatioihin. Huomaa, että tämä koodi on tarkoitettu vain syntaksin havainnollistamiseen ja toimii vain yhdellä solmulla. LUMI-simulaatioissa katso alla olevasta taulukosta resurssivaatimukset suhteessa simuloitavien kubittien määrään.
from qiskit import QuantumCircuit
from qiskit_aer import AerSimulator
## CHOOSE PARAMETERS
num_qubits = 5 # Number of qubits in the circuit
num_shots = 1000 # How many times we sample the circuit
## CREATE CIRCUIT FOR N-QUBIT GHZ-STATE
circuit = QuantumCircuit(num_qubits)
circuit.h(0)
for i in range(1,num_qubits):
circuit.cx(0,i)
circuit.measure_all()
## INITIALIZE SIMULATOR BACKEND THAT RUNS ON GPU
simulator = AerSimulator(method="statevector", device="GPU")
## RUN THE CIRCUIT WITH CUSTATEVEC ENABLED
result_statevec = simulator.run(circuit, shots=num_shots, seed_simulator=12345, cuStateVec_enable=True).result()
## PRINT RESULTS
counts = result_statevec.get_counts()
print(f"Counts:, {counts}")
from qiskit import QuantumCircuit
from qiskit_aer import AerSimulator
## CHOOSE PARAMETERS
num_qubits = 5 # Number of qubits in the circuit
num_shots = 1000 # How many times we sample the circuit
## CREATE CIRCUIT FOR N-QUBIT GHZ-STATE
circuit = QuantumCircuit(num_qubits)
circuit.h(0)
for i in range(1,num_qubits):
circuit.cx(0,i)
circuit.measure_all()
## INITIALIZE SIMULATOR BACKEND THAT RUNS ON GPU
simulator = AerSimulator(method="statevector", device="GPU")
## RUN THE CIRCUIT WITH CUSTATEVEC ENABLED
result_statevec = simulator.run(circuit, shots=num_shots, seed_simulator=12345, cuStateVec_enable=True).result()
## PRINT RESULTS
counts = result_statevec.get_counts()
print(f"Counts:, {counts}")
from qiskit import QuantumCircuit, transpile
from qiskit.transpiler import CouplingMap
from qiskit_aer import AerSimulator
from qiskit.circuit.library import QuantumVolume
## CHOOSE PARAMETERS
num_qubits = 34 # Number of qubits in the circuit
circuit_depth = 30 # Layers in quantum volume circuit
num_shots = 1000 # How many times we sample the circuit
sim_method = 'statevector' # Choosing simulation method
sim_device = 'GPU' # Choose whether simulation is run on CPUs or GPUs
use_cache_blocking = True # Cache blocking technique parallelizes simulation by distributing quantum states into distributed memory space
num_blocking_qubits = 29 # Defines chunk size for cache blocking. Must be smaller than "qubits-log2(number-of-processes)"
use_batched_shots = True # Distributing shots to multiple processess
num_parallel_experiments = 1 # Does not seem to do anything when running with MPI, probably intended to be used with multithreading
## INITIALIZE SIMULATOR BACKEND
simulator = AerSimulator(method=sim_method, device=sim_device, batched_shots_gpu=use_batched_shots)
## CREATE QUANTUM VOLUME CIRCUIT
circuit = QuantumVolume(num_qubits, circuit_depth, seed=0)
circuit.measure_all()
## TRANSPILE THE CIRCUIT FOR SPECIFIC COUPLING MAP
coupling_map = CouplingMap.from_full(num_qubits)
transpiled_circuit = transpile(circuit, simulator, coupling_map=coupling_map, optimization_level=0)
## RUN THE SIMULATION
result_statevec = simulator.run(transpiled_circuit, shots=num_shots, seed_simulator=12345, blocking_enable=use_cache_blocking, blocking_qubits=num_blocking_qubits, max_parallel_experiments=num_parallel_experiments).result()
## GATHER THE RESULTS AND SOME ADDITIONAL METADATA
counts = result_statevec.get_counts()
result_dict = result_statevec.to_dict()
metadata = result_dict['metadata']
input_data = {'Circuit' : 'Quantum Volume', 'Qubits' : num_qubits, 'Depth' : circuit_depth, 'Shots' : num_shots, 'Batched Shots' : use_batched_shots , 'Device' : sim_device, 'Simulation Method' : sim_method}
if (use_cache_blocking):
num_chunks = 2**(num_qubits - num_blocking_qubits)
input_data['Blocking Qubits'] = num_blocking_qubits
input_data['Number of Chunks'] = num_chunks
## PRINT FOR ONE MPI RANK
if (metadata['mpi_rank'] == 0):
print()
print(f"Input data: {input_data}")
print(f"Metadata: {metadata}")
#print(f"Results: {counts}")
print(f"-------------------- \n")
## PRINT ALL MPI PROCESSES
#print(f"Input data: {input_data}")
#print(f"Metadata: {metadata}")
#print(f"-------------------- \n")
Lähetä skripti komennolla sbatch <sbatch_script_name>.sh
Esimerkki sbatch- ja python-skriptistä - monisolmuiset simulaatiot, jotka hyödyntävät natiivia HPE Cray MPI:tä GPU-kiihdytyksellä LUMIssa
Esimerkki <sbatch_MPI_script_name>.sh-skriptistä simulaation ajamiseen usealla LUMI-solmulla standard-g-partitiossa käyttäen kaikkia GPU:ita ja kaikkia CPU-ytimiä solmulla. Tämä on tarkoitettu simulaatioille, joissa on 35 kubittia tai enemmän (enintään 45* kubittia - katso alla olevasta taulukosta suositellut resurssivaraukset simuloitavien kubittien määrän perusteella):
#!/bin/bash
## Here is an example sbatch script for a 38 qubit quantum volume simulation (myprog_MPI.py) using 16 nodes
#SBATCH --job-name=aer_job
#SBATCH --output=aer_job.o%j
#SBATCH --error=aer_job.e%j
#SBATCH --account=<project_id>
#SBATCH --time=2:00:00
#SBATCH --partition=standard-g
#SBATCH --nodes=16
#SBATCH --gpus-per-node=8
#SBATCH --ntasks-per-node=8
#SBATCH --cpus-per-task=7
export LUMI_QISKIT_SINGULARITY_CONTAINER_PATH=/appl/local/quantum/qiskit/qiskit_1.3.2_csc.sif
export GPU_WRAPPER_PATH=/appl/local/quantum/qiskit/run-singularity-with-gpu-affinity
mask=mask_cpu:0xfe000000000000,0xfe00000000000000,0xfe0000,0xfe000000,0xfe,0xfe00,0xfe00000000,0xfe0000000000
export MPICH_GPU_SUPPORT_ENABLED=1
srun --cpu-bind=$mask $GPU_WRAPPER_PATH $LUMI_QISKIT_SINGULARITY_CONTAINER_PATH python myprog_MPI.py
Pieni koodiesimerkki <myprog_MPI>.py-python-skriptistä, jossa käytetään 38 kubittia ja jonka suosittelemme ajamaan 16 solmulla
*katso viitteeksi alla oleva suositeltu resurssivaraustaulukko
from qiskit import QuantumCircuit, transpile
from qiskit.transpiler import CouplingMap
from qiskit_aer import AerSimulator
from qiskit.circuit.library import QuantumVolume
## CHOOSE PARAMETERS
num_qubits = 38 # Number of qubits in the circuit
circuit_depth = 30 # Layers in quantum volume circuit
num_shots = 1000 # How many times we sample the circuit
sim_method = 'statevector' # Choosing simulation method
sim_device = 'GPU' # Choose whether simulation is run on CPUs or GPUs
use_cache_blocking = True # Cache blocking technique parallelizes simulation by distributing quantum states into distributed memory space
num_blocking_qubits = 29 # Defines chunk size for cache blocking. Must be smaller than "qubits-log2(number-of-processes)"
use_batched_shots = True # Distributing shots to multiple processess
num_parallel_experiments = 1 # Does not seem to do anything when running with MPI, probably intended to be used with multithreading
## INITIALIZE SIMULATOR BACKEND
simulator = AerSimulator(method=sim_method, device=sim_device, batched_shots_gpu=use_batched_shots)
## CREATE QUANTUM VOLUME CIRCUIT
circuit = QuantumVolume(num_qubits, circuit_depth, seed=0)
circuit.measure_all()
## TRANSPILE THE CIRCUIT FOR SPECIFIC COUPLING MAP
coupling_map = CouplingMap.from_full(num_qubits)
transpiled_circuit = transpile(circuit, simulator, coupling_map=coupling_map, optimization_level=0)
## RUN THE SIMULATION
result_statevec = simulator.run(transpiled_circuit, shots=num_shots, seed_simulator=12345, blocking_enable=use_cache_blocking, blocking_qubits=num_blocking_qubits, max_parallel_experiments=num_parallel_experiments).result()
## GATHER THE RESULTS AND SOME ADDITIONAL METADATA
counts = result_statevec.get_counts()
result_dict = result_statevec.to_dict()
metadata = result_dict['metadata']
input_data = {'Circuit' : 'Quantum Volume', 'Qubits' : num_qubits, 'Depth' : circuit_depth, 'Shots' : num_shots, 'Batched Shots' : use_batched_shots , 'Device' : sim_device, 'Simulation Method' : sim_method}
if (use_cache_blocking):
num_chunks = 2**(num_qubits - num_blocking_qubits)
input_data['Blocking Qubits'] = num_blocking_qubits
input_data['Number of Chunks'] = num_chunks
## PRINT FOR ONE MPI RANK
if (metadata['mpi_rank'] == 0):
print()
print(f"Input data: {input_data}")
print(f"Metadata: {metadata}")
#print(f"Results: {counts}")
print(f"-------------------- \n")
## PRINT ALL MPI PROCESSES
#print(f"Input data: {input_data}")
#print(f"Metadata: {metadata}")
#print(f"-------------------- \n")
Lähetä skripti komennolla sbatch <sbatch_MPI_script_name>.sh
Ohjeet LUMIn resurssien varaamiseen
Statevector-simulaation vaatima muisti kaksinkertaistuu jokaisen lisätyn kubitin myötä. Käytettäessä 16 tavun tarkkuutta (qiskit-aerin oletus), LUMI tukee statevector-simulaatioita enintään 34 kubittiin yhdellä solmulla ja enintään 44* kubittiin 1024 solmulla cache blocking -tekniikkaa käyttäen. Cache blocking hyödyntää GPU-muistin hajautettuja muistialueita simulaation rinnakkaistamiseen. Hajautettujen prosessien koko määritellään blocking qubits -parametreilla, jotka eivät voi olla suurempia kuin yhden välimuistin koko. LUMIssa välimuistin tulisi vastata yhden GPU:n muistia, eikä blocking qubits -arvo saa olla suurempi kuin 29.
Alla oleva taulukko esittää esimerkkiparametreja Quantum Volume -piirin, jonka syvyys on 30, simulointiin eri kubittimäärillä LUMIn standard-g-partitiossa. Statevectorin vaatima muisti on laskettu 16 tavun tarkkuudella. Käytettyjen solmujen määrä vastaa kaksinkertaista statevectorin vaatimaa muistimäärää, mikä tuottaa optimaalisen suorituskyvyn varaamalla lisämuistia cache blockingia varten hajautettujen prosessien välisen tiedonvaihdon käsittelyyn. Huomaa, että nämä parametrit testattiin tietylle piirille. Solmujen määrän muuttaminen tai erilaisten piirien simulointi voi vaatia erilaisten blocking qubits -määrien määrittämistä.
Muistivaatimukset ja esimerkkiparametrit quantum volume -statevector-simulaatiolle, kun piirin syvyys on 30 ja tarkkuus 16 tavua
| # kubitteja | # blocking qubits | Suositeltu # solmuja | # gpus-per-node | # tasks-per-node | # gpus-per-task | # cpus-per-task | Kubittimuistin vaatimukset |
|---|---|---|---|---|---|---|---|
| 1 | 0 | 1 | 8 | 1 | 8 | 56 | 32 tavua |
| 2 | 0 | 1 | 8 | 1 | 8 | 56 | 64 |
| 3 | 0 | 1 | 8 | 1 | 8 | 56 | 128 |
| 4 | 0 | 1 | 8 | 1 | 8 | 56 | 256 |
| 5 | 0 | 1 | 8 | 1 | 8 | 56 | 512 |
| 6 | 0 | 1 | 8 | 1 | 8 | 56 | 1024 |
| 7 | 0 | 1 | 8 | 1 | 8 | 56 | 2 kilotavua |
| 8 | 0 | 1 | 8 | 1 | 8 | 56 | 4 |
| 9 | 0 | 1 | 8 | 1 | 8 | 56 | 8 |
| 10 | 0 | 1 | 8 | 1 | 8 | 56 | 16 |
| 11 | 0 | 1 | 8 | 1 | 8 | 56 | 32 |
| 12 | 0 | 1 | 8 | 1 | 8 | 56 | 64 |
| 13 | 0 | 1 | 8 | 1 | 8 | 56 | 128 |
| 14 | 0 | 1 | 8 | 1 | 8 | 56 | 256 |
| 15 | 0 | 1 | 8 | 1 | 8 | 56 | 512 |
| 16 | 0 | 1 | 8 | 1 | 8 | 56 | 1024 |
| 17 | 0 | 1 | 8 | 1 | 8 | 56 | 2 megatavua |
| 18 | 0 | 1 | 8 | 1 | 8 | 56 | 4 |
| 19 | 0 | 1 | 8 | 1 | 8 | 56 | 8 |
| 20 | 0 | 1 | 8 | 1 | 8 | 56 | 16 |
| 21 | 0 | 1 | 8 | 1 | 8 | 56 | 32 |
| 22 | 0 | 1 | 8 | 1 | 8 | 56 | 64 |
| 23 | 0 | 1 | 8 | 1 | 8 | 56 | 128 |
| 24 | 0 | 1 | 8 | 1 | 8 | 56 | 256 |
| 25 | 0 | 1 | 8 | 1 | 8 | 56 | 512 |
| 26 | 0 | 1 | 8 | 1 | 8 | 56 | 1024 |
| 27 | 0 | 1 | 8 | 1 | 8 | 56 | 2 gigatavua |
| 28 | 0 | 1 | 8 | 1 | 8 | 56 | 4 |
| 29 | 0 | 1 | 8 | 1 | 8 | 56 | 8 |
| 30 | 29 | 1 | 8 | 1 | 8 | 56 | 16 |
| 31 | 29 | 1 | 8 | 1 | 8 | 56 | 32 |
| 32 | 29 | 1 | 8 | 1 | 8 | 56 | 64 |
| 33 | 29 | 1 | 8 | 1 | 8 | 56 | 128 |
| 34 | 29 | 1 | 8 | 1 | 8 | 56 | 256 |
| 35 | 29 | 2 | 8 | 8 | 1 | 7 | 512 |
| 36 | 29 | 4 | 8 | 8 | 1 | 7 | 1024 |
| 37 | 29 | 8 | 8 | 8 | 1 | 7 | 2 teratavua |
| 38 | 29 | 16 | 8 | 8 | 1 | 7 | 4 |
| 39 | 29 | 32 | 8 | 8 | 1 | 7 | 8 |
| 40 | 29 | 64 | 8 | 8 | 1 | 7 | 16 |
| 41 | 29 | 128 | 8 | 8 | 1 | 7 | 32 |
| 42 | 29 | 256 | 8 | 8 | 1 | 7 | 64 |
| 43 | 29 | 512 | 8 | 8 | 1 | 7 | 128 |
| 44 | 29 | 1024 | 8 | 8 | 1 | 7 | 256 |
- Jos LUMIin lähetetty työ vaatii yli 1024 solmua, resurssien varaamista varten on tehtävä erityinen hero run -hakemus.
Enemmän kuin tehokas vähimmäismäärä LUMI-resursseja simulaatiolle
Simulaation suoritusaikaa on mahdollista nopeuttaa lisäämällä resurssien määrää tehokkaan vähimmäissolmujen määrän yli, joka vastaa kaksinkertaista statevectorin muistivaatimusta. Tällaisissa tapauksissa hajautettujen prosessien (MPI_Ranks) määrä ja varatut resurssit on harkittava huolellisesti. Blocking qubits tulee määrittää siten, ettei MPI-rankkeja ole enempää kuin välimuisteja. Alla olevat kaavat antavat suuntaa työn enimmäissolmujen määrän arviointiin.