-
Notifications
You must be signed in to change notification settings - Fork 6k
[API Compatibility] Fix Tensor.type #79641
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Closed
Closed
Changes from 32 commits
Commits
Show all changes
35 commits
Select commit
Hold shift + click to select a range
91b9144
align 3 Tensor api and PReLU
Manfredss 3451263
Merge branch 'develop' of https://github.com/paddlepaddle/paddle into…
Manfredss d5154f3
fix PReLU, fix enable_compat restore after using guard
Manfredss 4865ecc
add test coverage
Manfredss 8aa81ef
fix per bot feedback
Manfredss 7f2684a
fix typo
Manfredss 7eda286
also fix paddle.distributions.categorical.Categorical
Manfredss ec4686b
fix
Manfredss cf76ec4
fix
Manfredss f668adb
Refine compat levels and guard state restoration
Manfredss 111a665
Merge branch 'develop' of https://github.com/paddlepaddle/paddle into…
Manfredss b3bb47c
remove assertion
Manfredss 2f3cc36
fix fleet tests failure
Manfredss ec1295c
Merge branch 'develop' of https://github.com/paddlepaddle/paddle into…
Manfredss f514e71
staged
Manfredss a721161
Merge branch 'develop' of https://github.com/paddlepaddle/paddle into…
Manfredss c64978f
reframe use_compat_guard
Manfredss 826269a
remove unused methods
Manfredss a119dbe
fix counter; add dispatch_property
Manfredss 5a5b7b3
fix
Manfredss 219307c
fix tests
Manfredss fde90cf
Merge branch 'develop' of https://github.com/paddlepaddle/paddle into…
Manfredss b0217d4
Merge branch 'develop' of https://github.com/paddlepaddle/paddle into…
Manfredss 82f8ebf
fix
Manfredss ce136ec
Merge branch 'develop' of https://github.com/paddlepaddle/paddle into…
Manfredss 3eeb401
improve code per review suggestions
Manfredss 43c95f1
fix
Manfredss 8c035b1
refine
Manfredss 0488bce
fix Tensor.type so that paconvert can pass without check_value=False
Manfredss 2921bbb
fix factory device missed
Manfredss 6132cef
Merge branch 'develop' of https://github.com/paddlepaddle/paddle into…
Manfredss c995fa1
fix
Manfredss 9c9fe9b
fix device convert to cpu silently
Manfredss 61b6e77
add tests
Manfredss 25748d7
Merge branch 'develop' of https://github.com/paddlepaddle/paddle into…
Manfredss File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -40,6 +40,7 @@ | |
| from collections.abc import Sequence | ||
|
|
||
| from paddle import Tensor | ||
| from paddle._typing import DTypeLike | ||
|
|
||
| __all__ = [ | ||
| 'allclose', | ||
|
|
@@ -56,6 +57,26 @@ | |
| ] | ||
|
|
||
|
|
||
| _TENSOR_TYPE_DTYPES = { | ||
| 'HalfTensor': 'float16', | ||
| 'FloatTensor': 'float32', | ||
| 'DoubleTensor': 'float64', | ||
| 'Float8_e4m3fnTensor': 'float8_e4m3fn', | ||
| 'Float8_e5m2Tensor': 'float8_e5m2', | ||
| 'BFloat16Tensor': 'bfloat16', | ||
| 'ByteTensor': 'uint8', | ||
| 'CharTensor': 'int8', | ||
| 'ShortTensor': 'int16', | ||
| 'IntTensor': 'int32', | ||
| 'LongTensor': 'int64', | ||
| 'BoolTensor': 'bool', | ||
| 'ComplexFloatTensor': 'complex64', | ||
| 'ComplexDoubleTensor': 'complex128', | ||
| } | ||
|
|
||
| _DTYPE_TENSOR_TYPES = {v: k for k, v in _TENSOR_TYPE_DTYPES.items()} | ||
|
|
||
|
|
||
| def __getattr__(name): | ||
| if name == "paddle_triton": | ||
| return paddle_triton_fun() | ||
|
|
@@ -66,6 +87,129 @@ def __getattr__(name): | |
| raise AttributeError(f"module {__name__!r} has no attribute {name!r}") | ||
|
|
||
|
|
||
| def _tensor_numel(input: Tensor) -> int: | ||
| """ | ||
| Returns the total number of elements in the tensor. | ||
|
|
||
| Args: | ||
| input (Tensor): The input tensor. | ||
|
|
||
| Returns: | ||
| int: The number of elements in ``input``. | ||
| """ | ||
| return int(input.size) | ||
|
|
||
|
|
||
| def _tensor_type_name(input: Tensor) -> str: | ||
| """The tensor type name of ``input``, e.g. ``'torch.cuda.sparse.FloatTensor'``, | ||
| following ``torch.Tensor.type``. The device segment is ``'cuda'`` for GPU, | ||
| ``'xpu'`` for XPU and the device type itself for custom devices, e.g. | ||
| ``'torch.npu.FloatTensor'``. Dtypes without a tensor type name fall back to | ||
| the dtype string.""" | ||
| dtype_name = str(input.dtype).removeprefix("paddle.") | ||
| tensor_type = _DTYPE_TENSOR_TYPES.get(dtype_name) | ||
| if tensor_type is None: | ||
| return str(input.dtype) | ||
| segments = ["torch"] | ||
| place = input.place | ||
| if place.is_gpu_place(): | ||
| segments.append("cuda") | ||
| elif place.is_xpu_place(): | ||
| segments.append("xpu") | ||
| elif place.is_custom_place(): | ||
| segments.append(place.custom_device_type().lower()) | ||
| if input.is_sparse_coo(): | ||
| segments.append("sparse") | ||
| segments.append(tensor_type) | ||
| return ".".join(segments) | ||
|
|
||
|
|
||
| def _tensor_type( | ||
| input: Tensor, | ||
| dtype: DTypeLike | str | type | None = None, | ||
| non_blocking: bool = False, | ||
| **kwargs: Any, | ||
| ) -> str | Tensor: | ||
| """ | ||
| Returns the tensor type when ``dtype`` is not specified, otherwise casts | ||
| the tensor to the requested type. | ||
|
|
||
| Args: | ||
| input (Tensor): The input tensor. | ||
| dtype (DTypeLike|str|type|None, optional): The target tensor type or | ||
| data type. Qualified ``torch.*`` and ``paddle.*`` dtype or tensor | ||
| type strings are supported. When it is ``None``, returns the tensor | ||
| type name. Default: ``None``. | ||
| non_blocking (bool, optional): Whether the conversion may occur | ||
| asynchronously. Default: ``False``. | ||
|
|
||
| Returns: | ||
| str|Tensor: The tensor type name when ``dtype`` is ``None``, e.g. | ||
| ``'torch.FloatTensor'``, ``'torch.cuda.FloatTensor'`` or | ||
| ``'torch.cuda.sparse.FloatTensor'``, encoding the dtype, the place | ||
| and the sparse COO layout as ``torch.Tensor.type`` does; otherwise, | ||
| a tensor with the requested type. | ||
| """ | ||
| if "async" in kwargs: | ||
| non_blocking = kwargs.pop("async") | ||
| if kwargs: | ||
| key = next(iter(kwargs)) | ||
| raise TypeError(f"type() got an unexpected keyword argument {key!r}") | ||
|
|
||
| if dtype is None: | ||
| return _tensor_type_name(input) | ||
|
|
||
| device = None | ||
| if getattr(dtype, "__name__", None) in _TENSOR_TYPE_DTYPES: | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 当前 head 已改为带设备标记的独立 CUDA factory,并加入 CUDA 构造覆盖测试,原问题已修复。 |
||
| # tensor factory classes, e.g. paddle.DoubleTensor | ||
| device = getattr(dtype, "_device", None) or "cpu" | ||
| dtype = getattr(paddle, _TENSOR_TYPE_DTYPES[dtype.__name__]) | ||
| elif isinstance(dtype, str): | ||
| dtype_string = dtype | ||
| tensor_type = dtype_string.rsplit(".", 1)[-1] | ||
| if not dtype_string.startswith(("torch.", "paddle.")): | ||
| raise ValueError(f"invalid type: {dtype_string!r}") | ||
| if tensor_type in _TENSOR_TYPE_DTYPES: | ||
| dtype = getattr(paddle, _TENSOR_TYPE_DTYPES[tensor_type]) | ||
| device = ( | ||
| "gpu" | ||
| if dtype_string.startswith(("torch.cuda.", "paddle.cuda.")) | ||
| else "cpu" | ||
| ) | ||
| elif tensor_type in _TENSOR_TYPE_DTYPES.values(): | ||
| dtype = getattr(paddle, tensor_type) | ||
| else: | ||
| raise ValueError(f"invalid type: {dtype_string!r}") | ||
|
|
||
| same_device = ( | ||
| device is None | ||
| or (device == "cpu" and input.place.is_cpu_place()) | ||
| or (device == "gpu" and input.place.is_gpu_place()) | ||
| ) | ||
| if input.dtype == dtype and same_device: | ||
| return input | ||
|
|
||
| return input.to( | ||
| device=device, | ||
| dtype=dtype, | ||
| blocking=not non_blocking, | ||
| ) | ||
|
|
||
|
|
||
| @property | ||
| def _tensor_is_sparse(input: Tensor) -> bool: | ||
| """ | ||
| Whether the tensor uses the sparse COO layout. | ||
|
|
||
| Args: | ||
| input (Tensor): The input tensor. | ||
|
|
||
| Returns: | ||
| bool: ``True`` for a sparse COO tensor, otherwise ``False``. | ||
| """ | ||
| return input.is_sparse_coo() | ||
|
|
||
|
|
||
| def allclose( | ||
| input: Tensor, | ||
| other: Tensor, | ||
|
|
@@ -1132,3 +1276,21 @@ def GetShapeOnDimInRange(shape, dim: int) -> int: | |
| split_size_or_sections | ||
| ) | ||
| return tuple(_C_ops.split(tensor, split_size_or_sections, dim)) | ||
|
|
||
|
|
||
| # ``paddle.Tensor`` APIs routed to their ``paddle.compat`` implementations | ||
| _TENSOR_API_OVERRIDES = { | ||
| 'allclose': allclose, | ||
| 'equal': equal, | ||
| 'slogdet': slogdet, | ||
| 'sort': sort, | ||
| 'split': split, | ||
| 'min': min, | ||
| 'max': max, | ||
| 'unique': unique, | ||
| 'median': median, | ||
| 'nanmedian': nanmedian, | ||
| 'numel': _tensor_numel, | ||
| 'type': _tensor_type, | ||
| 'is_sparse': _tensor_is_sparse, | ||
| } | ||
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
torch.xpu.*/custom-device 类型名,但_tensor_type()解析字符串时只把torch.cuda./paddle.cuda.映射到 GPU,其余合法torch.*名称都落到device="cpu"。因此t.type("torch.xpu.FloatTensor")(以及 custom-device 对应名称)会把 Tensor 从 XPU/自定义设备错误迁移到 CPU;当前测试只覆盖名称生成,没有覆盖反向转换。请补齐 XPU/custom 的设备解析与 round-trip 测试。There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@risemeup1111 现在的改动可以吗
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
XPU/custom 的解析已补齐,但当前修改仍不完整:
torch.FloatTensor/paddle.FloatTensor这类无设备段的 tensor type 现在返回device=None,GPU Tensor 调用后会保留在 GPU;PyTorch 中这些名称表示 CPU tensor type,应转到 CPU。请让已识别的 tensor-type 字符串在无设备段时默认cpu,同时保留torch.float32这类 dtype-only 字符串的device=None,并补 GPU→torch.FloatTensor回归测试。Uh oh!
There was an error while loading. Please reload this page.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@risemeup1111 我觉得像
torch.FloatTensor/paddle.FloatTensor这样的调用,本身就不应该涉及设备的转换,所以device=None保持设备不变是对的;即参数中有设备段或者显式表明了类(比如 paddle.cuda.DoubleTensor)才要管设备,否则保持不变There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
这里的
device=None只适用于 dtype-only 参数(例如torch.float32),不适用于 tensor type factory。PyTorch 中torch.FloatTensor是 CPU tensor class,torch.cuda.FloatTensor才是 CUDA class;本 PR 的_tensor_type_name()也明确把 CPU Tensor 编码成torch.FloatTensor、GPU Tensor 编码成torch.cuda.FloatTensor。因此t.type(t.type())必须保持 round-trip,GPU Tensor 的t.type("torch.FloatTensor")应转换到 CPU;否则返回的类型名不能表达并恢复 Tensor 的 place。请将无设备段的 tensor-type 字符串区分为device="cpu",同时继续让torch.float32保持device=None。There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@risemeup1111 现在可以没 审查一下