Skip to content

Commit 0fbbb99

Browse files
committed
[API-Compat] Try adding even more unittests.
1 parent 17f080e commit 0fbbb99

File tree

7 files changed

+279
-126
lines changed

7 files changed

+279
-126
lines changed

paddle/fluid/pir/dialect/operator/interface/infer_symbolic_shape/unary_infer_sym.cc

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -352,7 +352,7 @@ bool MinMaxOpInferSymbolicShape(pir::Operation *op,
352352
std::vector<symbol::DimExpr> out_sym_shape;
353353
if (flatten) {
354354
if (keepdims) {
355-
out_sym_shape.emplace_back(std::int64_t(rank));
355+
out_sym_shape.resize(rank, std::int64_t(1));
356356
} else {
357357
out_sym_shape = {};
358358
}

paddle/phi/infermeta/unary.cc

Lines changed: 64 additions & 84 deletions
Original file line numberDiff line numberDiff line change
@@ -366,90 +366,6 @@ void ArgMinMaxInferMeta(const MetaTensor& x,
366366
}
367367
}
368368

369-
void MinMaxWithIndexInferMeta(const MetaTensor& x,
370-
const Scalar& axis,
371-
bool keepdims,
372-
bool flatten,
373-
MetaTensor* val_out,
374-
MetaTensor* ind_out,
375-
MetaConfig config) {
376-
DataType val_dtype = x.dtype();
377-
378-
if (!config.is_runtime && axis.FromTensor()) {
379-
std::vector<int64_t> vec;
380-
if (flatten) {
381-
if (keepdims) { // NOLINT
382-
vec = std::vector<int64_t>(x.dims().size(), -1);
383-
} else {
384-
vec = {};
385-
}
386-
} else {
387-
if (keepdims) {
388-
vec = std::vector<int64_t>(x.dims().size(), -1);
389-
} else {
390-
vec = std::vector<int64_t>(x.dims().size() - 1, -1);
391-
}
392-
}
393-
val_out->set_dims(common::make_ddim(vec));
394-
val_out->set_dtype(val_dtype);
395-
ind_out->set_dims(common::make_ddim(vec));
396-
ind_out->set_dtype(DataType::INT64);
397-
return;
398-
}
399-
auto int_axis = axis.to<int64_t>();
400-
const auto& x_dims = x.dims();
401-
402-
auto x_rank = x.dims().size();
403-
if (x_rank > 0) {
404-
PADDLE_ENFORCE_GE(int_axis,
405-
-x_rank,
406-
common::errors::InvalidArgument(
407-
"'axis'(%d) must be greater than or equal to"
408-
" -Rank(X)(%d).",
409-
int_axis,
410-
-x_rank));
411-
PADDLE_ENFORCE_LT(
412-
int_axis,
413-
x_rank,
414-
common::errors::InvalidArgument(
415-
"'axis'(%d) must be less than Rank(X)(%d) of Input(X).",
416-
int_axis,
417-
x_rank));
418-
} else {
419-
// 0-dim tensor
420-
PADDLE_ENFORCE_EQ(int_axis == 0 || int_axis == -1,
421-
true,
422-
common::errors::InvalidArgument(
423-
"'axis'(%d) must be 0 or -1 if input tensor is "
424-
"0-dim.",
425-
int_axis));
426-
}
427-
428-
if (int_axis < 0) int_axis += x_rank;
429-
430-
std::vector<int64_t> vec;
431-
if (flatten) {
432-
if (keepdims) { // NOLINT
433-
vec = std::vector<int64_t>(x.dims().size(), 1);
434-
} else {
435-
vec = {};
436-
}
437-
} else {
438-
for (int64_t i = 0; i < int_axis; i++)
439-
vec.emplace_back(x_dims[static_cast<int>(i)]);
440-
if (keepdims) {
441-
vec.emplace_back(static_cast<int64_t>(1));
442-
}
443-
for (int64_t i = int_axis + 1; i < x_rank; i++)
444-
vec.emplace_back(x_dims[static_cast<int>(i)]);
445-
}
446-
447-
val_out->set_dims(common::make_ddim(vec));
448-
val_out->set_dtype(val_dtype);
449-
ind_out->set_dims(common::make_ddim(vec));
450-
ind_out->set_dtype(DataType::INT64);
451-
}
452-
453369
void ArgsortInferMeta(const MetaTensor& input,
454370
int axis,
455371
bool descending,
@@ -3034,6 +2950,70 @@ void ModeInferMeta(const MetaTensor& x,
30342950
indices->set_dtype(DataType::INT64);
30352951
}
30362952

2953+
void MinMaxWithIndexInferMeta(const MetaTensor& x,
2954+
const Scalar& axis,
2955+
bool keepdims,
2956+
bool flatten,
2957+
MetaTensor* val_out,
2958+
MetaTensor* ind_out,
2959+
MetaConfig config) {
2960+
DataType val_dtype = x.dtype();
2961+
2962+
// axis.FromTensor will never be true for this op
2963+
auto int_axis = axis.to<int64_t>();
2964+
const auto& x_dims = x.dims();
2965+
2966+
auto x_rank = x.dims().size();
2967+
if (x_rank > 0) {
2968+
PADDLE_ENFORCE_GE(int_axis,
2969+
-x_rank,
2970+
common::errors::InvalidArgument(
2971+
"'axis'(%d) must be greater than or equal to"
2972+
" -Rank(X)(%d).",
2973+
int_axis,
2974+
-x_rank));
2975+
PADDLE_ENFORCE_LT(
2976+
int_axis,
2977+
x_rank,
2978+
common::errors::InvalidArgument(
2979+
"'axis'(%d) must be less than Rank(X)(%d) of Input(X).",
2980+
int_axis,
2981+
x_rank));
2982+
} else {
2983+
// 0-dim tensor
2984+
PADDLE_ENFORCE_EQ(int_axis == 0 || int_axis == -1,
2985+
true,
2986+
common::errors::InvalidArgument(
2987+
"'axis'(%d) must be 0 or -1 if input tensor is "
2988+
"0-dim.",
2989+
int_axis));
2990+
}
2991+
2992+
if (int_axis < 0) int_axis += x_rank;
2993+
2994+
std::vector<int64_t> vec;
2995+
if (flatten) {
2996+
if (keepdims) { // NOLINT
2997+
vec = std::vector<int64_t>(x.dims().size(), 1);
2998+
} else {
2999+
vec = {};
3000+
}
3001+
} else {
3002+
for (int64_t i = 0; i < int_axis; i++)
3003+
vec.emplace_back(x_dims[static_cast<int>(i)]);
3004+
if (keepdims) {
3005+
vec.emplace_back(static_cast<int64_t>(1));
3006+
}
3007+
for (int64_t i = int_axis + 1; i < x_rank; i++)
3008+
vec.emplace_back(x_dims[static_cast<int>(i)]);
3009+
}
3010+
3011+
val_out->set_dims(common::make_ddim(vec));
3012+
val_out->set_dtype(val_dtype);
3013+
ind_out->set_dims(common::make_ddim(vec));
3014+
ind_out->set_dtype(DataType::INT64);
3015+
}
3016+
30373017
void MultinomialInferMeta(const MetaTensor& x,
30383018
const Scalar& num_samples,
30393019
bool replacement,

paddle/phi/ops/yaml/ops.yaml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3586,7 +3586,7 @@
35863586
func : max_with_index
35873587
data_type : x
35883588
backward : max_with_index_grad
3589-
interfaces : paddle::dialect::InferSymbolicShapeInterface, paddle::dialect::LayoutTransformationInterface
3589+
interfaces : paddle::dialect::InferSymbolicShapeInterface
35903590

35913591
- op : maxout
35923592
args : (Tensor x, int groups, int axis = 1)
@@ -3706,7 +3706,7 @@
37063706
func : min_with_index
37073707
data_type : x
37083708
backward : min_with_index_grad
3709-
interfaces : paddle::dialect::InferSymbolicShapeInterface, paddle::dialect::LayoutTransformationInterface
3709+
interfaces : paddle::dialect::InferSymbolicShapeInterface
37103710

37113711
- op : mish
37123712
args : (Tensor x, float lambda)

test/ir/pir/cinn/symbolic/test_infer_sym_shape_unary_op.py

Lines changed: 0 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -73,45 +73,6 @@ def test_eval_symbolic(self):
7373
return True
7474

7575

76-
class MaxMinWithIndexNet(paddle.nn.Layer):
77-
def __init__(self):
78-
super().__init__()
79-
80-
def forward(self, x):
81-
min_vals, min_inds = paddle.compat.min(x, dim=-1, keepdim=False)
82-
max_vals, max_inds = paddle.compat.max(x, dim=-1, keepdim=True)
83-
return min_vals + max_vals.squeeze(axis=-1), min_inds + max_inds
84-
85-
86-
class MinMaxWithIndexOpInferSymbolicShapeTest(TestBase):
87-
def prepare_data(self):
88-
self.cases = [np.random.rand(3, 4, 5, 6), np.random.rand(257)]
89-
self.expected = [
90-
[
91-
'shape[S0, S1, S2], data[NULL]',
92-
'shape[S0, Broadcast(S0, S1), Broadcast(S1, S2), S2], data[NULL]',
93-
],
94-
['shape[], data[NULL]', 'shape[1], data[NULL]'],
95-
]
96-
97-
def test_eval_symbolic(self):
98-
net = MaxMinWithIndexNet()
99-
100-
for i in range(len(self.cases)):
101-
x = self.cases[i]
102-
x_spec = InputSpec(
103-
shape=[None for index in range(len(x.shape))], dtype='float32'
104-
)
105-
input_spec = [x_spec]
106-
net = apply_to_static(net, False, input_spec)
107-
net.eval()
108-
check_infer_results(
109-
net, input_spec, 'builtin.shadow_output', self.expected[i]
110-
)
111-
112-
return True
113-
114-
11576
class AsComplexAsRealNet(paddle.nn.Layer):
11677
def __init__(self):
11778
super().__init__()
Lines changed: 119 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,119 @@
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+
import sys
16+
import unittest
17+
from os.path import dirname
18+
19+
import numpy as np
20+
from test_infer_sym_shape_utils import (
21+
TestBase,
22+
check_infer_results,
23+
)
24+
25+
import paddle
26+
from paddle.static import InputSpec
27+
28+
sys.path.append(dirname(dirname(__file__)))
29+
from utils import apply_to_static
30+
31+
# NOTE(SigureMo): Disable the CSE optimization to avoid op number change.
32+
paddle.set_flags({"FLAGS_enable_cse_in_dy2st": False})
33+
34+
35+
class MaxMinWithIndexNet(paddle.nn.Layer):
36+
def __init__(self):
37+
super().__init__()
38+
39+
def forward(self, x):
40+
min_vals, min_inds = paddle.compat.min(x, dim=-1, keepdim=False)
41+
max_vals, max_inds = paddle.compat.max(x, dim=-1, keepdim=True)
42+
return min_vals + max_vals.squeeze(axis=-1), min_inds + max_inds
43+
44+
45+
class MinMaxWithIndexOpInferSymbolicShapeTest(TestBase):
46+
def prepare_data(self):
47+
self.cases = [np.random.rand(3, 4, 5, 6), np.random.rand(257)]
48+
self.expected = [
49+
[
50+
'shape[S0, S1, S2], data[NULL]',
51+
'shape[S0, Broadcast(S0, S1), Broadcast(S1, S2), S2], data[NULL]',
52+
],
53+
['shape[], data[NULL]', 'shape[1], data[NULL]'],
54+
]
55+
56+
def test_eval_symbolic(self):
57+
net = MaxMinWithIndexNet()
58+
59+
for i in range(len(self.cases)):
60+
x = self.cases[i]
61+
x_spec = InputSpec(
62+
shape=[None for index in range(len(x.shape))], dtype='float32'
63+
)
64+
input_spec = [x_spec]
65+
net = apply_to_static(net, False, input_spec)
66+
net.eval()
67+
check_infer_results(
68+
net, input_spec, 'builtin.shadow_output', self.expected[i]
69+
)
70+
71+
return True
72+
73+
74+
class MinMaxWithIndexRawNet(paddle.nn.Layer):
75+
def __init__(self):
76+
super().__init__()
77+
78+
def forward(self, x):
79+
x = x * 2 + 1
80+
min_vals, min_inds = paddle._C_ops.min_with_index(x, 1, False, True)
81+
max_vals, max_inds = paddle._C_ops.max_with_index(x, 2, True, True)
82+
return min_vals + max_vals.squeeze(), min_inds * max_inds
83+
84+
85+
class MinMaxWithIndexOpRawInferShapeTest(TestBase):
86+
def prepare_data(self):
87+
self.cases = [np.random.rand(4, 5, 6), np.random.rand(3, 7, 1, 2)]
88+
self.expected = [
89+
[
90+
'shape[], data[NULL]',
91+
'shape[1, 1, 1], data[NULL]',
92+
],
93+
['shape[], data[NULL]', 'shape[1, 1, 1, 1], data[NULL]'],
94+
]
95+
96+
@unittest.skipIf(
97+
not paddle.core.is_compiled_with_cuda(),
98+
"core is not compiled with CUDA, skipping",
99+
)
100+
def test_eval_symbolic(self):
101+
net = MinMaxWithIndexRawNet()
102+
103+
for i in range(len(self.cases)):
104+
x = self.cases[i]
105+
x_spec = InputSpec(
106+
shape=[None for index in range(len(x.shape))], dtype='float32'
107+
)
108+
input_spec = [x_spec]
109+
net = apply_to_static(net, False, input_spec)
110+
net.eval()
111+
check_infer_results(
112+
net, input_spec, 'builtin.shadow_output', self.expected[i]
113+
)
114+
115+
return True
116+
117+
118+
if __name__ == "__main__":
119+
unittest.main()

0 commit comments

Comments
 (0)