huanmei9 opened a new pull request, #12315:
URL: https://github.com/apache/tvm/pull/12315
This PR is aim to change floating point multiplication of resize operator to
integer division when `method` is nearest_neighbor and
`coordinate_transformation_mode` is asymmetric.
**Why this change?**
When using `create_prim_func` to convert topi.upsampling into primfunc, tir
analyzer cannot parse complex floating point operations in tir block body. In
the following case, the dimensions of read buffer are inferred as 0 : 128. We
expect to be `tir.reads([x[i0_1, i1_1, i2_1/scale_h, i3_1/scale_w]])`in line
18,so it can perform compute_at schedule on this prim_func.
```python
scale_h = 2
scale_w = 2
x = te.placeholder([1, 128, 128, 128], "int8", "x")
y = topi.nn.upsampling(x, scale_h , scale_w)
func = te.create_prim_func([x, y])
print(func)
```
```Python
primfn(var_x: handle, var_resize: handle) -> ()
attr = {"global_symbol": "main", "tir.noalias": True}
buffers = {x: Buffer(x_1: Pointer(global int8), int8, [1, 128, 128, 128],
[]),
resize: Buffer(resize_1: Pointer(global int8), int8, [1, 128,
256, 256], [])}
buffer_map = {var_x: x, var_resize: resize} {
block([], "root") {
tir.reads([])
tir.writes([])
for (i0: int32, 0, 1) {
for (i1: int32, 0, 128) {
for (i2: int32, 0, 256) {
for (i3: int32, 0, 256) {
block([1, 128, 256, 256], "resize") as [i0_1, i1_1, i2_1, i3_1] {
bind(i0_1, i0)
bind(i1_1, i1)
bind(i2_1, i2)
bind(i3_1, i3)
tir.reads([x[i0_1, i1_1, 0:128, 0:128]])
tir.writes([resize[i0_1, i1_1, i2_1, i3_1]])
resize[i0_1, i1_1, i2_1, i3_1] = cast(int8, cast(float32,
x[i0_1, i1_1, max(min(cast(int32, @tir.floor(((0.5f32*cast(float32, i2_1)) +
1e-05f32), dtype=float32)), 127), 0), max(min(cast(int32,
@tir.floor(((0.5f32*cast(float32, i3_1)) + 1e-05f32), dtype=float32)), 127),
0)]))
}
}
}
}
}
```
**Why can it be changed?**
This PR only modify float multiplication to integer division when `method`
is `nearest_neighbor` and `coordinate_transformation_mode` is `asymmetric`(it's
default setting for topi.upsampling op).
Go further, we expect to convert $\lfloor s * x + \epsilon_1 \rfloor$ to
$x//a$, $s$ is scale, a float number, $x$ is input, $\epsilon_1$ is 1e-5 in
resize op, $a$ is the reciprocal of $s$, an integer.
So, we can represent output as this:
$y = \lfloor s * x + \epsilon_1 \rfloor = \lfloor ( \frac{1}{a} + \epsilon_0
) * x + \epsilon_1 \rfloor = \lfloor \frac{x}{a} + \epsilon_0 * x + \epsilon_1
\rfloor$, let $x = a * m + n$, where $m = x // a, n = x \% a$ , then we can get
$y = m + \lfloor \frac{n}{a} + \epsilon_0 * x + \epsilon_1 \rfloor$. In the
case of upsampling op, $x$ and $a$ are always integers, so inequality
$\frac{n}{a} \le \frac{a-1}{a}$ always holds. If $\epsilon_0 * x + \epsilon_1 <
\frac{1}{a}$, we can get $0 < \frac{n}{a} + \epsilon_0 * x + \epsilon_1 <
1$,then $y = m + \lfloor \frac{n}{a} + \epsilon_0 * x + \epsilon_1 \rfloor = m
= x // a$.
To sum up, when $\epsilon_0 * x + \epsilon_1 < \frac{1}{a}$, we can get $y =
\lfloor s*x + \epsilon_1 \rfloor = x // a$.
In this PR, we assume $\epsilon_0 = \epsilon_1 = 1e-5$ and
`can_multiple2div`to check $\epsilon_0 * x + \epsilon_1 < \frac{1}{a}$.
--
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
To unsubscribe, e-mail: [email protected]
For queries about this service, please contact Infrastructure at:
[email protected]