Skip to content

Commit 47f085e

Browse files
committed
[Backend Tester] Add upsample tests
ghstack-source-id: 20258de ghstack-comment-id: 3116317107 Pull-Request: #12856
1 parent 13f6155 commit 47f085e

File tree

2 files changed

+410
-0
lines changed

2 files changed

+410
-0
lines changed
Lines changed: 273 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,273 @@
1+
# Copyright (c) Meta Platforms, Inc. and affiliates.
2+
# All rights reserved.
3+
#
4+
# This source code is licensed under the BSD-style license found in the
5+
# LICENSE file in the root directory of this source tree.
6+
7+
# pyre-unsafe
8+
9+
from typing import Optional, Tuple, Union
10+
11+
import torch
12+
from executorch.backends.test.suite.flow import TestFlow
13+
14+
from executorch.backends.test.suite.operators import (
15+
dtype_test,
16+
operator_test,
17+
OperatorTest,
18+
)
19+
20+
21+
class ModelWithSize(torch.nn.Module):
22+
def __init__(
23+
self,
24+
size: Optional[Tuple[int, int]] = None,
25+
align_corners: Optional[bool] = None,
26+
):
27+
super().__init__()
28+
self.size = size
29+
self.align_corners = align_corners
30+
31+
def forward(self, x):
32+
return torch.nn.functional.interpolate(
33+
x, size=self.size, mode="bilinear", align_corners=self.align_corners
34+
)
35+
36+
37+
class ModelWithScale(torch.nn.Module):
38+
def __init__(
39+
self,
40+
scale_factor: Union[float, Tuple[float, float]] = 2.0,
41+
align_corners: Optional[bool] = None,
42+
):
43+
super().__init__()
44+
self.scale_factor = scale_factor
45+
self.align_corners = align_corners
46+
47+
def forward(self, x):
48+
return torch.nn.functional.interpolate(
49+
x,
50+
scale_factor=self.scale_factor,
51+
mode="bilinear",
52+
align_corners=self.align_corners,
53+
)
54+
55+
56+
@operator_test
57+
class TestUpsampleBilinear2d(OperatorTest):
58+
@dtype_test
59+
def test_upsample_bilinear2d_dtype(self, flow: TestFlow, dtype) -> None:
60+
# Input shape: (batch_size, channels, height, width)
61+
model = ModelWithSize(size=(10, 10), align_corners=False).to(dtype)
62+
self._test_op(model, (torch.rand(2, 3, 5, 5).to(dtype),), flow)
63+
64+
def test_upsample_bilinear2d_sizes(self, flow: TestFlow) -> None:
65+
# Test with different input and output sizes
66+
67+
# Small input, larger output
68+
self._test_op(
69+
ModelWithSize(size=(8, 8), align_corners=False),
70+
(torch.randn(1, 2, 4, 4),),
71+
flow,
72+
)
73+
self._test_op(
74+
ModelWithSize(size=(8, 8), align_corners=True),
75+
(torch.randn(1, 2, 4, 4),),
76+
flow,
77+
)
78+
79+
# Larger input, even larger output
80+
self._test_op(
81+
ModelWithSize(size=(16, 16), align_corners=False),
82+
(torch.randn(1, 2, 8, 8),),
83+
flow,
84+
)
85+
self._test_op(
86+
ModelWithSize(size=(16, 16), align_corners=True),
87+
(torch.randn(1, 2, 8, 8),),
88+
flow,
89+
)
90+
91+
# Different height and width
92+
self._test_op(
93+
ModelWithSize(size=(16, 8), align_corners=False),
94+
(torch.randn(1, 2, 8, 4),),
95+
flow,
96+
)
97+
self._test_op(
98+
ModelWithSize(size=(16, 8), align_corners=True),
99+
(torch.randn(1, 2, 8, 4),),
100+
flow,
101+
)
102+
103+
# Asymmetric upsampling
104+
self._test_op(
105+
ModelWithSize(size=(20, 10), align_corners=False),
106+
(torch.randn(1, 2, 5, 5),),
107+
flow,
108+
)
109+
self._test_op(
110+
ModelWithSize(size=(20, 10), align_corners=True),
111+
(torch.randn(1, 2, 5, 5),),
112+
flow,
113+
)
114+
115+
def test_upsample_bilinear2d_scale_factors(self, flow: TestFlow) -> None:
116+
# Test with different scale factors
117+
118+
# Scale by 2
119+
self._test_op(
120+
ModelWithScale(scale_factor=2.0, align_corners=False),
121+
(torch.randn(1, 2, 5, 5),),
122+
flow,
123+
)
124+
self._test_op(
125+
ModelWithScale(scale_factor=2.0, align_corners=True),
126+
(torch.randn(1, 2, 5, 5),),
127+
flow,
128+
)
129+
130+
# Scale by 3
131+
self._test_op(
132+
ModelWithScale(scale_factor=3.0, align_corners=False),
133+
(torch.randn(1, 2, 5, 5),),
134+
flow,
135+
)
136+
self._test_op(
137+
ModelWithScale(scale_factor=3.0, align_corners=True),
138+
(torch.randn(1, 2, 5, 5),),
139+
flow,
140+
)
141+
142+
# Scale by 1.5
143+
self._test_op(
144+
ModelWithScale(scale_factor=1.5, align_corners=False),
145+
(torch.randn(1, 2, 6, 6),),
146+
flow,
147+
)
148+
self._test_op(
149+
ModelWithScale(scale_factor=1.5, align_corners=True),
150+
(torch.randn(1, 2, 6, 6),),
151+
flow,
152+
)
153+
154+
# Different scales for height and width
155+
self._test_op(
156+
ModelWithScale(scale_factor=(2.0, 1.5), align_corners=False),
157+
(torch.randn(1, 2, 5, 6),),
158+
flow,
159+
generate_random_test_inputs=False,
160+
)
161+
self._test_op(
162+
ModelWithScale(scale_factor=(2.0, 1.5), align_corners=True),
163+
(torch.randn(1, 2, 5, 6),),
164+
flow,
165+
generate_random_test_inputs=False,
166+
)
167+
168+
def test_upsample_bilinear2d_batch_sizes(self, flow: TestFlow) -> None:
169+
# Test with different batch sizes
170+
self._test_op(
171+
ModelWithSize(size=(10, 10), align_corners=False),
172+
(torch.randn(1, 3, 5, 5),),
173+
flow,
174+
)
175+
self._test_op(
176+
ModelWithSize(size=(10, 10), align_corners=False),
177+
(torch.randn(4, 3, 5, 5),),
178+
flow,
179+
)
180+
self._test_op(
181+
ModelWithSize(size=(10, 10), align_corners=False),
182+
(torch.randn(8, 3, 5, 5),),
183+
flow,
184+
)
185+
186+
def test_upsample_bilinear2d_channels(self, flow: TestFlow) -> None:
187+
# Test with different numbers of channels
188+
self._test_op(
189+
ModelWithSize(size=(10, 10), align_corners=False),
190+
(torch.randn(2, 1, 5, 5),),
191+
flow,
192+
) # Grayscale
193+
self._test_op(
194+
ModelWithSize(size=(10, 10), align_corners=False),
195+
(torch.randn(2, 3, 5, 5),),
196+
flow,
197+
) # RGB
198+
self._test_op(
199+
ModelWithSize(size=(10, 10), align_corners=False),
200+
(torch.randn(2, 4, 5, 5),),
201+
flow,
202+
) # RGBA
203+
self._test_op(
204+
ModelWithSize(size=(10, 10), align_corners=False),
205+
(torch.randn(2, 16, 5, 5),),
206+
flow,
207+
) # Multi-channel
208+
209+
def test_upsample_bilinear2d_same_size(self, flow: TestFlow) -> None:
210+
# Test with output size same as input size (should be identity)
211+
self._test_op(
212+
ModelWithSize(size=(5, 5), align_corners=False),
213+
(torch.randn(2, 3, 5, 5),),
214+
flow,
215+
generate_random_test_inputs=False,
216+
)
217+
self._test_op(
218+
ModelWithSize(size=(5, 5), align_corners=True),
219+
(torch.randn(2, 3, 5, 5),),
220+
flow,
221+
generate_random_test_inputs=False,
222+
)
223+
self._test_op(
224+
ModelWithScale(scale_factor=1.0, align_corners=False),
225+
(torch.randn(2, 3, 5, 5),),
226+
flow,
227+
generate_random_test_inputs=False,
228+
)
229+
self._test_op(
230+
ModelWithScale(scale_factor=1.0, align_corners=True),
231+
(torch.randn(2, 3, 5, 5),),
232+
flow,
233+
generate_random_test_inputs=False,
234+
)
235+
236+
def test_upsample_bilinear2d_downsampling(self, flow: TestFlow) -> None:
237+
# Test downsampling
238+
self._test_op(
239+
ModelWithSize(size=(4, 4), align_corners=False),
240+
(torch.randn(2, 3, 8, 8),),
241+
flow,
242+
)
243+
self._test_op(
244+
ModelWithSize(size=(4, 4), align_corners=True),
245+
(torch.randn(2, 3, 8, 8),),
246+
flow,
247+
)
248+
self._test_op(
249+
ModelWithScale(scale_factor=0.5, align_corners=False),
250+
(torch.randn(2, 3, 8, 8),),
251+
flow,
252+
generate_random_test_inputs=False,
253+
)
254+
self._test_op(
255+
ModelWithScale(scale_factor=0.5, align_corners=True),
256+
(torch.randn(2, 3, 8, 8),),
257+
flow,
258+
generate_random_test_inputs=False,
259+
)
260+
261+
# Test with non-integer downsampling factor
262+
self._test_op(
263+
ModelWithScale(scale_factor=0.75, align_corners=False),
264+
(torch.randn(2, 3, 8, 8),),
265+
flow,
266+
generate_random_test_inputs=False,
267+
)
268+
self._test_op(
269+
ModelWithScale(scale_factor=0.75, align_corners=True),
270+
(torch.randn(2, 3, 8, 8),),
271+
flow,
272+
generate_random_test_inputs=False,
273+
)

0 commit comments

Comments
 (0)