mirror of
https://github.com/NVIDIA/cuda-samples.git
synced 2026-10-13 00:08:26 +08:00
CUDA 13.2 samples update (#432)
- Added Python samples for CUDA Python 1.0 release - Renamed top-level `Samples` directory to `cpp` to accommodate Python samples.
This commit is contained in:
134
python/Utilities/README.md
Normal file
134
python/Utilities/README.md
Normal file
@@ -0,0 +1,134 @@
|
||||
# CUDA Python Utilities
|
||||
|
||||
Common utilities for CUDA Python samples using the `cuda.core` API.
|
||||
|
||||
## Overview
|
||||
|
||||
This module provides reusable utility functions for CUDA samples to reduce code duplication. Samples import from `cuda_samples_utils.py` using simple path-based imports (no package structure needed).
|
||||
|
||||
## Installation Requirements
|
||||
|
||||
Install from the Python samples directory:
|
||||
|
||||
```bash
|
||||
cd /path/to/cuda-samples/Python
|
||||
pip install -r requirements.txt
|
||||
```
|
||||
|
||||
This installs a common CUDA 13 stack (see `python/requirements.txt`):
|
||||
|
||||
- `cuda-python` (>=13.0.0)
|
||||
- `cuda-core` (>=0.6.0)
|
||||
- `cupy-cuda13x` (>=13.0.0)
|
||||
- `numpy` (>=2.3.2)
|
||||
|
||||
## How to Use in Samples
|
||||
|
||||
Import utilities using path-based import:
|
||||
|
||||
```python
|
||||
import sys
|
||||
from pathlib import Path
|
||||
|
||||
# Add Utilities directory to path
|
||||
sys.path.insert(0, str(Path(__file__).parent.parent.parent / "Utilities"))
|
||||
from cuda_samples_utils import verify_array_result
|
||||
|
||||
# Use the utility
|
||||
if verify_array_result(result, expected):
|
||||
print("Success!")
|
||||
```
|
||||
|
||||
## Available Functions
|
||||
|
||||
### Result Verification
|
||||
|
||||
#### `verify_array_result(result, expected, rtol=1e-5, atol=1e-8, verbose=True)`
|
||||
|
||||
Verify computed results match expected values. The helper detects whether both
|
||||
arguments are NumPy arrays or both are CuPy arrays and uses the matching
|
||||
library's `allclose` (no unnecessary cross-device transfers).
|
||||
|
||||
**Parameters:**
|
||||
- `result`: NumPy or CuPy array with computed results
|
||||
- `expected`: NumPy or CuPy array with expected values (same kind as `result`)
|
||||
- `rtol`: Relative tolerance (default: 1e-5)
|
||||
- `atol`: Absolute tolerance (default: 1e-8)
|
||||
- `verbose`: Print test result (default: True)
|
||||
|
||||
**Returns:**
|
||||
- `True` if results match within tolerance, `False` otherwise
|
||||
|
||||
**Example:**
|
||||
```python
|
||||
expected = a + b
|
||||
if verify_array_result(c, expected):
|
||||
print("Computation correct!")
|
||||
```
|
||||
|
||||
### Package Check
|
||||
|
||||
#### `check_cuda_requirements()`
|
||||
|
||||
Check if required CUDA packages are available.
|
||||
|
||||
**Returns:**
|
||||
- `True` if requirements are met, `False` otherwise
|
||||
|
||||
**Example:**
|
||||
```python
|
||||
if not check_cuda_requirements():
|
||||
sys.exit(1)
|
||||
```
|
||||
|
||||
## Design Philosophy
|
||||
|
||||
These utilities focus on common operations that are **not** part of `cuda.core` API:
|
||||
- Result verification for NumPy or CuPy arrays
|
||||
- Package requirements checking
|
||||
|
||||
For CUDA operations like device initialization, kernel compilation, and grid size calculations, samples should use `cuda.core` API directly to demonstrate the proper usage patterns.
|
||||
|
||||
## Complete Example
|
||||
|
||||
See `../1_GettingStarted/vectorAdd/vectorAdd.py` for a complete example:
|
||||
|
||||
```python
|
||||
import sys
|
||||
from pathlib import Path
|
||||
|
||||
# Import utility
|
||||
sys.path.insert(0, str(Path(__file__).parent.parent.parent / "Utilities"))
|
||||
from cuda_samples_utils import verify_array_result
|
||||
|
||||
import cupy as cp
|
||||
from cuda.core import Device, Program, ProgramOptions, LaunchConfig, launch
|
||||
|
||||
# Use cuda.core directly for device and kernel operations
|
||||
device = Device(0)
|
||||
device.set_current()
|
||||
|
||||
program_options = ProgramOptions(std="c++17", arch=f"sm_{device.arch}")
|
||||
program = Program(kernel_source, code_type="c++", options=program_options)
|
||||
module = program.compile("cubin", name_expressions=("kernel_name",))
|
||||
kernel = module.get_kernel("kernel_name")
|
||||
|
||||
# Calculate grid size inline
|
||||
threads_per_block = 256
|
||||
blocks_per_grid = (num_elements + threads_per_block - 1) // threads_per_block
|
||||
|
||||
# Launch kernel - pass cupy arrays directly
|
||||
config = LaunchConfig(grid=blocks_per_grid, block=threads_per_block)
|
||||
launch(stream, config, kernel, a, b, c, cp.int32(num_elements))
|
||||
|
||||
# Verify results using utility
|
||||
verify_array_result(c, expected)
|
||||
```
|
||||
|
||||
## Benefits
|
||||
|
||||
- **Code Reuse**: Write common functionality once
|
||||
- **Consistency**: All samples use the same patterns
|
||||
- **Maintainability**: Bug fixes benefit all samples
|
||||
- **Transparency**: Samples show cuda.core API usage directly
|
||||
- **Simplicity**: No complex package structure needed
|
||||
47
python/Utilities/__init__.py
Normal file
47
python/Utilities/__init__.py
Normal file
@@ -0,0 +1,47 @@
|
||||
# Copyright (c) 2025, NVIDIA CORPORATION. All rights reserved.
|
||||
#
|
||||
# Redistribution and use in source and binary forms, with or without
|
||||
# modification, are permitted provided that the following conditions
|
||||
# are met:
|
||||
# * Redistributions of source code must retain the above copyright
|
||||
# notice, this list of conditions and the following disclaimer.
|
||||
# * Redistributions in binary form must reproduce the above copyright
|
||||
# notice, this list of conditions and the following disclaimer in the
|
||||
# documentation and/or other materials provided with the distribution.
|
||||
# * Neither the name of NVIDIA CORPORATION nor the names of its
|
||||
# contributors may be used to endorse or promote products derived
|
||||
# from this software without specific prior written permission.
|
||||
#
|
||||
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY
|
||||
# EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
# PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
|
||||
# CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
# EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
# PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||
# PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
|
||||
# OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
"""
|
||||
CUDA Python Samples - Utilities
|
||||
|
||||
Common utilities for CUDA Python samples.
|
||||
|
||||
Provides:
|
||||
- Package requirements checking
|
||||
- Result verification
|
||||
"""
|
||||
|
||||
from .cuda_samples_utils import (
|
||||
check_cuda_requirements,
|
||||
verify_array_result,
|
||||
)
|
||||
|
||||
__version__ = "1.0.0"
|
||||
|
||||
__all__ = [
|
||||
"check_cuda_requirements",
|
||||
"verify_array_result",
|
||||
]
|
||||
144
python/Utilities/cuda_samples_utils.py
Normal file
144
python/Utilities/cuda_samples_utils.py
Normal file
@@ -0,0 +1,144 @@
|
||||
# Copyright (c) 2025, NVIDIA CORPORATION. All rights reserved.
|
||||
#
|
||||
# Redistribution and use in source and binary forms, with or without
|
||||
# modification, are permitted provided that the following conditions
|
||||
# are met:
|
||||
# * Redistributions of source code must retain the above copyright
|
||||
# notice, this list of conditions and the following disclaimer.
|
||||
# * Redistributions in binary form must reproduce the above copyright
|
||||
# notice, this list of conditions and the following disclaimer in the
|
||||
# distribution and/or other materials provided with the distribution.
|
||||
# * Neither the name of NVIDIA CORPORATION nor the names of its
|
||||
# contributors may be used to endorse or promote products derived
|
||||
# from this software without specific prior written permission.
|
||||
#
|
||||
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY
|
||||
# EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
# PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
|
||||
# CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
# EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
# PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||
# PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
|
||||
# OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
"""
|
||||
Common CUDA utilities for Python samples.
|
||||
|
||||
This module provides common utility functions for CUDA samples including:
|
||||
- Package requirements checking
|
||||
- Result verification
|
||||
- GPU device information
|
||||
|
||||
Requirements:
|
||||
- Python 3.10+
|
||||
- CUDA Toolkit 13.0+ (recommended; matches cuda-python 13.x)
|
||||
- cuda-python >= 13.0.0
|
||||
- cuda-core >= 0.6.0
|
||||
- cupy-cuda13x >= 13.0.0
|
||||
- numpy >= 2.3.2 (when used with samples that install it)
|
||||
"""
|
||||
|
||||
|
||||
def check_cuda_requirements() -> bool:
|
||||
"""
|
||||
Check if required CUDA packages are available.
|
||||
|
||||
Returns
|
||||
-------
|
||||
bool
|
||||
True if requirements are met, False otherwise
|
||||
"""
|
||||
try:
|
||||
import cupy as cp # noqa: F401
|
||||
from cuda.core import Device # noqa: F401
|
||||
|
||||
return True
|
||||
except ImportError as e:
|
||||
print(f"Error: Required package not found: {e}")
|
||||
print("Please install from requirements.txt:")
|
||||
print(" pip install -r requirements.txt")
|
||||
return False
|
||||
|
||||
|
||||
def verify_array_result(
|
||||
result, expected, rtol: float = 1e-5, atol: float = 1e-8, verbose: bool = True
|
||||
) -> bool:
|
||||
"""
|
||||
Verify that computed result matches expected result.
|
||||
|
||||
Automatically detects whether arrays are NumPy or CuPy and uses the
|
||||
appropriate library without unnecessary data transfers.
|
||||
|
||||
Parameters
|
||||
----------
|
||||
result : numpy.ndarray or cupy.ndarray
|
||||
Computed result array.
|
||||
expected : numpy.ndarray or cupy.ndarray
|
||||
Expected result array.
|
||||
rtol : float
|
||||
Relative tolerance (default: 1e-5)
|
||||
atol : float
|
||||
Absolute tolerance (default: 1e-8)
|
||||
verbose : bool
|
||||
Whether to print verification result (default: True).
|
||||
|
||||
Returns
|
||||
-------
|
||||
bool
|
||||
True if results match, False otherwise.
|
||||
|
||||
Raises
|
||||
------
|
||||
TypeError
|
||||
If arrays are not both NumPy or both CuPy, or if CuPy is needed
|
||||
but not available.
|
||||
"""
|
||||
import numpy as np
|
||||
|
||||
is_np = isinstance(result, np.ndarray) and isinstance(expected, np.ndarray)
|
||||
|
||||
if is_np:
|
||||
allclose = np.allclose
|
||||
abs_ = np.abs
|
||||
max_ = np.max
|
||||
else:
|
||||
import cupy as cp
|
||||
|
||||
is_cp = isinstance(result, cp.ndarray) and isinstance(expected, cp.ndarray)
|
||||
|
||||
if not is_cp:
|
||||
raise TypeError(
|
||||
"verify_array_result expects both arrays to be either "
|
||||
"numpy.ndarray or cupy.ndarray"
|
||||
)
|
||||
|
||||
allclose = cp.allclose
|
||||
abs_ = cp.abs
|
||||
max_ = cp.max
|
||||
|
||||
if allclose(result, expected, rtol=rtol, atol=atol):
|
||||
if verbose:
|
||||
print("Test PASSED")
|
||||
return True
|
||||
else:
|
||||
max_error = max_(abs_(result - expected))
|
||||
if verbose:
|
||||
print(f"Test FAILED - Max error: {max_error}")
|
||||
return False
|
||||
|
||||
|
||||
def print_gpu_info(device) -> None:
|
||||
"""
|
||||
Print GPU device information.
|
||||
|
||||
Parameters
|
||||
----------
|
||||
device : cuda.core.Device
|
||||
CUDA device object
|
||||
"""
|
||||
print(f"Device: {device.name}")
|
||||
cc = device.compute_capability
|
||||
print(f"Compute Capability: {cc.major}.{cc.minor}")
|
||||
Reference in New Issue
Block a user