NVIDIA cuQuantum SDK

repository·main·Indexed 19 days ago

https://github.com/nvidia/cuquantum

A high-performance library designed to accelerate quantum science simulations. This repository provides open-source components, samples, and the nv-quantum-benchmarks suite for benchmarking quantum circuits and APIs across various frontends (e.g., Qiskit, CUDA-Q) and backends (e.g., cutn, cusvaer). It includes documentation on building custom MPI CommPlugin extensions for multi-node state vector simulators and guides for dynamically linking projects to CUDA and cuQuantum Python wheels.

Tokens
18.5K
Snippets
51
Records
81
Agent score
66%

What's inside cuQuantum

  1. Overview of cuStateVec Ex Sample Capabilities

    main

    The custatevecEx samples demonstrate various advanced quantum simulation workflows:

    Single Device Workflows

    • Algorithm Simulation: estimate_pi.cpp demonstrates Phase Estimation using custatevecExApplyMatrix() and SVUpdater.
    • Pauli Operations: pauli_functions.cpp shows Pauli rotations and expectation value calculations.
    • Noise Modeling: noise_channel.cpp demonstrates the "build once, apply many times" pattern for quantum noise modeling.
    • State Manipulation: index_bit_permutation.cpp (qubit reordering) and quantum_state_initialization.cpp (advanced initialization and wire ordering).

    Distributed and Interoperable Workflows

    • Interoperability: interoperability_dot.cpp demonstrates using cuStateVec Ex pointers and CUDA streams with cuBLAS for dot product computations.
    • Scalability: quantum_volume.cpp provides performance metrics across different qubit counts.
    • Deployment Inspection: substatevector_indices.cpp helps visualize how statevectors are distributed across different deployment schemes.
  2. Overview of the cuQuantum repository contents

    main

    The cuQuantum repository contains several components related to the NVIDIA cuQuantum SDK:

    • benchmarks: The NVIDIA Quantum Performance Benchmark Suite.
    • extra: Utility files for using the cuQuantum SDK and the cuQuantum Appliance container.
    • python: The open-source cuQuantum Python project, available via Conda and PyPI.
    • samples: C/C++ sample code demonstrating usage of the cuQuantum SDK.
  3. Understand the benchmark output data format

    main

    Benchmark results are stored in the data directory as JSON files, organized by benchmark type.

    Data is structured hierarchically: json_data[nqubits][sim_config_hash].

    The sim_config_hash is a unique identifier generated from the combination of the frontend, backend, and run_env. This ensures that if any part of the configuration changes, the data is recorded under a new hash, preventing collisions.

    To perform analysis, it is recommended to iterate over all recorded sim_config_hash entries for a given qubit count.

  4. Generate CUDA-specific wheels for different major versions

    main
    To take advantage of CUDA minor version compatibility, you can generate different wheels for different CUDA major versions (e.g., cupy-cuda11x for CUDA 11, cupy-cuda12x for CUDA 12). This is typically achieved by populating the wheel name at build time, though note that this may be incompatible with static metadata-based approaches like PEP 621.
  5. Developer constraints for cuQuantum Python JAX

    main

    When developing with or around the cuQuantum Python JAX extension, be aware of the following constraints:

    • No Editable Installs: cuQuantum Python JAX does not support pip install -e . (editable mode).
    • Installation Location: Both cuquantum-python and cuquantum-python-jax must be installed into the same site-packages directory.
    • Dependency Assumption: The JAX extension assumes that cuquantum-python is already available in the current site-packages directory.
  6. How dynamic linking to NVIDIA wheels works

    main

    NVIDIA's CUDA Toolkit and cuQuantum SDK are distributed as Python wheels that repackage the proprietary binaries. These wheels follow the standard Linux directory structure (include/ and lib/), but they have a critical limitation: they do not contain symlinks (e.g., you will find libcusolver.so.11.x.x but not the libcusolver.so.11 symlink).

    To successfully build against these wheels, developers must:

    1. Target specific SONAMEs: Use the -l:filename linker flag to specify the exact filename (e.g., -l:libcutensornet.so.2) instead of the generic library name.
    2. Manage RPATH: Use linker flags to set the rpath (Run-time search path). This tells the dynamic loader where to find the .so files at runtime.
      • Use --disable-new-dtags to ensure the linker uses DT_RPATH instead of DT_RUNPATH when using nvcc.
      • Best Practice: For relocatable packages, compute the rpath relative to the executable itself using $ORIGIN rather than absolute paths.
    3. Use auditwheel --exclude: When building your own Python wheels, use auditwheel --exclude to allowlist these NVIDIA shared libraries. This prevents auditwheel from attempting to copy the massive CUDA/cuQuantum binaries into your wheel, keeping your package size small and compliant with PyPI limits.
  7. Declare run-time dependencies on CTK/cuQuantum wheels

    main

    When generating your own Python wheels that depend on cuQuantum, you should declare run-time dependencies on the CTK/cuQuantum wheels using your build system's standard mechanism. Common methods include:

    • setuptools: Use install_requires in the setup() function within setup.py.
    • PEP 621: Use dependencies in the [project] table of pyproject.toml.
    • setup.cfg: Use install_requires in the [options] section of setup.cfg.
  8. Run cuPauliProp sample executables

    main

    After compilation, you can run the sample executables directly. If you encounter library loading issues, ensure your CUDA library path is included in LD_LIBRARY_PATH.

    Note on LD_LIBRARY_PATH:

    export LD_LIBRARY_PATH=$CUDA_PATH/lib64:$LD_LIBRARY_PATH
    ### Kicked Ising circuit example
    ```bash
    ./kicked_ising_example

    Fused operators benchmark example

    ./fused_operators_example
  9. Build cuQuantum Python JAX from source

    main

    To build the JAX extension from source, follow these steps:

    1. Compile cuQuantum Python from source first (refer to the main cuQuantum Python GitHub instructions).
    2. Navigate to the python/extensions directory.
    3. Run the configuration script to generate the CUDA-specific pyproject.toml:
      ./configure.sh
    4. Install the package using pip:
      pip install .

    Note: The CUDA version is automatically detected from the $CUDA_PATH environment variable. The resulting wheel will be named cuquantum-python-jax-cu12 or cuquantum-python-jax-cu13 based on that detection.

    ./configure.sh
    pip install .
  10. Install cuTensorNet samples on Linux

    main

    To compile the cuTensorNet samples, you must define several environment variables pointing to the required libraries. You can use either make or cmake for the build process.

    Required Environment Variables:

    • CUDA_PATH: Path to the CUDA Toolkit.
    • CUTENSOR_ROOT: Path to the cuTENSOR library.
    • CUTENSORNET_ROOT: Path to the cuTensorNet library.
    • MPI_ROOT: Path to your MPI installation (required if using make).

    Note on Library Paths: Depending on your installation, you may need to update LD_LIBRARY_PATH to include the CUDA and cuTENSOR library directories.

    # Using make
    export CUDA_PATH=<path_to_cuda_root>
    export CUTENSOR_ROOT=<path_to_cutensor_root>
    export CUTENSORNET_ROOT=<path_to_cutensornet_root>
    export MPI_ROOT=<path_to_mpi_root>
    make -j
    
    # Using cmake
    export CUDA_PATH=<path_to_cuda_root>
    export CUTENSOR_ROOT=<path_to_cutensor_root>
    export CUTENSORNET_ROOT=<path_to_cutensornet_root>
    cmake . && make -j
    
    # Potential LD_LIBRARY_PATH update
    export LD_LIBRARY_PATH=$CUDA_PATH/lib64:$CUTENSOR_ROOT/lib:$LD_LIBRARY_PATH
  11. Compute gradients via back-propagation

    main

    To compute gradients of a tensor network with respect to specific input tensors, use the following workflow:

    1. Mark Tensors for Gradients: Use cutensornetNetworkSetAttribute to identify which input tensors require gradient computation.
    2. Setup Cache for Gradients:
      • Query the required cache size using cutensornetWorkspaceGetMemorySize with the CUTENSORNET_WORKSPACE_CACHE kind.
      • Provide the memory using cutensornetWorkspaceSetMemory. This cache holds intermediate data needed for the backward pass.
    3. Execute Backward Pass:
      • Call cutensornetNetworkPrepareGradientsBackward.
      • Call cutensornetNetworkComputeGradientsBackward to perform the actual computation.
    4. Cleanup: Use cutensornetWorkspacePurgeCache to clear the cache and prepare for the next gradient calculation.