Skip to content

Commit

Permalink
Merge branch 'release-v24.11' into 'main'
Browse files Browse the repository at this point in the history
Release v24.11

See merge request cuda-hpc-libraries/cuquantum-sdk/cuquantum-public!31
  • Loading branch information
mtjrider committed Nov 19, 2024
2 parents 8d3bbce + e62a135 commit b3e6d62
Show file tree
Hide file tree
Showing 101 changed files with 11,688 additions and 648 deletions.
8 changes: 4 additions & 4 deletions CITATION.cff
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
cff-version: 1.2.0
cff-version: 1.3.0
title: 'NVIDIA cuQuantum SDK'
message: 'If you use this software, please cite it as below.'
authors:
- name: "The cuQuantum development team"
- name: "The cuQuantum Development Team"
license: BSD-3-Clause
license-url: "https://github.com/NVIDIA/cuQuantum/blob/main/LICENSE"
repository-code: "https://github.com/nvidia/cuquantum"
type: software
url: "https://github.com/nvidia/cuquantum"
doi: 10.5281/zenodo.6385574
version: "v23.03.0"
doi: 10.1109/QCE57702.2023.00119
version: "v24.11.0"
7 changes: 4 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,15 +12,18 @@ This public repository contains a few sets of files related to the [NVIDIA cuQua
- Available for download on
- conda-forge:
- `cuquantum` [![Conda Version](https://img.shields.io/conda/vn/conda-forge/cuquantum.svg)](https://anaconda.org/conda-forge/cuquantum)
- `cudensitymat` [![Conda Version](https://img.shields.io/conda/vn/conda-forge/cudensitymat.svg)](https://anaconda.org/conda-forge/cudensitymat)
- `custatevec` [![Conda Version](https://img.shields.io/conda/vn/conda-forge/custatevec.svg)](https://anaconda.org/conda-forge/custatevec)
- `cutensornet` [![Conda Version](https://img.shields.io/conda/vn/conda-forge/cutensornet.svg)](https://anaconda.org/conda-forge/cutensornet)
- `cuquantum-python` [![Conda Version](https://img.shields.io/conda/vn/conda-forge/cuquantum-python.svg)](https://anaconda.org/conda-forge/cuquantum-python)
- PyPI:
- `cuquantum` [![pypi](https://img.shields.io/pypi/v/cuquantum.svg)](https://pypi.python.org/pypi/cuquantum)
- `cuquantum-cu11` [![pypi](https://img.shields.io/pypi/v/cuquantum-cu11.svg)](https://pypi.python.org/pypi/cuquantum-cu11)
- `cudensitymat-cu11` [![pypi](https://img.shields.io/pypi/v/cudensitymat-cu11.svg)](https://pypi.python.org/pypi/cudensitymat-cu11)
- `custatevec-cu11` [![pypi](https://img.shields.io/pypi/v/custatevec-cu11.svg)](https://pypi.python.org/pypi/custatevec-cu11)
- `cutensornet-cu11` [![pypi](https://img.shields.io/pypi/v/cutensornet-cu11.svg)](https://pypi.python.org/pypi/cutensornet-cu11)
- `cuquantum-cu12` [![pypi](https://img.shields.io/pypi/v/cuquantum-cu12.svg)](https://pypi.python.org/pypi/cuquantum-cu12)
- `cudensitymat-cu12` [![pypi](https://img.shields.io/pypi/v/cudensitymat-cu12.svg)](https://pypi.python.org/pypi/cudensitymat-cu12)
- `custatevec-cu12` [![pypi](https://img.shields.io/pypi/v/custatevec-cu12.svg)](https://pypi.python.org/pypi/custatevec-cu12)
- `cutensornet-cu12` [![pypi](https://img.shields.io/pypi/v/cutensornet-cu12.svg)](https://pypi.python.org/pypi/cutensornet-cu12)
- `cuquantum-python` [![pypi](https://img.shields.io/pypi/v/cuquantum-python.svg)](https://pypi.python.org/pypi/cuquantum-python)
Expand All @@ -39,6 +42,4 @@ All files hosted in this repository are subject to the [BSD-3-Clause](./LICENSE)

## Citing cuQuantum

This repository is uploaded to Zenodo automatically. Click the badge below to see citation formats.

[![DOI](https://zenodo.org/badge/DOI/10.5281/zenodo.6385574.svg)](https://doi.org/10.5281/zenodo.6385574)
H. Bayraktar et al., "cuQuantum SDK: A High-Performance Library for Accelerating Quantum Science", 2023 IEEE International Conference on Quantum Computing and Engineering (QCE), Bellevue, WA, USA, 2023, pp. 1050-1061, doi: [10.1109/QCE57702.2023.00119](https://doi.org/10.1109/QCE57702.2023.00119)
19 changes: 9 additions & 10 deletions python/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,8 +14,9 @@ For instructions on installing *cuQuantum Python*, refer to our
The build-time dependencies of the cuQuantum Python package include:

* CUDA Toolkit 11.x or 12.x
* cuStateVec 1.4.0+
* cuTensorNet 2.5.0+
* cuStateVec 1.7.0+
* cuTensorNet 2.6.0+
* cuDensityMat >=0.0.5, <0.1.0
* Python 3.10+
* Cython >=0.29.22,<3
* pip 21.3.1+
Expand Down Expand Up @@ -43,10 +44,9 @@ Notes:
* `-v`: enable more verbose output
* `--no-deps`: avoid installing the *run-time* dependencies
* `--no-build-isolation`: reuse the current Python environment instead of creating a new one for building the package (this avoids installing any *build-time* dependencies)
- As an alternative to setting `CUQUANTUM_ROOT`, `CUSTATEVEC_ROOT` and `CUTENSORNET_ROOT` can be set to point to the cuStateVec and the cuTensorNet libraries, respectively. The latter two environment variables take precedence if defined.
- As an alternative to setting `CUQUANTUM_ROOT`, `CUSTATEVEC_ROOT`, `CUTENSORNET_ROOT` and `CUDENSITYMAT_ROOT` can be set to point to the cuStateVec, cuTensorNet and cuDensityMat libraries, respectively. The latter three environment variables take precedence if defined.
- Please ensure that you use consistent binaries and packages for either CUDA 11 or 12. Mixing-and-matching will result in undefined behavior.


## Running

### Requirements
Expand All @@ -56,8 +56,9 @@ Runtime dependencies of the cuQuantum Python package include:
* An NVIDIA GPU with compute capability 7.0+
* Driver: Linux (450.80.02+ for CUDA 11, 525.60.13+ for CUDA 12)
* CUDA Toolkit 11.x or 12.x
* cuStateVec 1.4.0+
* cuTensorNet 2.5.0+
* cuStateVec 1.7.0+
* cuTensorNet 2.6.0+
* cuDensityMat >=0.0.5, <0.1.0
* Python 3.10+
* NumPy v1.21+
* CuPy v13.0.0+ (see [installation guide](https://docs.cupy.dev/en/stable/install.html))
Expand All @@ -83,17 +84,15 @@ Known issues:

Samples for demonstrating the usage of both low-level and high-level Python APIs are
available in the `samples` directory. The low-level API samples are 1:1 translations of the corresponding
samples written in C. The high-level API samples demonstrate pythonic usages of the cuTensorNet
samples written in C. The high-level API samples demonstrate pythonic usages of the cuTensorNet and cuDensityMat
library in Python.


## Testing

If pytest is installed, typing `pytest tests` at the command prompt in the Python source root directory will
run all tests. Some tests would be skipped if `cffi` is not installed or if the environment
variable `CUDA_PATH` is not set.


## Citing cuQuantum

Please click this Zenodo badge to see the citation format: [![DOI](https://zenodo.org/badge/DOI/10.5281/zenodo.6385574.svg)](https://doi.org/10.5281/zenodo.6385574)
H. Bayraktar et al., "cuQuantum SDK: A High-Performance Library for Accelerating Quantum Science", 2023 IEEE International Conference on Quantum Computing and Engineering (QCE), Bellevue, WA, USA, 2023, pp. 1050-1061, doi: [10.1109/QCE57702.2023.00119](https://doi.org/10.1109/QCE57702.2023.00119)
5 changes: 3 additions & 2 deletions python/builder/pep517.py
Original file line number Diff line number Diff line change
Expand Up @@ -30,8 +30,9 @@ def get_requires_for_build_wheel(config_settings=None):
# set up version constraints: note that CalVer like 22.03 is normalized to
# 22.3 by setuptools, so we must follow the same practice in the constraints;
# also, we don't need the patch number here
cuqnt_require = [f'custatevec-cu{utils.cuda_major_ver}~=1.6', # ">=1.6.0,<2"
f'cutensornet-cu{utils.cuda_major_ver}~=2.5', # ">=2.5.0,<3"
cuqnt_require = [f'custatevec-cu{utils.cuda_major_ver}~=1.7', # ">=1.7.0,<2"
f'cutensornet-cu{utils.cuda_major_ver}~=2.6', # ">=2.6.0,<3"
f'cudensitymat-cu{utils.cuda_major_ver}~=0.0.5' # ">=0.0.5, <0.1"
]

return _build_meta.get_requires_for_build_wheel(config_settings) + cuqnt_require
Expand Down
34 changes: 23 additions & 11 deletions python/builder/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -79,7 +79,7 @@ def run(self):
class build_ext(_build_ext):

def _set_library_roots(self):
custatevec_root = cutensornet_root = cuquantum_root = None
custatevec_root = cutensornet_root = cudensitymat_root = cuquantum_root = None
# Note that we need sys.path because of build isolation (since PEP 517)
py_paths = sys.path + [site.getusersitepackages()] + site.getsitepackages()

Expand All @@ -89,10 +89,10 @@ def _set_library_roots(self):
for path in py_paths:
path = os.path.join(path, 'cuquantum')
if os.path.isdir(os.path.join(path, 'include')):
custatevec_root = cutensornet_root = path
custatevec_root = cutensornet_root = cudensitymat_root = path
break
else:
# We allow setting CUSTATEVEC_ROOT and CUTENSORNET_ROOT separately for the ease
# We allow setting CUSTATEVEC_ROOT, CUTENSORNET_ROOT & CUDENSITYMAT_ROOT separately for the ease
# of development, but users are encouraged to either install cuquantum from PyPI
# or conda, or set CUQUANTUM_ROOT to the existing installation.
cuquantum_root = os.environ.get('CUQUANTUM_ROOT')
Expand All @@ -108,26 +108,35 @@ def _set_library_roots(self):
if cuquantum_root is None:
raise RuntimeError('cuTensorNet is not found, please set $CUQUANTUM_ROOT '
'or $CUTENSORNET_ROOT') from e

try:
cudensitymat_root = os.environ['CUDENSITYMAT_ROOT']
except KeyError as e:
if cuquantum_root is None:
raise RuntimeError('cuDensityMat is not found, please set $CUQUANTUM_ROOT '
'or $CUDENSITYMAT_ROOT') from e

return custatevec_root, cutensornet_root, cuquantum_root
return custatevec_root, cutensornet_root, cudensitymat_root, cuquantum_root

def _prep_includes_libs_rpaths(self):
"""
Set global vars cusv_incl_dir, cutn_incl_dir, and extra_linker_flags.
Set global vars cusv_incl_dir, cutn_incl_dir, cudm_incl_dir, and extra_linker_flags.
With the new bindings, we no longer need to link to cuQuantum DSOs.
"""
custatevec_root, cutensornet_root, cuquantum_root = self._set_library_roots()
custatevec_root, cutensornet_root, cudensitymat_root, cuquantum_root = self._set_library_roots()

global cusv_incl_dir, cutn_incl_dir, cuqnt_incl_dir
cusv_incl_dir = cutn_incl_dir = cuqnt_incl_dir = None
global cusv_incl_dir, cutn_incl_dir, cudm_incl_dir, cuqnt_incl_dir
cusv_incl_dir = cutn_incl_dir = cudm_incl_dir = cuqnt_incl_dir = None
base_incl_dir = (os.path.join(cuda_path, 'include'),)
if cuquantum_root is not None:
cuqnt_incl_dir = base_incl_dir + (os.path.join(cuquantum_root, 'include'),)
if custatevec_root is not None:
cusv_incl_dir = base_incl_dir + (os.path.join(custatevec_root, 'include'),)
if cutensornet_root is not None:
cutn_incl_dir = base_incl_dir + (os.path.join(cutensornet_root, 'include'),)
if cudensitymat_root is not None:
cudm_incl_dir = base_incl_dir + (os.path.join(cudensitymat_root, 'include'),)

global extra_linker_flags
if not building_wheel:
Expand All @@ -138,8 +147,8 @@ def _prep_includes_libs_rpaths(self):
# Note: soname = library major version
# We don't need to link to cuBLAS/cuSOLVER/cuTensor at build time
# The rpaths must be adjusted given the following full-wheel installation:
# - cuquantum-python: site-packages/cuquantum/{custatevec, cutensornet}/_internal/ [=$ORIGIN]
# - cusv & cutn: site-packages/cuquantum/lib/
# - cuquantum-python: site-packages/cuquantum/{custatevec, cutensornet, cudensitymat}/_internal/ [=$ORIGIN]
# - cusv, cutn & cudm: site-packages/cuquantum/lib/
# - cutensor: site-packages/cutensor/lib/
# - cublas: site-packages/nvidia/cublas/lib/
# - cusolver: site-packages/nvidia/cusolver/lib/
Expand All @@ -157,17 +166,20 @@ def _prep_includes_libs_rpaths(self):
print("CUDA path:", cuda_path)
print("cuStateVec path:", custatevec_root if custatevec_root else cuquantum_root)
print("cuTensorNet path:", cutensornet_root if cutensornet_root else cuquantum_root)
print("cuDensityMat path:", cudensitymat_root if cudensitymat_root else cuquantum_root)
print("*"*80+"\n")

def build_extension(self, ext):
ext.include_dirs = ()
for include_dir in (cusv_incl_dir, cutn_incl_dir, cuqnt_incl_dir):
for include_dir in (cusv_incl_dir, cutn_incl_dir, cudm_incl_dir, cuqnt_incl_dir):
if include_dir is not None:
ext.include_dirs += include_dir
if ext.name.endswith("custatevec"):
ext.extra_link_args = extra_linker_flags
elif ext.name.endswith("cutensornet"):
ext.extra_link_args = extra_linker_flags
elif ext.name.endswith("cudensitymat"):
ext.extra_link_args = extra_linker_flags

super().build_extension(ext)

Expand Down
4 changes: 3 additions & 1 deletion python/cuquantum/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,14 @@
#
# SPDX-License-Identifier: BSD-3-Clause

from cuquantum import bindings
from cuquantum import custatevec
from cuquantum import cutensornet
from cuquantum import densitymat
from cuquantum.cutensornet import (
contract, contract_path, einsum, einsum_path, tensor, tensor_qualifiers_dtype, BaseCUDAMemoryManager, CircuitToEinsum, MemoryPointer,
Network, NetworkOptions, OptimizerInfo, OptimizerOptions, PathFinderOptions,
ReconfigOptions, SlicerOptions)
ReconfigOptions, SlicerOptions, MemoryLimitExceeded)
from cuquantum._utils import ComputeType, cudaDataType, libraryPropertyType
from cuquantum._version import __version__

Expand Down
9 changes: 6 additions & 3 deletions python/cuquantum/__main__.py
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,9 @@ def get_lib_path(name):
elif "cutensor" in name: # cutensor or cutensornet
from cuquantum import cutensornet as cutn
cutn._internal.cutensornet._inspect_function_pointers()
elif "cudensitymat" in name:
from cuquantum import bindings
bindings._internal.cudensitymat._inspect_function_pointers()

try:
with open('/proc/self/maps') as f:
Expand Down Expand Up @@ -53,7 +56,7 @@ def get_lib_path(name):

def _get_cuquantum_libs():
paths = set()
for lib in ('custatevec', 'cutensornet', 'cutensor'):
for lib in ('custatevec', 'cutensornet', 'cutensor', 'cudensitymat'):
path = os.path.normpath(get_lib_path(f"lib{lib}.so"))
paths.add(path)
return tuple(paths)
Expand Down Expand Up @@ -92,7 +95,7 @@ def _get_cuquantum_target(target):
parser.add_argument('--libs', action='store_true',
help='get cuQuantum linker flags')
parser.add_argument('--target', action='append', default=[],
choices=('custatevec', 'cutensornet'),
choices=('custatevec', 'cutensornet', 'cudensitymat'),
help='get the linker flag for the target cuQuantum component')
args = parser.parse_args()

Expand All @@ -109,6 +112,6 @@ def _get_cuquantum_target(target):
flag = ''
for target in args.target:
flag += _get_cuquantum_target(target)
if target == 'cutensornet':
if target in ('cutensornet', 'cudensitymat') :
flag += _get_cuquantum_target('cutensor')
print(flag)
7 changes: 4 additions & 3 deletions python/cuquantum/_utils.pxd
Original file line number Diff line number Diff line change
Expand Up @@ -166,9 +166,10 @@ cdef cppclass nested_resource[T]:
nullable_unique_ptr[ vector[vector[T]] ] nested_resource_ptr


cdef nullable_unique_ptr[ vector[ResT] ] get_resource_ptr(object obj, ResT* __unused)
cdef nullable_unique_ptr[ vector[PtrT*] ] get_resource_ptrs(object obj, PtrT* __unused)
cdef nested_resource[ResT] get_nested_resource_ptr(object obj, ResT* __unused)
# accepts the output pointer as input to use the return value for exception propagation
cdef int get_resource_ptr(nullable_unique_ptr[vector[ResT]] &in_out_ptr, object obj, ResT* __unused) except 1
cdef int get_resource_ptrs(nullable_unique_ptr[ vector[PtrT*] ] &in_out_ptr, object obj, PtrT* __unused) except 1
cdef int get_nested_resource_ptr(nested_resource[ResT] &in_out_ptr, object obj, ResT* __unused) except 1


# Cython limitation: need standalone typedef if we wanna use it for casting
Expand Down
47 changes: 24 additions & 23 deletions python/cuquantum/_utils.pyx
Original file line number Diff line number Diff line change
Expand Up @@ -196,42 +196,41 @@ cdef int[29] _WHITESPACE_UNICODE_INTS = [
WHITESPACE_UNICODE = ''.join(chr(s) for s in _WHITESPACE_UNICODE_INTS)


# Cython can't infer the overload by return type alone, so we need a dummy
# input argument to help it
cdef nullable_unique_ptr[ vector[ResT] ] get_resource_ptr(object obj, ResT* __unused):
cdef nullable_unique_ptr[ vector[ResT] ] ptr
cdef vector[ResT]* vec
# Cython can't infer the ResT overload when it is wrapped in nullable_unique_ptr,
# so we need a dummy (__unused) input argument to help it
cdef int get_resource_ptr(nullable_unique_ptr[vector[ResT]] &in_out_ptr, object obj, ResT* __unused) except 1:
if isinstance(obj, _np_ndarray):
# TODO: can we do "assert obj.dtype == some_dtype" here? it seems we have no
# way to check the dtype...
# TODO: how about buffer protocol?
assert <size_t>(obj.dtype.itemsize) == sizeof(ResT)
ptr.reset(<vector[ResT]*><intptr_t>(obj.ctypes.data), False)
in_out_ptr.reset(<vector[ResT]*><intptr_t>(obj.ctypes.data), False)
elif cpython.PySequence_Check(obj):
vec = new vector[ResT](len(obj))
# set the ownership immediately to avoid leaking the `vec` memory in
# case of exception in the following loop
in_out_ptr.reset(vec, True)
for i in range(len(obj)):
deref(vec)[i] = obj[i]
ptr.reset(vec, True)
else:
ptr.reset(<vector[ResT]*><intptr_t>obj, False)
return move(ptr)
in_out_ptr.reset(<vector[ResT]*><intptr_t>obj, False)
return 0


cdef nullable_unique_ptr[ vector[PtrT*] ] get_resource_ptrs(object obj, PtrT* __unused):
cdef nullable_unique_ptr[ vector[PtrT*] ] ptr
cdef vector[PtrT*]* vec
cdef int get_resource_ptrs(nullable_unique_ptr[ vector[PtrT*] ] &in_out_ptr, object obj, PtrT* __unused) except 1:
if cpython.PySequence_Check(obj):
vec = new vector[PtrT*](len(obj))
# set the ownership immediately to avoid leaking the `vec` memory in
# case of exception in the following loop
in_out_ptr.reset(vec, True)
for i in range(len(obj)):
deref(vec)[i] = <PtrT*><intptr_t>(obj[i])
ptr.reset(vec, True)
else:
ptr.reset(<vector[PtrT*]*><intptr_t>obj, False)
return move(ptr)
in_out_ptr.reset(<vector[PtrT*]*><intptr_t>obj, False)
return 0


cdef nested_resource[ResT] get_nested_resource_ptr(object obj, ResT* __unused):
cdef nested_resource[ResT] res
cdef int get_nested_resource_ptr(nested_resource[ResT] &in_out_ptr, object obj, ResT* __unused) except 1:
cdef nullable_unique_ptr[ vector[intptr_t] ] nested_ptr
cdef nullable_unique_ptr[ vector[vector[ResT]] ] nested_res_ptr
cdef vector[intptr_t]* nested_vec = NULL
Expand All @@ -243,26 +242,28 @@ cdef nested_resource[ResT] get_nested_resource_ptr(object obj, ResT* __unused):
length = len(obj)
nested_res_vec = new vector[vector[ResT]](length)
nested_vec = new vector[intptr_t](length)
# set the ownership immediately to avoid leaking memory in case of
# exception in the following loop
nested_res_ptr.reset(nested_res_vec, True)
nested_ptr.reset(nested_vec, True)
for i, obj_i in enumerate(obj):
deref(nested_res_vec)[i] = obj_i
deref(nested_vec)[i] = <intptr_t>(deref(nested_res_vec)[i].data())
nested_res_ptr.reset(nested_res_vec, True)
nested_ptr.reset(nested_vec, True)
elif cpython.PySequence_Check(obj):
length = len(obj)
nested_vec = new vector[intptr_t](length)
nested_ptr.reset(nested_vec, True)
for i, addr in enumerate(obj):
deref(nested_vec)[i] = addr
nested_res_ptr.reset(NULL, False)
nested_ptr.reset(nested_vec, True)
else:
# obj is an int (ResT**)
nested_res_ptr.reset(NULL, False)
nested_ptr.reset(<vector[intptr_t]*><intptr_t>obj, False)

res.ptrs = move(nested_ptr)
res.nested_resource_ptr = move(nested_res_ptr)
return move(res)
in_out_ptr.ptrs = move(nested_ptr)
in_out_ptr.nested_resource_ptr = move(nested_res_ptr)
return 0


class FunctionNotFoundError(RuntimeError): pass
Expand Down
2 changes: 1 addition & 1 deletion python/cuquantum/_version.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,4 +5,4 @@
# Note: cuQuantum Python follows the cuQuantum SDK version, which is now
# switched to YY.MM and is different from individual libraries' (semantic)
# versioning scheme.
__version__ = '24.08.0'
__version__ = '24.11.0'
Loading

0 comments on commit b3e6d62

Please sign in to comment.