Skip to content

Commit a73f8c7

Browse files
authored
[Cpp API Compatibility] add SymInt related API (PaddlePaddle#77301)
1 parent f975ea0 commit a73f8c7

4 files changed

Lines changed: 207 additions & 36 deletions

File tree

paddle/phi/api/include/compat/ATen/core/TensorBase.h

Lines changed: 19 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@
2222
#include <c10/core/ScalarType.h>
2323
#include <c10/core/Storage.h>
2424
#include <c10/core/SymInt.h>
25+
#include <c10/core/SymIntArrayRef.h>
2526
#include <c10/core/TensorOptions.h>
2627
#include <utils/int_array_ref_conversion.h>
2728
#include <utils/scalar_type_conversion.h>
@@ -86,24 +87,41 @@ class PADDLE_API TensorBase {
8687
}
8788
return tensor_.strides()[static_cast<int>(dim)];
8889
}
90+
91+
c10::SymInt sym_stride(int64_t dim) const {
92+
return static_cast<c10::SymInt>(stride(dim));
93+
}
94+
8995
c10::IntArrayRef strides() const {
9096
return compat::_PD_PhiDDimToIntArrayRef(tensor_.strides());
9197
}
9298

99+
c10::SymIntArrayRef sym_strides() const {
100+
return c10::SymIntArrayRef(strides());
101+
}
102+
93103
int64_t size(int64_t dim) const {
94104
if (dim < 0) {
95105
dim += tensor_.dims().size();
96106
}
97107
return tensor_.dims()[static_cast<int>(dim)];
98108
}
99109

110+
c10::SymInt sym_size(int64_t dim) const {
111+
return static_cast<c10::SymInt>(size(dim));
112+
}
113+
100114
c10::IntArrayRef sizes() const {
101115
return compat::_PD_PhiDDimToIntArrayRef(tensor_.dims());
102116
}
103117

118+
c10::SymIntArrayRef sym_sizes() const { return c10::SymIntArrayRef(sizes()); }
119+
104120
int64_t numel() const { return tensor_.numel(); }
105121

