chore: import upstream snapshot with attribution
This commit is contained in:
@@ -0,0 +1,928 @@
|
||||
# Copyright (c) 2025 PaddlePaddle Authors. All Rights Reserved.
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
# You may obtain a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
|
||||
# paddle/cuda/__init__.py
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
from contextlib import contextmanager
|
||||
from typing import TYPE_CHECKING, Any
|
||||
|
||||
import paddle
|
||||
from paddle import base, core, device as paddle_device
|
||||
from paddle.cuda.graphs import CUDAGraph, graph, graph_pool_handle
|
||||
from paddle.device import (
|
||||
Event,
|
||||
Stream,
|
||||
StreamContext,
|
||||
_device_to_paddle as _device_to_paddle,
|
||||
amp,
|
||||
current_device,
|
||||
device,
|
||||
ipc_collect,
|
||||
is_available as _device_is_available,
|
||||
is_bf16_supported,
|
||||
is_current_stream_capturing as _is_current_stream_capturing,
|
||||
manual_seed,
|
||||
manual_seed_all as device_manual_seed_all,
|
||||
reset_peak_memory_stats,
|
||||
set_stream,
|
||||
stream,
|
||||
)
|
||||
from paddle.tensor.creation import (
|
||||
BFloat16Tensor,
|
||||
BoolTensor,
|
||||
ByteTensor,
|
||||
CharTensor,
|
||||
DoubleTensor,
|
||||
FloatTensor,
|
||||
HalfTensor,
|
||||
IntTensor,
|
||||
LongTensor,
|
||||
ShortTensor,
|
||||
)
|
||||
|
||||
if TYPE_CHECKING:
|
||||
from collections.abc import Generator
|
||||
|
||||
DeviceLike = paddle.core.Place | int | str | None
|
||||
|
||||
|
||||
def is_available() -> bool:
|
||||
"""
|
||||
Check whether **any supported device** is available in the current environment.
|
||||
|
||||
This function checks whether Paddle is built with support for at least one
|
||||
type of accelerator (e.g., CUDA, XPU, CustomDevice) and whether there is
|
||||
at least one device of that type available.
|
||||
|
||||
If any supported device is available, this function returns True. Otherwise,
|
||||
it returns False.
|
||||
|
||||
Returns:
|
||||
bool: True if there is at least one available device (GPU/XPU/CustomDevice),
|
||||
False otherwise.
|
||||
|
||||
Examples:
|
||||
.. code-block:: pycon
|
||||
|
||||
>>> import paddle
|
||||
|
||||
>>> if paddle.cuda.is_available():
|
||||
... print("At least one device is available")
|
||||
... else:
|
||||
... print("No supported devices available")
|
||||
"""
|
||||
return _device_is_available()
|
||||
|
||||
|
||||
def synchronize(device: DeviceLike = None) -> None:
|
||||
"""
|
||||
Wait for all streams on a given device to complete.
|
||||
|
||||
This function blocks the calling thread until all the operations
|
||||
on the specified device have finished. It is useful for ensuring
|
||||
synchronization between CPU and GPU or across multiple devices.
|
||||
|
||||
Args:
|
||||
device (CUDAPlace | CustomPlace | int | str | None, optional): The target device to synchronize.
|
||||
- None: Synchronize the current device.
|
||||
- int: Device index, e.g., ``2`` means ``gpu:2``.
|
||||
- str: Device string, e.g., ``'cuda:0'`` or ``'gpu:0'``.
|
||||
- CUDAPlace: A Paddle CUDA place object.
|
||||
- CustomPlace: A Paddle custom device place object.
|
||||
|
||||
Returns:
|
||||
None
|
||||
|
||||
Examples:
|
||||
.. code-block:: pycon
|
||||
|
||||
>>> # doctest: +REQUIRES(env:CUSTOM_DEVICE)
|
||||
>>> import paddle
|
||||
|
||||
# synchronize the current device
|
||||
>>> paddle.cuda.synchronize()
|
||||
"""
|
||||
dev = _device_to_paddle(device)
|
||||
paddle_device.synchronize(dev)
|
||||
|
||||
|
||||
def current_stream(device: DeviceLike = None) -> Stream:
|
||||
"""
|
||||
Return the current stream for the given device.
|
||||
|
||||
Args:
|
||||
device (int | str | paddle.CUDAPlace | paddle.CustomPlace | None, optional):
|
||||
The target device to query.
|
||||
|
||||
- None: use the current device.
|
||||
- int: device index (e.g., 0 -> 'gpu:0').
|
||||
- str: device string (e.g., "cuda:0", "gpu:1").
|
||||
- CUDAPlace or CustomPlace: Paddle device objects.
|
||||
|
||||
Returns:
|
||||
core.CUDAStream: The current CUDA stream associated with the given device.
|
||||
|
||||
Examples:
|
||||
.. code-block:: pycon
|
||||
|
||||
>>> # doctest: +REQUIRES(env:CUSTOM_DEVICE)
|
||||
>>> import paddle
|
||||
|
||||
# Get the current stream on the default CUDA device
|
||||
>>> s1 = paddle.cuda.current_stream()
|
||||
>>> print(s1)
|
||||
|
||||
# Get the current stream on device cuda:0
|
||||
>>> s2 = paddle.cuda.current_stream("cuda:0")
|
||||
>>> print(s2)
|
||||
"""
|
||||
dev = _device_to_paddle(device)
|
||||
return paddle_device.current_stream(dev)
|
||||
|
||||
|
||||
def is_current_stream_capturing() -> bool:
|
||||
"""
|
||||
Check whether the current stream is in CUDA graph capturing state.
|
||||
|
||||
Returns:
|
||||
bool: True if the current stream is capturing, False otherwise.
|
||||
|
||||
Examples:
|
||||
.. code-block:: pycon
|
||||
|
||||
>>> import paddle
|
||||
>>> if paddle.device.is_available():
|
||||
... graph = paddle.device.cuda.graphs.CUDAGraph()
|
||||
... graph.capture_begin()
|
||||
... print(paddle.cuda.is_current_stream_capturing()) # True
|
||||
... graph.capture_end()
|
||||
"""
|
||||
return _is_current_stream_capturing()
|
||||
|
||||
|
||||
def get_device_properties(device: DeviceLike = None):
|
||||
"""
|
||||
Get the properties of a CUDA device.
|
||||
|
||||
Args:
|
||||
device (int | str | paddle.CUDAPlace | paddle.CustomPlace | None, optional):
|
||||
The target device to query.
|
||||
|
||||
- None: use the current device.
|
||||
- int: device index (e.g., 0 -> 'gpu:0').
|
||||
- str: device string (e.g., "cuda:0", "gpu:1").
|
||||
- CUDAPlace or CustomPlace: Paddle device objects.
|
||||
|
||||
Returns:
|
||||
DeviceProperties: An object containing the device properties, such as
|
||||
name, total memory, compute capability, and multiprocessor count.
|
||||
|
||||
Examples:
|
||||
.. code-block:: pycon
|
||||
|
||||
>>> # doctest: +REQUIRES(env:GPU)
|
||||
>>> import paddle
|
||||
|
||||
# Get the properties of the current device
|
||||
>>> paddle.device.set_device('gpu')
|
||||
>>> props = paddle.cuda.get_device_properties()
|
||||
>>> print(props)
|
||||
|
||||
"""
|
||||
return paddle_device.get_device_properties(device)
|
||||
|
||||
|
||||
def get_device_name(device: DeviceLike = None) -> str:
|
||||
"""
|
||||
Get the name of a device.
|
||||
|
||||
Args:
|
||||
device (int | str | paddle.CUDAPlace | paddle.CustomPlace | None, optional):
|
||||
The target device to query.
|
||||
|
||||
- None: use the current device.
|
||||
- int: device index (e.g., 0 -> 'gpu:0').
|
||||
- str: device string (e.g., "cuda:0", "gpu:1").
|
||||
- CUDAPlace or CustomPlace: Paddle device objects.
|
||||
|
||||
Returns:
|
||||
str: The name of the CUDA device.
|
||||
|
||||
Examples:
|
||||
.. code-block:: pycon
|
||||
|
||||
>>> # doctest: +REQUIRES(env:GPU)
|
||||
>>> import paddle
|
||||
|
||||
# Get the name of the current CUDA device
|
||||
>>> paddle.device.set_device('gpu')
|
||||
>>> name = paddle.cuda.get_device_name()
|
||||
>>> print(name)
|
||||
|
||||
# Get the name of device cuda:0
|
||||
>>> name0 = paddle.cuda.get_device_name("cuda:0")
|
||||
>>> print(name0)
|
||||
"""
|
||||
return paddle_device.get_device_name(device)
|
||||
|
||||
|
||||
def get_device_capability(device: DeviceLike = None) -> tuple[int, int]:
|
||||
"""
|
||||
Get the compute capability (major, minor) of a device.
|
||||
|
||||
Args:
|
||||
device (int | str | paddle.CUDAPlace | paddle.CustomPlace | None, optional):
|
||||
The target device to query.
|
||||
|
||||
- None: use the current device.
|
||||
- int: device index (e.g., 0 -> 'gpu:0').
|
||||
- str: device string (e.g., "cuda:0", "gpu:1").
|
||||
- CUDAPlace or CustomPlace: Paddle device objects.
|
||||
|
||||
Returns:
|
||||
tuple[int, int]: A tuple ``(major, minor)`` representing the compute capability of the CUDA device.
|
||||
|
||||
Examples:
|
||||
.. code-block:: pycon
|
||||
|
||||
>>> # doctest: +REQUIRES(env:GPU)
|
||||
>>> import paddle
|
||||
|
||||
# Get compute capability of the current CUDA device
|
||||
>>> paddle.device.set_device('gpu')
|
||||
>>> capability = paddle.cuda.get_device_capability()
|
||||
>>> print(capability) # e.g., (8, 0)
|
||||
|
||||
# Get compute capability of device cuda:0
|
||||
>>> capability0 = paddle.cuda.get_device_capability("cuda:0")
|
||||
>>> print(capability0)
|
||||
"""
|
||||
return paddle_device.get_device_capability(device)
|
||||
|
||||
|
||||
def manual_seed_all(seed: int) -> None:
|
||||
"""
|
||||
|
||||
Sets the seed for global default generator, which manages the random number generation.
|
||||
|
||||
Args:
|
||||
seed(int): The random seed to set.
|
||||
|
||||
Returns:
|
||||
None
|
||||
|
||||
Examples:
|
||||
.. code-block:: pycon
|
||||
|
||||
>>> import paddle
|
||||
>>> paddle.cuda.manual_seed_all(102)
|
||||
|
||||
"""
|
||||
device_manual_seed_all(seed)
|
||||
|
||||
|
||||
def get_rng_state(device: DeviceLike | None = None) -> core.GeneratorState:
|
||||
"""
|
||||
Return the random number generator state of the specified device.
|
||||
|
||||
Args:
|
||||
device (DeviceLike, optional): The device to retrieve the RNG state from.
|
||||
If not specified, uses the current default device (as returned by paddle.framework._current_expected_place_()).
|
||||
Can be a device object, integer device ID, or device string.
|
||||
|
||||
Returns:
|
||||
core.GeneratorState: The current RNG state of the specified device.
|
||||
|
||||
Examples:
|
||||
.. code-block:: pycon
|
||||
|
||||
>>> import paddle
|
||||
>>> paddle.cuda.get_rng_state()
|
||||
"""
|
||||
|
||||
return paddle_device.get_rng_state(device)
|
||||
|
||||
|
||||
def set_rng_state(
|
||||
new_state: core.GeneratorState, device: DeviceLike | None = None
|
||||
) -> None:
|
||||
"""
|
||||
Set the random number generator state of the specified device.
|
||||
|
||||
Args:
|
||||
new_state (core.GeneratorState): The desired RNG state to set.
|
||||
This should be a state object previously obtained from ``get_rng_state()``.
|
||||
device (DeviceLike, optional): The device to set the RNG state for.
|
||||
If not specified, uses the current default device (as returned by ``paddle.framework._current_expected_place_()``).
|
||||
Can be a device object, integer device ID, or device string.
|
||||
|
||||
Returns:
|
||||
None
|
||||
|
||||
Examples:
|
||||
.. code-block:: pycon
|
||||
|
||||
>>> import paddle
|
||||
>>> # Save RNG state
|
||||
>>> state = paddle.cuda.get_rng_state()
|
||||
>>> # Do some random operations
|
||||
>>> x = paddle.randn([2, 3])
|
||||
>>> # Restore RNG state
|
||||
>>> paddle.cuda.set_rng_state(state)
|
||||
"""
|
||||
paddle_device.set_rng_state(new_state, device)
|
||||
|
||||
|
||||
class nvtx:
|
||||
"""Namespace for NVTX marker operations."""
|
||||
|
||||
@staticmethod
|
||||
@contextmanager
|
||||
def range(
|
||||
msg: str, *args: Any, **kwargs: Any
|
||||
) -> Generator[None, None, None]:
|
||||
"""
|
||||
Context manager/decorator that pushes and pops an NVTX range.
|
||||
|
||||
Args:
|
||||
msg (str): The name of the NVTX range.
|
||||
*args: Arguments used to format ``msg``.
|
||||
**kwargs: Keyword arguments used to format ``msg``.
|
||||
"""
|
||||
nvtx.range_push(msg.format(*args, **kwargs))
|
||||
try:
|
||||
yield
|
||||
finally:
|
||||
nvtx.range_pop()
|
||||
|
||||
@staticmethod
|
||||
def range_push(msg: str):
|
||||
"""
|
||||
Push an NVTX range marker with the given message.
|
||||
|
||||
Args:
|
||||
msg (str): The name of the NVTX range.
|
||||
|
||||
Example:
|
||||
.. code-block:: pycon
|
||||
|
||||
>>> # doctest: +REQUIRES(env:GPU)
|
||||
>>> import paddle
|
||||
>>> # paddle.device.nvtx.range_push("test") is equivalent to paddle.cuda.nvtx.range_push("test")
|
||||
>>> paddle.cuda.nvtx.range_push("test")
|
||||
|
||||
"""
|
||||
paddle.base.core.nvprof_nvtx_push(msg)
|
||||
|
||||
@staticmethod
|
||||
def range_pop():
|
||||
"""
|
||||
Pop the most recent NVTX range marker.
|
||||
|
||||
Example:
|
||||
.. code-block:: pycon
|
||||
|
||||
>>> # doctest: +REQUIRES(env:GPU)
|
||||
>>> import paddle
|
||||
>>> # paddle.device.nvtx.range_pop("test") is equivalent to paddle.cuda.nvtx.range_pop("test")
|
||||
>>> paddle.cuda.nvtx.range_pop()
|
||||
"""
|
||||
paddle.base.core.nvprof_nvtx_pop()
|
||||
|
||||
|
||||
def cudart():
|
||||
r"""Retrieves the CUDA runtime API module.
|
||||
|
||||
This function initializes the CUDA runtime environment if it is not already
|
||||
initialized and returns the CUDA runtime API module (_cudart). The CUDA
|
||||
runtime API module provides access to various CUDA runtime functions.
|
||||
|
||||
Args:
|
||||
``None``
|
||||
|
||||
Returns:
|
||||
module: The CUDA runtime API module (_cudart).
|
||||
|
||||
Examples:
|
||||
.. code-block:: pycon
|
||||
|
||||
>>> # doctest: +REQUIRES(env:CUSTOM_DEVICE)
|
||||
>>> import paddle
|
||||
>>> from paddle.cuda import cudart, check_error
|
||||
>>> import os
|
||||
>>>
|
||||
>>> os.environ['CUDA_PROFILE'] = '1'
|
||||
>>>
|
||||
>>> def perform_cuda_operations_with_streams():
|
||||
>>> stream = paddle.cuda.Stream()
|
||||
>>> with paddle.cuda.stream(stream):
|
||||
>>> x = paddle.randn((100, 100), device='cuda')
|
||||
>>> y = paddle.randn((100, 100), device='cuda')
|
||||
>>> z = paddle.mul(x, y)
|
||||
>>> return z
|
||||
>>>
|
||||
>>> paddle.cuda.synchronize()
|
||||
>>> # print("====== Start nsys profiling ======")
|
||||
>>> check_error(cudart().cudaProfilerStart())
|
||||
>>> paddle.core.nvprof_start()
|
||||
>>> paddle.core.nvprof_nvtx_push("Test")
|
||||
>>> result = perform_cuda_operations_with_streams()
|
||||
>>> paddle.core.nvprof_nvtx_pop()
|
||||
>>> # print("CUDA operations completed.")
|
||||
>>> check_error(paddle.cuda.cudart().cudaProfilerStop())
|
||||
>>> # print("====== End nsys profiling ======")
|
||||
"""
|
||||
return base.libpaddle._cudart
|
||||
|
||||
|
||||
class CudaError(RuntimeError):
|
||||
def __init__(self, code: int) -> None:
|
||||
msg = base.libpaddle._cudart.cudaGetErrorString(
|
||||
base.libpaddle._cudart.cudaError(code)
|
||||
)
|
||||
super().__init__(f"{msg} ({code})")
|
||||
|
||||
|
||||
class OutOfMemoryError(RuntimeError):
|
||||
"""Exception raised when a CUDA operation fails due to running out of GPU memory."""
|
||||
|
||||
def __init__(self, msg: str) -> None:
|
||||
super().__init__(msg)
|
||||
|
||||
|
||||
def check_error(res: int) -> None:
|
||||
r"""Check the return code of a CUDA runtime API call.
|
||||
|
||||
This function validates whether the given result code from a CUDA
|
||||
runtime call indicates success. If the result code is not
|
||||
:data:`base.libpaddle._cudart.cudaError.success`, it raises a
|
||||
:class:`CudaError`.
|
||||
|
||||
Args:
|
||||
res (int): The CUDA runtime return code.
|
||||
|
||||
Examples:
|
||||
.. code-block:: pycon
|
||||
|
||||
>>> # doctest: +REQUIRES(env:CUSTOM_DEVICE)
|
||||
>>> from paddle.cuda import check_error
|
||||
>>> check_error(0) # check for cuda success code # will not raise Error
|
||||
>>> # check_error(1) # check for cuda error code 1(invalid argument), will raise Error
|
||||
>>> # check_error(2) # check for cuda error code 2(out of memory), will raise Error
|
||||
"""
|
||||
if res != base.libpaddle._cudart.cudaError.success:
|
||||
raise CudaError(res)
|
||||
|
||||
|
||||
def mem_get_info(device: DeviceLike = None) -> tuple[int, int]:
|
||||
r"""Return the free and total GPU memory (in bytes) for a given device using ``cudaMemGetInfo``.
|
||||
|
||||
This function queries the CUDA runtime for the amount of memory currently
|
||||
available and the total memory capacity of the specified device.
|
||||
|
||||
Args:
|
||||
device (DeviceLike, optional): The target device. If ``None`` (default),
|
||||
the current device, as returned by ``paddle.device.get_device``
|
||||
will be used.
|
||||
|
||||
Returns:
|
||||
tuple[int, int]: A tuple ``(free, total)``, where
|
||||
- ``free`` (int): The number of free bytes of GPU memory available.
|
||||
- ``total`` (int): The total number of bytes of GPU memory.
|
||||
|
||||
Examples:
|
||||
.. code-block:: pycon
|
||||
|
||||
>>> # doctest: +REQUIRES(env:CUSTOM_DEVICE)
|
||||
>>> from paddle.cuda import mem_get_info
|
||||
>>> free_bytes, total_bytes = mem_get_info()
|
||||
"""
|
||||
if device is None:
|
||||
device: str = paddle_device.get_device()
|
||||
|
||||
if isinstance(device, str):
|
||||
device: core.Place = paddle_device._convert_to_place(device)
|
||||
|
||||
if isinstance(device, int):
|
||||
device_id = device
|
||||
else:
|
||||
if not isinstance(device, core.CUDAPlace) or (
|
||||
isinstance(device, core.Place) and not device.is_gpu_place()
|
||||
):
|
||||
raise ValueError(f"Expected a cuda device, but got: {device}")
|
||||
|
||||
device_id = (
|
||||
device.get_device_id()
|
||||
if isinstance(device, core.CUDAPlace)
|
||||
else device.gpu_device_id()
|
||||
)
|
||||
return cudart().cudaMemGetInfo(device_id)
|
||||
|
||||
|
||||
def device_count() -> int:
|
||||
"""
|
||||
Return the number of devices available.
|
||||
|
||||
Returns:
|
||||
int: The number of devices available.
|
||||
|
||||
Examples:
|
||||
.. code-block:: pycon
|
||||
|
||||
>>> # doctest: +REQUIRES(env:GPU)
|
||||
>>> import paddle
|
||||
>>> count = paddle.cuda.device_count()
|
||||
>>> print(f"Number of devices available: {count}")
|
||||
"""
|
||||
# Use paddle.device.device_count() to get the device count
|
||||
# This function supports multiple hardware types (CUDA, XPU, Custom devices)
|
||||
return paddle_device.device_count()
|
||||
|
||||
|
||||
def empty_cache() -> None:
|
||||
"""
|
||||
Release all unoccupied cached memory currently held by the caching allocator so that those can be used in other application and visible in nvidia-smi.
|
||||
|
||||
Returns:
|
||||
None
|
||||
|
||||
Examples:
|
||||
.. code-block:: pycon
|
||||
|
||||
>>> # doctest: +REQUIRES(env:GPU)
|
||||
>>> import paddle
|
||||
>>> # Create a tensor to allocate memory
|
||||
>>> tensor = paddle.randn([1000, 1000], device='cuda')
|
||||
>>> # Delete the tensor to free memory (but it may still be cached)
|
||||
>>> del tensor
|
||||
>>> # Release the cached memory
|
||||
>>> paddle.cuda.empty_cache()
|
||||
"""
|
||||
# Use paddle.device.empty_cache() to release cached memory
|
||||
# This function supports multiple hardware types (CUDA, XPU, Custom devices)
|
||||
paddle_device.empty_cache()
|
||||
|
||||
|
||||
def is_initialized() -> bool:
|
||||
"""
|
||||
Return whether device has been initialized.
|
||||
|
||||
Returns:
|
||||
bool: True if any device (CUDA, XPU, or Custom) has been initialized, False otherwise.
|
||||
|
||||
Examples:
|
||||
.. code-block:: pycon
|
||||
|
||||
>>> # doctest: +REQUIRES(env:GPU)
|
||||
>>> import paddle
|
||||
>>> initialized = paddle.cuda.is_initialized()
|
||||
>>> print(f"Device initialized: {initialized}")
|
||||
"""
|
||||
# Check if any device type has been compiled/initialized
|
||||
# This supports multiple hardware types (CUDA, XPU, Custom devices)
|
||||
cuda_initialized = core.is_compiled_with_cuda()
|
||||
xpu_initialized = core.is_compiled_with_xpu()
|
||||
|
||||
# Check for custom devices - get all available custom device types
|
||||
custom_device_initialized = False
|
||||
custom_device_types = paddle_device.get_all_custom_device_type()
|
||||
if custom_device_types:
|
||||
# Check if any custom device type is compiled/initialized
|
||||
for device_type in custom_device_types:
|
||||
if core.is_compiled_with_custom_device(device_type):
|
||||
custom_device_initialized = True
|
||||
break
|
||||
else:
|
||||
custom_device_initialized = False
|
||||
|
||||
# Return True if any device type is initialized
|
||||
return cuda_initialized or xpu_initialized or custom_device_initialized
|
||||
|
||||
|
||||
def memory_allocated(device: DeviceLike = None) -> int:
|
||||
"""
|
||||
Return the current device memory occupied by tensors in bytes for a given device.
|
||||
|
||||
Args:
|
||||
device (DeviceLike, optional): The device to query. If None, use the current device.
|
||||
Can be paddle.CUDAPlace, paddle.CustomPlace, paddle.XPUPlace, int (device index), or str (device string).
|
||||
|
||||
Returns:
|
||||
int: The current memory occupied by tensors in bytes.
|
||||
|
||||
Examples:
|
||||
.. code-block:: pycon
|
||||
|
||||
>>> # doctest: +REQUIRES(env:GPU)
|
||||
>>> import paddle
|
||||
>>> # Get memory allocated for current device
|
||||
>>> mem_allocated = paddle.cuda.memory_allocated()
|
||||
>>> print(f"Memory allocated: {mem_allocated} bytes")
|
||||
>>>
|
||||
>>> # Get memory allocated for specific device
|
||||
>>> mem_allocated = paddle.cuda.memory_allocated(0)
|
||||
>>> print(f"Memory allocated on device 0: {mem_allocated} bytes")
|
||||
"""
|
||||
# Use paddle.device.memory_allocated() to get the memory allocated
|
||||
# This function supports multiple hardware types (CUDA, XPU, Custom devices)
|
||||
return paddle_device.memory_allocated(device)
|
||||
|
||||
|
||||
def max_memory_allocated(device: DeviceLike = None) -> int:
|
||||
'''
|
||||
Return the peak size of memory that is allocated to tensor of the given device.
|
||||
|
||||
Note:
|
||||
The size of memory allocated to tensor is 256-byte aligned in Paddle, which may larger than the memory size that tensor actually need.
|
||||
For instance, a float32 0-D Tensor with shape [] will take up 256 bytes memory, even though storing a float32 data requires only 4 bytes.
|
||||
|
||||
Args:
|
||||
device(paddle.CUDAPlace|int|str|None, optional): The device, the id of the device or
|
||||
the string name of device like 'gpu:x'. If device is None, the device is the current device.
|
||||
Default: None.
|
||||
|
||||
Return:
|
||||
int: The peak size of memory that is allocated to tensor of the given device, in bytes.
|
||||
|
||||
Examples:
|
||||
.. code-block:: pycon
|
||||
|
||||
>>> # doctest: +REQUIRES(env:GPU)
|
||||
>>> import paddle
|
||||
>>> paddle.device.set_device('gpu') # or '<custom_device>'
|
||||
|
||||
>>> max_memory_allocated_size = paddle.cuda.max_memory_allocated(paddle.CUDAPlace(0))
|
||||
>>> max_memory_allocated_size = paddle.cuda.max_memory_allocated(0)
|
||||
>>> max_memory_allocated_size = paddle.cuda.max_memory_allocated("gpu:0")
|
||||
'''
|
||||
return paddle_device.max_memory_allocated(device)
|
||||
|
||||
|
||||
def max_memory_reserved(device: DeviceLike = None) -> int:
|
||||
'''
|
||||
Return the peak size of memory that is held by the allocator of the given device.
|
||||
|
||||
Args:
|
||||
device(paddle.Place|int|str|None, optional): The device, the id of the device or
|
||||
the string name of device like 'gpu:x'. If device is None, the device is the current device.
|
||||
Default: None.
|
||||
|
||||
Return:
|
||||
int: The peak size of memory that is held by the allocator of the given device, in bytes.
|
||||
|
||||
Examples:
|
||||
.. code-block:: pycon
|
||||
|
||||
>>> # doctest: +REQUIRES(env:GPU)
|
||||
>>> import paddle
|
||||
>>> paddle.device.set_device('gpu') # or '<custom_device>'
|
||||
|
||||
>>> max_memory_reserved_size = paddle.cuda.max_memory_reserved(paddle.CUDAPlace(0))
|
||||
>>> max_memory_reserved_size = paddle.cuda.max_memory_reserved(0)
|
||||
>>> max_memory_reserved_size = paddle.cuda.max_memory_reserved("gpu:0")
|
||||
'''
|
||||
return paddle_device.max_memory_reserved(device)
|
||||
|
||||
|
||||
def reset_max_memory_allocated(device: DeviceLike | None = None) -> None:
|
||||
'''
|
||||
Reset the peak size of memory that is allocated to tensor of the given device.
|
||||
|
||||
Args:
|
||||
device(paddle.Place|int|str|None, optional): The device, the id of the device or
|
||||
the string name of device like 'gpu:x'. If device is None, the device is the current device.
|
||||
Default: None.
|
||||
|
||||
Examples:
|
||||
.. code-block:: pycon
|
||||
|
||||
>>> # doctest: +REQUIRES(env:GPU)
|
||||
>>> import paddle
|
||||
>>> paddle.device.set_device('gpu') # or '<custom_device>'
|
||||
|
||||
>>> paddle.cuda.reset_max_memory_allocated(paddle.CUDAPlace(0))
|
||||
>>> paddle.cuda.reset_max_memory_allocated(0)
|
||||
>>> paddle.cuda.reset_max_memory_allocated("gpu:0")
|
||||
'''
|
||||
|
||||
return paddle_device.reset_max_memory_allocated(device)
|
||||
|
||||
|
||||
def reset_max_memory_reserved(device: DeviceLike | None = None) -> None:
|
||||
'''
|
||||
Reset the peak size of memory that is held by the allocator of the given device.
|
||||
|
||||
Args:
|
||||
device(paddle.Place|int|str|None, optional): The device, the id of the device or
|
||||
the string name of device like 'gpu:x'. If device is None, the device is the current device.
|
||||
Default: None.
|
||||
|
||||
Examples:
|
||||
.. code-block:: pycon
|
||||
|
||||
>>> # doctest: +REQUIRES(env:GPU)
|
||||
>>> import paddle
|
||||
>>> paddle.device.set_device('gpu') # or '<custom_device>'
|
||||
|
||||
>>> paddle.cuda.reset_max_memory_reserved(paddle.CUDAPlace(0))
|
||||
>>> paddle.cuda.reset_max_memory_reserved(0)
|
||||
>>> paddle.cuda.reset_max_memory_reserved("gpu:0")
|
||||
'''
|
||||
return paddle_device.reset_max_memory_reserved(device)
|
||||
|
||||
|
||||
def memory_reserved(device: DeviceLike = None) -> int:
|
||||
"""
|
||||
Return the current device memory managed by the caching allocator in bytes for a given device.
|
||||
|
||||
Args:
|
||||
device (DeviceLike, optional): The device to query. If None, use the current device.
|
||||
Can be paddle.CUDAPlace, paddle.CustomPlace, paddle.XPUPlace, int (device index), or str (device string).
|
||||
|
||||
Returns:
|
||||
int: The current memory managed by the caching allocator in bytes.
|
||||
|
||||
Examples:
|
||||
.. code-block:: pycon
|
||||
|
||||
>>> # doctest: +REQUIRES(env:GPU)
|
||||
>>> import paddle
|
||||
>>> # Get memory reserved for current device
|
||||
>>> mem_reserved = paddle.cuda.memory_reserved()
|
||||
>>> print(f"Memory reserved: {mem_reserved} bytes")
|
||||
>>>
|
||||
>>> # Get memory reserved for specific device
|
||||
>>> mem_reserved = paddle.cuda.memory_reserved(0)
|
||||
>>> print(f"Memory reserved on device 0: {mem_reserved} bytes")
|
||||
"""
|
||||
# Use paddle.device.memory_reserved() to get the memory reserved
|
||||
# This function supports multiple hardware types (CUDA, XPU, Custom devices)
|
||||
return paddle_device.memory_reserved(device)
|
||||
|
||||
|
||||
def set_device(device: DeviceLike) -> None:
|
||||
"""
|
||||
Set the current device.
|
||||
|
||||
Args:
|
||||
device (DeviceLike): The CUDA device to set as current. Can be an int
|
||||
(GPU index), a CUDA/GPU device string (e.g. 'gpu:0' or 'cuda:0'),
|
||||
or a paddle.CUDAPlace. For XPU / custom devices, use
|
||||
paddle.device.set_device().
|
||||
|
||||
Returns:
|
||||
None
|
||||
|
||||
Examples:
|
||||
.. code-block:: pycon
|
||||
|
||||
>>> # doctest: +REQUIRES(env:GPU)
|
||||
>>> import paddle
|
||||
>>> # Set current device to GPU:0
|
||||
>>> paddle.cuda.set_device(0)
|
||||
>>> # Set current device to GPU:0
|
||||
>>> paddle.cuda.set_device('gpu:0')
|
||||
>>> # Set current device to a specific CUDAPlace
|
||||
>>> place = paddle.CUDAPlace(0)
|
||||
>>> paddle.cuda.set_device(place)
|
||||
"""
|
||||
# Convert CUDA device identifiers to paddle.device's GPU device string.
|
||||
if isinstance(device, int):
|
||||
# An int index always refers to a CUDA GPU.
|
||||
# raises if Paddle is not compiled with CUDA.
|
||||
device_str = f'gpu:{device}'
|
||||
elif isinstance(device, str):
|
||||
# paddle.cuda only accepts CUDA/GPU device strings. Use
|
||||
# paddle.device.set_device() for XPU / custom devices.
|
||||
lower_device = device.lower()
|
||||
if lower_device == 'gpu' or lower_device.startswith('gpu:'):
|
||||
device_str = lower_device
|
||||
elif lower_device == 'cuda':
|
||||
device_str = 'gpu'
|
||||
elif lower_device.startswith('cuda:'):
|
||||
device_str = f"gpu:{lower_device.split(':', 1)[1]}"
|
||||
else:
|
||||
raise ValueError(
|
||||
f"paddle.cuda.set_device only supports CUDA/GPU device strings "
|
||||
f"(e.g. 'gpu', 'gpu:0', 'cuda:0'), but got '{device}'. "
|
||||
f"Use paddle.device.set_device() for other devices."
|
||||
)
|
||||
elif isinstance(device, core.CUDAPlace):
|
||||
# Convert CUDAPlace object to string format
|
||||
device_str = f'gpu:{device.get_device_id()}'
|
||||
else:
|
||||
raise ValueError(
|
||||
f"Unsupported device type: {type(device)}. paddle.cuda.set_device only "
|
||||
f"supports int, a CUDA/GPU device string, or paddle.CUDAPlace. Use "
|
||||
f"paddle.device.set_device() for XPU / custom devices."
|
||||
)
|
||||
|
||||
# Call paddle.device.set_device() to set the current device
|
||||
paddle_device.set_device(device_str)
|
||||
|
||||
|
||||
def get_stream_from_external(
|
||||
data_ptr: int, device: DeviceLike = None
|
||||
) -> Stream:
|
||||
"""
|
||||
Wrap an externally allocated CUDA stream into a Paddle :class:`paddle.cuda.Stream` object.
|
||||
|
||||
This function allows integrating CUDA streams allocated by other libraries
|
||||
into Paddle, enabling multi-library interoperability and data exchange.
|
||||
|
||||
Note:
|
||||
- This function does not manage the lifetime of the external stream.
|
||||
It is the caller's responsibility to ensure the external stream remains valid
|
||||
while the returned Paddle stream is in use.
|
||||
- Providing an incorrect `device` may result in errors during kernel launches.
|
||||
|
||||
Args:
|
||||
data_ptr (int): Integer representation of the external `cudaStream_t`.
|
||||
device (DeviceLike, optional): The device where the external stream was created.
|
||||
Can be a Paddle device string (e.g., "cuda:0"), an int index (e.g., 0),
|
||||
or a PaddlePlace (CUDAPlace). Default: None (current device).
|
||||
|
||||
Returns:
|
||||
paddle.cuda.Stream: A Paddle Stream object that wraps the external CUDA stream.
|
||||
|
||||
Examples:
|
||||
.. code-block:: pycon
|
||||
|
||||
>>> # doctest: +REQUIRES(env:CUSTOM_DEVICE)
|
||||
>>> import paddle
|
||||
|
||||
>>> # Assume an external library provides a stream pointer:original_raw_ptr
|
||||
>>> # doctest: +SKIP('original_raw_ptr not exist')
|
||||
>>> original_raw_ptr = 77777
|
||||
>>> external_stream = paddle.cuda.get_stream_from_external(original_raw_ptr)
|
||||
"""
|
||||
|
||||
device = _device_to_paddle(device)
|
||||
stream_ex = paddle_device.get_stream_from_external(data_ptr, device)
|
||||
|
||||
return stream_ex
|
||||
|
||||
|
||||
__all__ = [
|
||||
"CudaError",
|
||||
"OutOfMemoryError",
|
||||
"cudart",
|
||||
"check_error",
|
||||
"is_available",
|
||||
"is_initialized",
|
||||
"mem_get_info",
|
||||
"synchronize",
|
||||
"current_stream",
|
||||
"get_device_properties",
|
||||
"get_device_name",
|
||||
"get_device_capability",
|
||||
"stream",
|
||||
"Stream",
|
||||
"get_stream_from_external",
|
||||
"current_device",
|
||||
"device_count",
|
||||
"empty_cache",
|
||||
"is_initialized",
|
||||
"memory_allocated",
|
||||
"memory_reserved",
|
||||
"set_device",
|
||||
"set_stream",
|
||||
"manual_seed_all",
|
||||
"get_rng_state",
|
||||
"set_rng_state",
|
||||
'FloatTensor',
|
||||
'DoubleTensor',
|
||||
'HalfTensor',
|
||||
'BFloat16Tensor',
|
||||
'ByteTensor',
|
||||
'CharTensor',
|
||||
'ShortTensor',
|
||||
'IntTensor',
|
||||
'LongTensor',
|
||||
'BoolTensor',
|
||||
"device",
|
||||
"is_bf16_supported",
|
||||
"manual_seed",
|
||||
"max_memory_allocated",
|
||||
"reset_peak_memory_stats",
|
||||
"Event",
|
||||
"ipc_collect",
|
||||
"StreamContext",
|
||||
"amp",
|
||||
"CUDAGraph",
|
||||
"graph",
|
||||
"graph_pool_handle",
|
||||
]
|
||||
Reference in New Issue
Block a user