|
6 | 6 | # the terms of the Apache License 2.0 which accompanies this distribution. # |
7 | 7 | # ============================================================================ # |
8 | 8 |
|
9 | | -import sys, os, numpy, platform, multiprocessing |
10 | | -from ._packages import get_library_path |
| 9 | +import multiprocessing |
| 10 | +import os |
| 11 | +import sys |
| 12 | +import warnings |
| 13 | +from pathlib import Path |
| 14 | +from typing import Dict, List, Tuple |
| 15 | + |
| 16 | +import numpy |
| 17 | + |
11 | 18 | from ._metadata import cuda_major |
| 19 | +from ._packages import get_library_path |
12 | 20 |
|
13 | | -# Set the multiprocessing start method to 'spawn' if not already set |
| 21 | +# Set the multiprocessing start method to `forkserver` if not already set |
14 | 22 | if multiprocessing.get_start_method(allow_none=True) is None: |
15 | 23 | multiprocessing.set_start_method('forkserver') |
16 | 24 |
|
| 25 | + |
| 26 | +# ============================================================================ # |
| 27 | +# CUDA Library Path Configuration |
| 28 | +# ============================================================================ # |
| 29 | +def _configure_cuda_library_paths() -> None: |
| 30 | + """ |
| 31 | + Sets the `CUDAQ_DYNLIBS` environment variable with paths to required |
| 32 | + CUDA libraries based on the detected CUDA version. |
| 33 | + """ |
| 34 | + # Skip if already configured or CUDA not detected |
| 35 | + if "CUDAQ_DYNLIBS" in os.environ or cuda_major is None: |
| 36 | + return |
| 37 | + |
| 38 | + # Library configuration: (package_name_template, library_filename_template) |
| 39 | + # Common libraries |
| 40 | + common_libs: Dict[str, Tuple[str, str]] = { |
| 41 | + 'curand': ('nvidia-curand', 'libcurand.so.10'), |
| 42 | + 'cutensor': ('cutensor-cu{cuda_major}', 'libcutensor.so.2'), |
| 43 | + 'custatevec': ('custatevec-cu{cuda_major}', 'libcustatevec.so.1'), |
| 44 | + 'cutensornet': ('cutensornet-cu{cuda_major}', 'libcutensornet.so.2'), |
| 45 | + 'cudensitymat': ('cudensitymat-cu{cuda_major}', 'libcudensitymat.so.0'), |
| 46 | + } |
| 47 | + |
| 48 | + # CUDA 12 specific libraries |
| 49 | + cuda_12_specific: Dict[str, Tuple[str, str]] = { |
| 50 | + 'cudart': |
| 51 | + ('nvidia-cuda_runtime-cu{cuda_major}', 'libcudart.so.{cuda_major}'), |
| 52 | + 'nvrtc': |
| 53 | + ('nvidia-cuda_nvrtc-cu{cuda_major}', 'libnvrtc.so.{cuda_major}'), |
| 54 | + 'cublas': ('nvidia-cublas-cu{cuda_major}', 'libcublas.so.{cuda_major}'), |
| 55 | + 'cublaslt': |
| 56 | + ('nvidia-cublas-cu{cuda_major}', 'libcublasLt.so.{cuda_major}'), |
| 57 | + 'cusolver': ('nvidia-cusolver-cu{cuda_major}', 'libcusolver.so.11'), |
| 58 | + 'cusolvermg': ('nvidia-cusolver-cu{cuda_major}', 'libcusolverMg.so.11'), |
| 59 | + } |
| 60 | + |
| 61 | + # CUDA 13 specific libraries |
| 62 | + cuda_13_specific: Dict[str, Tuple[str, str]] = { |
| 63 | + 'cudart': ('nvidia-cuda_runtime', 'libcudart.so.{cuda_major}'), |
| 64 | + 'nvrtc': ('nvidia-cuda_nvrtc', 'libnvrtc.so.{cuda_major}'), |
| 65 | + 'nvrtc_builtins': |
| 66 | + ('nvidia-cuda_nvrtc', 'libnvrtc-builtins.so.{cuda_major}.0'), |
| 67 | + 'cublas': ('nvidia-cublas', 'libcublas.so.{cuda_major}'), |
| 68 | + 'cublaslt': ('nvidia-cublas', 'libcublasLt.so.{cuda_major}'), |
| 69 | + 'cusolver': ('nvidia-cusolver', 'libcusolver.so.12'), |
| 70 | + 'cusolvermg': ('nvidia-cusolver', 'libcusolverMg.so.12'), |
| 71 | + } |
| 72 | + |
| 73 | + # Load dependencies first |
| 74 | + load_order: List[str] = [ |
| 75 | + 'cudart', 'curand', 'nvrtc', 'nvrtc_builtins', 'cublas', 'cublaslt', |
| 76 | + 'cusolver', 'cusolvermg', 'cutensor', 'custatevec', 'cutensornet', |
| 77 | + 'cudensitymat' |
| 78 | + ] |
| 79 | + |
| 80 | + # Select library configuration based on CUDA version |
| 81 | + if cuda_major == 12: |
| 82 | + lib_config = {**common_libs, **cuda_12_specific} |
| 83 | + elif cuda_major == 13: |
| 84 | + lib_config = {**common_libs, **cuda_13_specific} |
| 85 | + else: |
| 86 | + warnings.warn(f"Unsupported CUDA version {cuda_major}.", RuntimeWarning) |
| 87 | + return |
| 88 | + |
| 89 | + # Colon-separated list of library paths for `LinkedLibraryHolder` to load |
| 90 | + library_paths: List[str] = [] |
| 91 | + |
| 92 | + # Attempt to load each library |
| 93 | + for lib_name in load_order: |
| 94 | + if lib_name not in lib_config: |
| 95 | + continue |
| 96 | + |
| 97 | + package_template, lib_filename_template = lib_config[lib_name] |
| 98 | + |
| 99 | + try: |
| 100 | + # Resolve package and library names |
| 101 | + package_name = package_template.format(cuda_major=cuda_major) |
| 102 | + lib_filename = lib_filename_template.format(cuda_major=cuda_major) |
| 103 | + # Get library directory and construct full path |
| 104 | + lib_dir = get_library_path(package_name) |
| 105 | + lib_path = os.path.join(lib_dir, lib_filename) |
| 106 | + # Verify the library file exists |
| 107 | + if not os.path.isfile(lib_path): |
| 108 | + raise FileNotFoundError(f"Library file not found: {lib_path}") |
| 109 | + |
| 110 | + library_paths.append(lib_path) |
| 111 | + |
| 112 | + except Exception as exc: |
| 113 | + warnings.warn(f"Error loading {lib_name}: {exc}.", RuntimeWarning) |
| 114 | + continue |
| 115 | + |
| 116 | + os.environ["CUDAQ_DYNLIBS"] = ":".join(library_paths) |
| 117 | + |
| 118 | + |
17 | 119 | # CUDAQ_DYNLIBS must be set before any other imports that would initialize |
18 | | -# LinkedLibraryHolder. |
19 | | -if not "CUDAQ_DYNLIBS" in os.environ and not cuda_major is None: |
20 | | - try: |
21 | | - # common |
22 | | - curand_libs = get_library_path(f"nvidia-curand") |
23 | | - curand_path = os.path.join(curand_libs, "libcurand.so.10") |
24 | | - |
25 | | - if cuda_major == 12: |
26 | | - custatevec_libs = get_library_path(f"custatevec-cu{cuda_major}") |
27 | | - custatevec_path = os.path.join(custatevec_libs, |
28 | | - "libcustatevec.so.1") |
29 | | - |
30 | | - cutensornet_libs = get_library_path(f"cutensornet-cu{cuda_major}") |
31 | | - cutensornet_path = os.path.join(cutensornet_libs, |
32 | | - "libcutensornet.so.2") |
33 | | - |
34 | | - cudensitymat_libs = get_library_path(f"cudensitymat-cu{cuda_major}") |
35 | | - cudensitymat_path = os.path.join(cudensitymat_libs, |
36 | | - "libcudensitymat.so.0") |
37 | | - |
38 | | - cutensor_libs = get_library_path(f"cutensor-cu{cuda_major}") |
39 | | - cutensor_path = os.path.join(cutensor_libs, "libcutensor.so.2") |
40 | | - |
41 | | - cudart_libs = get_library_path( |
42 | | - f"nvidia-cuda_runtime-cu{cuda_major}") |
43 | | - cudart_path = os.path.join(cudart_libs, |
44 | | - f"libcudart.so.{cuda_major}") |
45 | | - |
46 | | - cuda_nvrtc_libs = get_library_path( |
47 | | - f"nvidia-cuda_nvrtc-cu{cuda_major}") |
48 | | - cuda_nvrtc_path = os.path.join(cuda_nvrtc_libs, |
49 | | - f"libnvrtc.so.{cuda_major}") |
50 | | - |
51 | | - cusolver_libs = get_library_path(f"nvidia-cusolver-cu{cuda_major}") |
52 | | - cusolver_path = os.path.join(cusolver_libs, f"libcusolver.so.11") |
53 | | - cusolvermg_path = os.path.join(cusolver_libs, |
54 | | - f"libcusolverMg.so.11") |
55 | | - |
56 | | - cublas_libs = get_library_path(f"nvidia-cublas-cu{cuda_major}") |
57 | | - cublas_path = os.path.join(cublas_libs, |
58 | | - f"libcublas.so.{cuda_major}") |
59 | | - cublaslt_path = os.path.join(cublas_libs, |
60 | | - f"libcublasLt.so.{cuda_major}") |
61 | | - |
62 | | - os.environ[ |
63 | | - "CUDAQ_DYNLIBS"] = f"{cudart_path}:{curand_path}:{cuda_nvrtc_path}:{cublaslt_path}:{cublas_path}:{cusolver_path}:{cusolvermg_path}:{cutensor_path}:{custatevec_path}:{cutensornet_path}:{cudensitymat_path}" |
64 | | - else: # CUDA 13 |
65 | | - custatevec_libs = get_library_path(f"custatevec-cu{cuda_major}") |
66 | | - custatevec_path = os.path.join(custatevec_libs, |
67 | | - "libcustatevec.so.1") |
68 | | - |
69 | | - cutensornet_libs = get_library_path(f"cutensornet-cu{cuda_major}") |
70 | | - cutensornet_path = os.path.join(cutensornet_libs, |
71 | | - "libcutensornet.so.2") |
72 | | - |
73 | | - cudensitymat_libs = get_library_path(f"cudensitymat-cu{cuda_major}") |
74 | | - cudensitymat_path = os.path.join(cudensitymat_libs, |
75 | | - "libcudensitymat.so.0") |
76 | | - |
77 | | - cutensor_libs = get_library_path(f"cutensor-cu{cuda_major}") |
78 | | - cutensor_path = os.path.join(cutensor_libs, "libcutensor.so.2") |
79 | | - |
80 | | - cudart_libs = get_library_path(f"nvidia-cuda_runtime") |
81 | | - cudart_path = os.path.join(cudart_libs, |
82 | | - f"libcudart.so.{cuda_major}") |
83 | | - |
84 | | - cuda_nvrtc_libs = get_library_path(f"nvidia-cuda_nvrtc") |
85 | | - cuda_nvrtc_path = os.path.join(cuda_nvrtc_libs, |
86 | | - f"libnvrtc.so.{cuda_major}") |
87 | | - cuda_nvrtc_builtin_path = os.path.join( |
88 | | - cuda_nvrtc_libs, f"libnvrtc-builtins.so.{cuda_major}.0") |
89 | | - |
90 | | - cublas_libs = get_library_path(f"nvidia-cublas") |
91 | | - cublas_path = os.path.join(cublas_libs, |
92 | | - f"libcublas.so.{cuda_major}") |
93 | | - cublaslt_path = os.path.join(cublas_libs, |
94 | | - f"libcublasLt.so.{cuda_major}") |
95 | | - |
96 | | - cusolver_libs = get_library_path(f"nvidia-cusolver") |
97 | | - cusolver_path = os.path.join(cusolver_libs, f"libcusolver.so.12") |
98 | | - cusolvermg_path = os.path.join(cusolver_libs, |
99 | | - f"libcusolverMg.so.12") |
100 | | - |
101 | | - os.environ[ |
102 | | - "CUDAQ_DYNLIBS"] = f"{cudart_path}:{curand_path}:{cuda_nvrtc_path}:{cuda_nvrtc_builtin_path}:{cublas_path}:{cublaslt_path}:{cusolver_path}:{cusolvermg_path}:{cutensor_path}:{custatevec_path}:{cutensornet_path}:{cudensitymat_path}" |
103 | | - except: |
104 | | - import importlib.util |
105 | | - package_spec = importlib.util.find_spec(f"cuda-quantum-cu{cuda_major}") |
106 | | - if not package_spec is None and not package_spec.loader is None: |
107 | | - print("Could not find a suitable cuQuantum Python package.") |
108 | | - pass |
| 120 | +# `LinkedLibraryHolder`. |
| 121 | +try: |
| 122 | + _configure_cuda_library_paths() |
| 123 | +except Exception as exc: |
| 124 | + print(f"Error configuring CUDA libraries: {exc}.") |
| 125 | + |
| 126 | + import importlib.util |
| 127 | + package_spec = importlib.util.find_spec(f"cuda-quantum-cu{cuda_major}") |
| 128 | + if not package_spec is None and not package_spec.loader is None: |
| 129 | + print("Could not find a suitable cuQuantum Python package.") |
| 130 | + pass |
| 131 | + |
| 132 | +# ============================================================================ # |
| 133 | +# Module Imports |
| 134 | +# ============================================================================ # |
109 | 135 |
|
110 | 136 | from .display import display_trace |
111 | 137 | from .kernel.kernel_decorator import kernel, PyKernelDecorator |
|
236 | 262 | orca = cudaq_runtime.orca |
237 | 263 |
|
238 | 264 |
|
| 265 | +# ============================================================================ # |
| 266 | +# Utility Functions |
| 267 | +# ============================================================================ # |
239 | 268 | def synthesize(kernel, *args): |
240 | 269 | # Compile if necessary, no-op if already compiled |
241 | 270 | kernel.compile() |
@@ -281,6 +310,9 @@ def __clearKernelRegistries(): |
281 | 310 | from .kernels import uccsd |
282 | 311 | from .dbg import ast |
283 | 312 |
|
| 313 | +# ============================================================================ # |
| 314 | +# Command Line Argument Parsing |
| 315 | +# ============================================================================ # |
284 | 316 | initKwargs = {} |
285 | 317 |
|
286 | 318 | # Look for --target=<target> options |
|
0 commit comments