qsim

repository·main·Indexed 20 days ago

https://github.com/quantumlib/qsim

A high-performance state-vector (Schrödinger) quantum circuit simulator for C++ and Python (via the qsimcirq package). It is optimized for speed using gate fusion, vectorization (AVX/FMA), multithreading (OpenMP), and GPU support. qsim can be used as a simulation library for Cirq and supports various GPU backends, including native qsim, NVIDIA cuQuantum SDK/cuStateVec, and the cuQuantum Appliance for multi-GPU workloads.

Tokens
34.3K
Snippets
109
Records
154
Agent score
72%

What's inside qsim

  1. Available simulation operations in qsim

    main

    Depending on the simulator chosen, you can perform the following operations:

    OperationqsimqsimhMPS
    Determine final state vectorYesNoNo
    Sample resultsYesNoNo
    Calculate amplitudes for specific bitstringsYesYesNo
    Simulate low-entanglement circuits (approximate)NoNoYes
  2. Choose a qsim GPU backend option

    main

    Before setting up GPU-based simulation, decide which of the three available backend options fits your needs:

    1. Native qsim GPU backend: Uses the native qsim implementation for GPU acceleration.
    2. NVIDIA cuQuantum backend: Uses NVIDIA's cuQuantum as a backend for the latest version of qsim.
    3. cuQuantum Appliance: Runs in a Docker container with a modified version of qsim. Required if you plan to do multi-GPU simulations.
  3. Optimize noisy simulation performance with Kraus operators

    main

    The impact of noise on simulation performance depends on the error types (decoherence, depolarizing, coherent, or readout errors) and how they are represented using Kraus operator formalism:

    • Best performance: When all Kraus operators are proportional to unitary matrices (e.g., using only a depolarizing channel).
    • Reduced performance: Using noise that cannot be represented with Kraus operators proportional to unitary matrices can slow down simulations by up to a factor of 6 compared to a depolarizing channel.
    • Noise levels: Noisy simulations generally run faster when noise levels are lower (i.e., when one Kraus operator dominates).
  4. Use multinode simulation for parallel workloads

    main

    Multinode simulation is effective when your workload can be parallelized:

    • Noisy simulations: Trajectories (repetitions/iterations) are "embarrassingly parallelizable" and can be distributed over multiple nodes using an automated workflow.
    • Noiseless simulations: A large number of independent noiseless circuits can also be distributed across multiple compute nodes.
  5. How the hybrid Schrödinger-Feynman method works in qsimh

    main

    The qsimh applications (e.g., qsimh_base.x, qsimh_amplitudes.x) use a hybrid Schrödinger-Feynman method. The lattice is split into two parts using a cut. The gates on the cut are divided into three segments:

    1. Prefix gates (-p): Gates applied before the first checkpoint. There is no summation over these paths.
    2. Root gates (-r): Gates applied between the first and second checkpoint.
    3. Suffix gates: The remaining gates on the cut (calculated as Total gates on cut - p - r).

    A two-level checkpointing scheme is used to improve performance. The full summation over all paths for the root and suffix gates is performed.

    Key Configuration Concepts:

    • Lattice Splitting (-k): Defines how the lattice is split. For optimal performance, split the grid into roughly equal parts with the fewest cuts possible.
    • Prefix Path (-w): Specifies the path for the prefix gates (bit-shifted path indices). This is essential for distributed execution.
    • Suffix Selection: For performance, suffix gates should typically be the gates on the cut with the maximum "time."
  6. Understand the Matrix Product State (MPS) Simulator

    main

    The MPS simulator is a memory-efficient alternative to the standard state-vector simulator. Instead of storing an exponentially large vector, it represents the quantum state as a chain of tensors (one per qubit).

    Key Concepts

    • Bond Dimension (bond_dim): Controls the amount of entanglement the representation can capture. A higher bond dimension increases accuracy but uses more memory and computation time.
    • Approximation: MPS provides approximate results for highly entangled circuits. When a gate creates entanglement exceeding the bond_dim, the simulator uses Singular Value Decomposition (SVD) to truncate the state, keeping only the top bond_dim singular values.
    • Best Use Cases: Low-entanglement circuits (e.g., 1D nearest-neighbor circuits, shallow QAOA) or circuits with many qubits but low depth.

    Limitations

    • Gate Support: Only 1-qubit and 2-qubit gates are supported. 3+ qubit gates and controlled gates are not yet implemented.
    • Connectivity: 2-qubit gates must act on adjacent qubits. Non-adjacent gates require manual SWAP networks.
    • Interface: Currently C++ only; there is no Python interface via qsimcirq.
    • Functionality: Expectation values are not yet implemented.
  7. Optimize gate fusion using the 'f' parameter

    main

    The f parameter defines the maximum number of qubits allowed per fused gate. Users should experiment with different f values to optimize their specific simulation setup.

    • CPU optimization: For large circuits on CPUs with a small number of threads (e.g., 4 to 8 threads), f=2 or f=3 may be optimal depending on circuit structure.
    • Avoid f=6: A value of f=6 is rarely optimal.
  8. Note on small circuit performance (< 20 qubits)

    main
    For circuits with fewer than 20 qubits, qsim is not specifically optimized. The performance is often dominated by the qsimcirq translation layer overhead. This overhead can be significant enough to mask the expected $2^N$ runtime growth.
  9. Estimate qsim simulation runtime

    main

    Simulation runtime in qsim scales based on the number of qubits ($N$) and circuit depth. Beyond 20 qubits, runtime grows linearly with circuit depth.

    • Noiseless simulations: Runtime grows at a rate of $2^N$.
    • Noisy simulations: Runtime grows at a rate of $2^N$ multiplied by the number of iterations performed.
  10. Estimate memory requirements for qsim simulations

    main

    You can estimate the memory required for an $N$-qubit circuit using the following rule of thumb:

    ${\text{memory required}} = 8 \cdot 2^N \text{ bytes}$

    Additionally, because qsim performs best when utilizing the maximum number of threads, it is recommended to use high-bandwidth memory (above 100GB/s) for multi-threaded simulations.

  11. Choose the right qsim simulator for your workload

    main

    The qsim repository provides three distinct simulation engines, each suited for different hardware constraints and circuit types:

    • qsim: A Schrödinger state-vector simulator optimized for single machines. It uses AVX/FMA vector operations, OpenMP multithreading, and gate fusion. It produces the full state vector, allowing for repeated sampling from a single execution.
      • Capacity: ~30 qubits with ~16GB RAM (each additional qubit doubles RAM requirements).
    • qsimh: A hybrid Schrödinger-Feynman simulator designed for parallel execution on clusters. Instead of the full state vector, it calculates amplitudes for user-specified bitstrings. This approach allows for simulating larger systems.
      • Capacity: Can support 50 qubits or more through parallelization.
    • MPS: A truncated Matrix Product State simulator (C++ only). It represents the state as a chain of tensors with a configurable "bond dimension". It is highly memory-efficient for circuits with low entanglement (shallow or 1D-structured circuits) but provides an approximate result for highly entangled states.
  12. How qsim handles gate decompositions and parameters

    main

    The qsimcirq interface provides several automated features for Cirq circuits:

    • Gate Decompositions: Circuits are automatically decomposed into the qsim gate set using Cirq's decompose operation. If a gate cannot be decomposed, qsim attempts to parse it as a raw matrix if one is provided.
    • Parametrized Circuits: QSimCircuit objects support parameterized gates. Values are assigned using Cirq's ParamResolver during the simulation process.