106-
c10::ScalarType dtype() const { // Should we use `TypeMeta` here?
122+
c10::SymInt sym_numel() const { return static_cast<c10::SymInt>(numel()); }
123+
124+
c10::ScalarType dtype() const { // Should we use `caffe2::TypeMeta` here?
107125
return compat::_PD_PhiDataTypeToAtenScalarType(tensor_.dtype());
108126
}
109127

test/cpp/compat/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ if(NOT WIN32)
44
nv_test(compat_squeeze_test SRCS compat_squeeze_test.cc)
55
nv_test(c10_ScalarType_test SRCS c10_ScalarType_test.cc)
66
nv_test(c10_storage_test SRCS c10_storage_test.cc)
7+
nv_test(c10_SizesAndStrides_test SRCS c10_SizesAndStrides_test.cc)
78
cc_test(torch_library_test SRCS torch_library_test.cc)
89
endif()
910
endif()
Lines changed: 187 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,187 @@
1+
// Copyright (c) 2025 PaddlePaddle Authors. All Rights Reserved.
2+
//
3+
// Licensed under the Apache License, Version 2.0 (the "License");
4+
// you may not use this file except in compliance with the License.
5+
// You may obtain a copy of the License at
6+
//
7+
// http://www.apache.org/licenses/LICENSE-2.0
8+
//
9+
// Unless required by applicable law or agreed to in writing, software
10+
// distributed under the License is distributed on an "AS IS" BASIS,
11+
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
// See the License for the specific language governing permissions and
13+
// limitations under the License.
14+
15+
#include <ATen/Functions.h>
16+
#include <ATen/core/TensorBody.h>
17+
#include <ATen/cuda/EmptyTensor.h>
18+
#include <ATen/native/cuda/Resize.h>
19+
#include <ATen/ops/tensor.h>
20+
#include <c10/core/ScalarType.h>
21+
#include <c10/core/SymInt.h>
22+
#include <c10/core/TensorOptions.h>
23+
#if defined(PADDLE_WITH_CUDA) || defined(PADDLE_WITH_HIP)
24+
#include <c10/cuda/CUDAFunctions.h>
25+
#include <c10/cuda/CUDAGuard.h>
26+
#endif
27+
#include "ATen/ATen.h"
28+
#include "gtest/gtest.h"
29+
#include "paddle/phi/common/float16.h"
30+
#include "torch/all.h"
31+
32+
TEST(TensorBaseTest, DimensionAPIs) {
33+
// Test dimension related APIs
34+
at::TensorBase tensor = at::ones({2, 3, 4}, at::kFloat);
35+
36+
// Test sizes()
37+
auto sizes = tensor.sizes();
38+
ASSERT_EQ(sizes.size(), 3);
39+
ASSERT_EQ(sizes[0], 2);
40+
ASSERT_EQ(sizes[1], 3);
41+
ASSERT_EQ(sizes[2], 4);
42+
43+
// Test size(dim)
44+
ASSERT_EQ(tensor.size(0), 2);
45+
ASSERT_EQ(tensor.size(1), 3);
46+
ASSERT_EQ(tensor.size(2), 4);
47+
48+
// Test strides()
49+
auto strides = tensor.strides();
50+
ASSERT_EQ(strides.size(), 3);
51+
ASSERT_EQ(strides[0], 12); // 3*4
52+
ASSERT_EQ(strides[1], 4); // 4
53+
ASSERT_EQ(strides[2], 1); // contiguous
54+
55+
// Test stride(dim)
56+
ASSERT_EQ(tensor.stride(0), 12);
57+
ASSERT_EQ(tensor.stride(1), 4);
58+
ASSERT_EQ(tensor.stride(2), 1);
59+
60+
// Test numel()
61+
ASSERT_EQ(tensor.numel(), 24); // 2*3*4
62+
63+
// Test dim()/ndimension()
64+
ASSERT_EQ(tensor.dim(), 3);
65+
ASSERT_EQ(tensor.ndimension(), 3);
66+
}
67+
68+
TEST(TestSymbolicInt, SymSizeAPI) {
69+
// Test sym_size() API
70+
at::TensorBase tensor = at::ones({2, 3, 4}, at::kFloat);
71+
72+
// Test sym_size(dim) returns c10::SymInt
73+
c10::SymInt sym_size_0 = tensor.sym_size(0);
74+
c10::SymInt sym_size_1 = tensor.sym_size(1);
75+
c10::SymInt sym_size_2 = tensor.sym_size(2);
76+
77+
ASSERT_EQ(sym_size_0, 2);
78+
ASSERT_EQ(sym_size_1, 3);
79+
ASSERT_EQ(sym_size_2, 4);
80+
81+
// Test sym_size with negative index
82+
c10::SymInt sym_size_neg1 = tensor.sym_size(-1);
83+
c10::SymInt sym_size_neg2 = tensor.sym_size(-2);
84+
c10::SymInt sym_size_neg3 = tensor.sym_size(-3);
85+
86+
ASSERT_EQ(sym_size_neg1, 4);
87+
ASSERT_EQ(sym_size_neg2, 3);
88+
ASSERT_EQ(sym_size_neg3, 2);
89+
}
90+
91+
TEST(TestSymbolicInt, SymSizesAPI) {
92+
// Test sym_sizes() API
93+
at::TensorBase tensor = at::ones({2, 3, 4, 5}, at::kFloat);
94+
95+
// Test sym_sizes() returns c10::SymIntArrayRef
96+
c10::SymIntArrayRef sym_sizes = tensor.sym_sizes();
97+
98+
ASSERT_EQ(sym_sizes.size(), 4);
99+
ASSERT_EQ(sym_sizes[0], 2);
100+
ASSERT_EQ(sym_sizes[1], 3);
101+
ASSERT_EQ(sym_sizes[2], 4);
102+
ASSERT_EQ(sym_sizes[3], 5);
103+
}
104+
105+
TEST(TestSymbolicInt, SymStrideAPI) {
106+
// Test sym_stride() API
107+
at::TensorBase tensor = at::ones({2, 3, 4}, at::kFloat);
108+
109+
// Test sym_stride(dim) returns c10::SymInt
110+
c10::SymInt sym_stride_0 = tensor.sym_stride(0);
111+
c10::SymInt sym_stride_1 = tensor.sym_stride(1);
112+
c10::SymInt sym_stride_2 = tensor.sym_stride(2);
113+
114+
ASSERT_EQ(sym_stride_0, 12); // 3*4
115+
ASSERT_EQ(sym_stride_1, 4); // 4
116+
ASSERT_EQ(sym_stride_2, 1); // contiguous
117+
118+
// Test sym_stride with negative index
119+
c10::SymInt sym_stride_neg1 = tensor.sym_stride(-1);
120+
c10::SymInt sym_stride_neg2 = tensor.sym_stride(-2);
121+
122+
ASSERT_EQ(sym_stride_neg1, 1);
123+
ASSERT_EQ(sym_stride_neg2, 4);
124+
}
125+
126+
TEST(TestSymbolicInt, SymStridesAPI) {
127+
// Test sym_strides() API
128+
at::TensorBase tensor = at::ones({2, 3, 4}, at::kFloat);
129+
130+
// Test sym_strides() returns c10::SymIntArrayRef
131+
c10::SymIntArrayRef sym_strides = tensor.sym_strides();
132+
133+
ASSERT_EQ(sym_strides.size(), 3);
134+
ASSERT_EQ(sym_strides[0], 12); // 3*4
135+
ASSERT_EQ(sym_strides[1], 4); // 4
136+
ASSERT_EQ(sym_strides[2], 1); // contiguous
137+
}
138+
139+
TEST(TestSymbolicInt, SymNumelAPI) {
140+
// Test sym_numel() API
141+
at::TensorBase tensor = at::ones({2, 3, 4}, at::kFloat);
142+
143+
// Test sym_numel() returns c10::SymInt
144+
c10::SymInt sym_numel = tensor.sym_numel();
145+
146+
ASSERT_EQ(sym_numel, 24); // 2*3*4
147+
148+
// Test with different shape
149+
at::TensorBase tensor2 = at::ones({5, 6, 7, 8}, at::kFloat);
150+
c10::SymInt sym_numel2 = tensor2.sym_numel();
151+
152+
ASSERT_EQ(sym_numel2, 1680); // 5*6*7*8
153+
}
154+
155+
TEST(TestSymbolicInt, SymAPIsConsistency) {
156+
// Test that sym_* APIs return values consistent with non-sym APIs
157+
at::TensorBase tensor = at::ones({3, 4, 5, 6}, at::kFloat);
158+
159+
// Test sym_size vs size
160+
for (int64_t i = 0; i < tensor.dim(); ++i) {
161+
ASSERT_EQ(tensor.sym_size(i), tensor.size(i));
162+
}
163+
164+
// Test sym_stride vs stride
165+
for (int64_t i = 0; i < tensor.dim(); ++i) {
166+
ASSERT_EQ(tensor.sym_stride(i), tensor.stride(i));
167+
}
168+
169+
// Test sym_numel vs numel
170+
ASSERT_EQ(tensor.sym_numel(), tensor.numel());
171+
172+
// Test sym_sizes vs sizes
173+
auto sizes = tensor.sizes();
174+
auto sym_sizes = tensor.sym_sizes();
175+
ASSERT_EQ(sizes.size(), sym_sizes.size());
176+
for (size_t i = 0; i < sizes.size(); ++i) {
177+
ASSERT_EQ(sym_sizes[i], sizes[i]);
178+
}
179+
180+
// Test sym_strides vs strides
181+
auto strides = tensor.strides();
182+
auto sym_strides = tensor.sym_strides();
183+
ASSERT_EQ(strides.size(), sym_strides.size());
184+
for (size_t i = 0; i < strides.size(); ++i) {
185+
ASSERT_EQ(sym_strides[i], strides[i]);
186+
}
187+
}

test/cpp/compat/compat_basic_test.cc

Lines changed: 0 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -53,41 +53,6 @@ TEST(TensorBaseTest, DataPtrAPIs) {
5353
ASSERT_NE(mutable_ptr, nullptr);
5454
ASSERT_EQ(mutable_ptr, void_ptr);
5555
}
56-
TEST(TensorBaseTest, DimensionAPIs) {
57-
// Test dimension related APIs
58-
at::TensorBase tensor = at::ones({2, 3, 4}, at::kFloat);
59-
60-
// Test sizes()
61-
auto sizes = tensor.sizes();
62-
ASSERT_EQ(sizes.size(), 3);
63-
ASSERT_EQ(sizes[0], 2);
64-
ASSERT_EQ(sizes[1], 3);
65-
ASSERT_EQ(sizes[2], 4);
66-
67-
// Test size(dim)
68-
ASSERT_EQ(tensor.size(0), 2);
69-
ASSERT_EQ(tensor.size(1), 3);
70-
ASSERT_EQ(tensor.size(2), 4);
71-
72-
// Test strides()
73-
auto strides = tensor.strides();
74-
ASSERT_EQ(strides.size(), 3);
75-
ASSERT_EQ(strides[0], 12); // 3*4
76-
ASSERT_EQ(strides[1], 4); // 4
77-
ASSERT_EQ(strides[2], 1); // contiguous
78-
79-
// Test stride(dim)
80-
ASSERT_EQ(tensor.stride(0), 12);
81-
ASSERT_EQ(tensor.stride(1), 4);
82-
ASSERT_EQ(tensor.stride(2), 1);
83-
84-
// Test numel()
85-
ASSERT_EQ(tensor.numel(), 24); // 2*3*4
86-
87-
// Test dim()/ndimension()
88-
ASSERT_EQ(tensor.dim(), 3);
89-
ASSERT_EQ(tensor.ndimension(), 3);
90-
}
9156
TEST(TensorBaseTest, TypeDeviceAPIs) {
9257
// Test type and device related APIs
9358
at::TensorBase cpu_tensor = at::ones({2, 3}, at::kFloat);

0 commit comments

Comments
 (0)