chore: import upstream snapshot with attribution
Lint / lint (push) Waiting to run
CI / MacOS (push) Waiting to run
CI / Windows (push) Waiting to run

This commit is contained in:
wehub-resource-sync
2026-07-13 13:36:25 +08:00
commit 26446540fa
3151 changed files with 974126 additions and 0 deletions
@@ -0,0 +1,948 @@
# Licensed to the Apache Software Foundation (ASF) under one
# or more contributor license agreements. See the NOTICE file
# distributed with this work for additional information
# regarding copyright ownership. The ASF licenses this file
# to you under the Apache License, Version 2.0 (the
# "License"); you may not use this file except in compliance
# with the License. You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing,
# software distributed under the License is distributed on an
# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
# KIND, either express or implied. See the License for the
# specific language governing permissions and limitations
# under the License.
# ruff: noqa: F401, F811, RUF005
from collections.abc import Callable
from typing import Union
import numpy as np
import pytest
import tvm_ffi
import tvm
import tvm.testing
from tvm import relax
from tvm.ir import Call
from tvm.ir.op import Op
from tvm.relax.transform import LegalizeOps
from tvm.relax.type import TensorType, TupleType
from tvm.testing.utils import check_numerical_grads
def relax_check_gradients(
op_func: Callable,
inputs_numpy: list[np.array],
target: str | tvm.target.Target,
dev: tvm.runtime.Device,
tuple_input: bool = False,
ignore_grads: list[int] = [],
**kwargs, # attr for operators
):
"""Generate the forward and the gradient module. Then run them and check numeric gradients.
Parameters
----------
op_func : Callable
The forward operator function. Should be a function in package relax.op.
inputs_numpy : List[np.array]
The np array inputs for op_func. inputs_numpy will be transformed into TVM Tensor inside
this function.
If op_func takes a tuple of tensors as input, you can set tuple_input as True, and pass the
tuple input (or list) as inputs_numpy. See test_concat().
target : Union[str, tvm.target.Target]
The building target.
dev : tvm.runtime.Device
The device to deploy the module.
tuple_input : bool
Whether the operator accepts a tuple as input. If true, operator will accept exactly one
tuple of tensors as input; otherwise, operator accept one or more tensors as input. See
test_concat(). Default: False.
ignore_grads: List[int]
Specifies which input we do not need to find gradient.
Sometimes the input is not differentiable, such as shape, boolean values, positions, etc.
We can specify the index of these inputs to check the gradient of them is no_grad, and
prevent computing numeric gradient.
kwargs : Any
The keyword arguments for the op_func. Will be passed to op_func directly.
"""
func_name = "main"
# Helper functions
def _numpy_to_ty(data):
if isinstance(data, list):
return relax.TupleType([_numpy_to_ty(d) for d in data])
return relax.TensorType(data.shape, str(data.dtype))
def _numpy_to_tvm(data):
if isinstance(data, list):
return [_numpy_to_tvm(d) for d in data]
return tvm.runtime.tensor(data)
def _tvm_to_numpy(data, ignore_idx=[]):
if isinstance(data, tvm_ffi.Array):
return [_tvm_to_numpy(d) for i, d in enumerate(data) if i not in ignore_idx]
if isinstance(data, tvm.runtime.Tensor):
return data.numpy()
return data
def _gen_weights(out_ty):
if isinstance(out_ty, TupleType):
return [_gen_weights(ty) for ty in out_ty.fields]
else:
assert isinstance(out_ty, TensorType)
return np.random.uniform(size=[int(i) for i in out_ty.shape]).astype(out_ty.dtype)
def _is_call_no_grad(expr):
return isinstance(expr, Call) and expr.op == Op.get("relax.grad.no_grad")
# Generate parameter relax Vars
param_vars = [
relax.Var("x_" + str(i), _numpy_to_ty(data)) for i, data in enumerate(inputs_numpy)
]
# Generate the forward call
if tuple_input:
t = relax.Tuple(param_vars)
call = op_func(t, **kwargs)
else:
call = op_func(*param_vars, **kwargs)
# Forward mod
forward_bb = relax.BlockBuilder()
with forward_bb.function(func_name, param_vars):
with forward_bb.dataflow():
out = forward_bb.emit_output(call)
forward_bb.emit_func_output(out)
forward_mod = forward_bb.get()
forward_ex = tvm.compile(forward_mod, target)
forward_vm = relax.VirtualMachine(forward_ex, dev)
# Generate weights
# In forward process, weights represent the weight of every element of the result of the
# forward call. The weighted result will be sum(weight * result).
# If the result is a tuple, weights will be a list, and the weighted result will be
# sum(i * j for i, j in zip(weights, result))
# In the gradient process, weights is the output gradient, i.e. the gradient w.r.t. the result.
out_ty = forward_mod[func_name].body.body.ty
weights = _gen_weights(out_ty)
# The inputs of the forward function are inputs_filtered below.
def forward(*inputs):
inputs_iter = iter(inputs)
inputs_tvm = [
_numpy_to_tvm(next(inputs_iter))
if i not in ignore_grads
else _numpy_to_tvm(inputs_numpy[i])
for i in range(len(inputs_numpy))
]
result = forward_vm[func_name](*inputs_tvm)
result_numpy = _tvm_to_numpy(result)
if isinstance(result_numpy, list):
assert isinstance(weights, list)
assert len(weights) == len(result_numpy)
ret = 0
for i, weight in enumerate(weights):
ret += np.sum(weight * result_numpy[i])
return ret
return np.sum(weights * result_numpy)
# The gradient function
assert isinstance(call.op, Op)
op_grad_func = call.op.get_attr("FPrimalGradient")
# The parameter Var for gradient
grad_var = relax.Var("grad", _numpy_to_ty(weights))
# Gradient mod
grad_bb = relax.BlockBuilder()
with grad_bb.function(func_name, param_vars + [grad_var]):
with grad_bb.dataflow():
orig = grad_bb.emit(call)
# op_grad_func returns a list of Exprs representing the gradients
grad_call = op_grad_func(orig, call, grad_var, grad_bb)
# Check ignore_grads
for i, grad in enumerate(grad_call):
if i in ignore_grads:
assert _is_call_no_grad(grad), f"The {i}-th gradient should be no_grad"
else:
assert not _is_call_no_grad(grad), f"The {i}-th gradient should not be no_grad"
if tuple_input:
# If the input is a tuple, the gradient is also a tuple.
# The gradient tuple is the first (the only) element of grad_call.
out = grad_bb.emit_output(grad_call[0])
else:
# We need to wrap the list into a relax.Tuple so as to emit it
out = grad_bb.emit_output(relax.Tuple(grad_call))
grad_bb.emit_func_output(out)
grad_mod = grad_bb.get()
grad_ex = tvm.compile(grad_mod, target)
grad_vm = relax.VirtualMachine(grad_ex, dev)
# tvm.runtime.Tensor inputs
inputs_tvm = [_numpy_to_tvm(i) for i in inputs_numpy]
weights_tvm = _numpy_to_tvm(weights)
result_filtered = _tvm_to_numpy(grad_vm[func_name](*inputs_tvm, weights_tvm), ignore_grads)
# Inputs contained in ignore_grads are removed
inputs_filtered = [inputs_numpy[i] for i in range(len(inputs_numpy)) if i not in ignore_grads]
check_numerical_grads(forward, inputs_filtered, result_filtered)
##################### Unary #####################
@pytest.mark.parametrize(
"unary_op_func,can_be_neg",
[
(relax.op.abs, True),
(relax.op.cos, True),
(relax.op.exp, True),
(relax.op.log, False),
(relax.op.negative, True),
(relax.op.sigmoid, True),
(relax.op.sin, True),
(relax.op.sqrt, False),
(relax.op.tanh, True),
],
)
@pytest.mark.skipif(not tvm.testing.device_enabled("llvm"), reason="llvm not enabled")
def test_unary(unary_op_func, can_be_neg):
target = "llvm"
dev = tvm.device(target)
(low, high) = (-1, 1) if can_be_neg else (0.1, 1)
data_numpy = np.random.uniform(low, high, (3, 3)).astype(np.float32)
relax_check_gradients(unary_op_func, [data_numpy], target, dev)
##################### Binary #####################
@pytest.mark.parametrize(
"binary_arith_op_func",
[
relax.op.add,
relax.op.subtract,
relax.op.multiply,
relax.op.divide,
relax.op.power,
],
)
@pytest.mark.skipif(not tvm.testing.device_enabled("llvm"), reason="llvm not enabled")
def test_binary_arith(binary_arith_op_func):
target = "llvm"
dev = tvm.device(target)
data1_numpy = np.random.uniform(1, 2, (3, 3)).astype(np.float32)
data2_numpy = np.random.uniform(1, 2, (3, 3)).astype(np.float32)
relax_check_gradients(binary_arith_op_func, [data1_numpy, data2_numpy], target, dev)
@pytest.mark.parametrize("binary_minmax_op_func", [relax.op.maximum, relax.op.minimum])
@pytest.mark.skipif(not tvm.testing.device_enabled("llvm"), reason="llvm not enabled")
def test_binary_minmax(binary_minmax_op_func):
target = "llvm"
dev = tvm.device(target)
# Checking numerical gradient of min and max requires data1_numpy[i] != data2_numpy[i]
# for all possible i.
# If data1_numpy[i] == data2_numpy[i], the operator is not differentiable w.r.t. place i
data1_numpy = np.random.uniform(1, 1.1, (3, 3)).astype(np.float32)
delta = np.random.uniform(1, 1.1, (3, 3)).astype(np.float32)
sign = np.random.randint(0, 2, (3, 3)).astype(np.float32) * 2 - 1
data2_numpy = data1_numpy + delta * sign
relax_check_gradients(binary_minmax_op_func, [data1_numpy, data2_numpy], target, dev)
@pytest.mark.parametrize(
"binary_cmp_op_func",
[
relax.op.equal,
relax.op.greater,
relax.op.greater_equal,
relax.op.less,
relax.op.less_equal,
relax.op.not_equal,
],
)
@pytest.mark.skipif(not tvm.testing.device_enabled("llvm"), reason="llvm not enabled")
def test_binary_cmp(binary_cmp_op_func):
target = "llvm"
dev = tvm.device(target)
data1_numpy = np.random.uniform(1, 2, (3, 3)).astype(np.float32)
data2_numpy = np.random.uniform(1, 2, (3, 3)).astype(np.float32)
relax_check_gradients(
binary_cmp_op_func, [data1_numpy, data2_numpy], target, dev, ignore_grads=[0, 1]
)
##################### Create #####################
@pytest.mark.parametrize("like_op_func", [relax.op.zeros_like, relax.op.ones_like])
@pytest.mark.skipif(not tvm.testing.device_enabled("llvm"), reason="llvm not enabled")
def test_ones_zeros_like(like_op_func):
target = "llvm"
dev = tvm.device(target)
data_numpy = np.random.uniform(-1, 1, (3, 3)).astype(np.float32)
relax_check_gradients(like_op_func, [data_numpy], target, dev, ignore_grads=[0])
@pytest.mark.skipif(not tvm.testing.device_enabled("llvm"), reason="llvm not enabled")
def test_full_like():
target = "llvm"
dev = tvm.device(target)
data_numpy = np.random.uniform(-1, 1, (3, 3)).astype(np.float32)
fill_value = np.random.uniform(-1, 1, ()).astype(np.float32)
relax_check_gradients(
relax.op.full_like, [data_numpy, fill_value], target, dev, ignore_grads=[0, 1]
)
@pytest.mark.parametrize("create_op_func", [relax.op.zeros, relax.op.ones])
@pytest.mark.skipif(not tvm.testing.device_enabled("llvm"), reason="llvm not enabled")
def test_ones_zeros(create_op_func):
target = "llvm"
dev = tvm.device(target)
relax_check_gradients(
create_op_func, [], target, dev, ignore_grads=[0], shape=(3, 3), dtype="float32"
)
@pytest.mark.skipif(not tvm.testing.device_enabled("llvm"), reason="llvm not enabled")
def test_triu():
target = "llvm"
dev = tvm.device(target)
data_numpy = np.random.uniform(-1, 1, (3, 3)).astype(np.float32)
relax_check_gradients(relax.op.triu, [data_numpy], target, dev, k=0)
##################### Statistical #####################
@pytest.mark.skipif(not tvm.testing.device_enabled("llvm"), reason="llvm not enabled")
def test_sum():
target = "llvm"
dev = tvm.device(target)
data1_numpy = np.random.uniform(0, 16, (3, 3)).astype(np.float32)
relax_check_gradients(relax.op.sum, [data1_numpy], target, dev)
@pytest.mark.skipif(not tvm.testing.device_enabled("llvm"), reason="llvm not enabled")
def test_sum_with_axis():
target = "llvm"
dev = tvm.device(target)
data1_numpy = np.random.uniform(0, 16, (2, 3, 4, 5)).astype(np.float32)
relax_check_gradients(relax.op.sum, [data1_numpy], target, dev, axis=[1, 3])
@pytest.mark.skipif(not tvm.testing.device_enabled("llvm"), reason="llvm not enabled")
def test_sum_keepdims():
target = "llvm"
dev = tvm.device(target)
data1_numpy = np.random.uniform(0, 16, (3, 3)).astype(np.float32)
relax_check_gradients(relax.op.sum, [data1_numpy], target, dev, keepdims=True, axis=1)
@pytest.mark.skipif(not tvm.testing.device_enabled("llvm"), reason="llvm not enabled")
def test_mean():
target = "llvm"
dev = tvm.device(target)
data1_numpy = np.random.uniform(0, 16, (3, 3)).astype(np.float32)
relax_check_gradients(relax.op.mean, [data1_numpy], target, dev)
@pytest.mark.skipif(not tvm.testing.device_enabled("llvm"), reason="llvm not enabled")
def test_mean_with_axis():
target = "llvm"
dev = tvm.device(target)
data1_numpy = np.random.uniform(0, 16, (2, 3, 4, 5)).astype(np.float32)
relax_check_gradients(relax.op.mean, [data1_numpy], target, dev, axis=[1, 3])
@pytest.mark.skipif(not tvm.testing.device_enabled("llvm"), reason="llvm not enabled")
def test_mean_keepdims():
target = "llvm"
dev = tvm.device(target)
data1_numpy = np.random.uniform(0, 16, (3, 3)).astype(np.float32)
relax_check_gradients(relax.op.mean, [data1_numpy], target, dev, keepdims=True, axis=1)
@pytest.mark.skipif(not tvm.testing.device_enabled("llvm"), reason="llvm not enabled")
def test_variance():
target = "llvm"
dev = tvm.device(target)
data1_numpy = np.random.uniform(0, 16, (3, 3)).astype(np.float32)
relax_check_gradients(relax.op.variance, [data1_numpy], target, dev)
@pytest.mark.skipif(not tvm.testing.device_enabled("llvm"), reason="llvm not enabled")
def test_variance_with_axis():
target = "llvm"
dev = tvm.device(target)
data1_numpy = np.random.uniform(0, 16, (2, 3, 4, 5)).astype(np.float32)
relax_check_gradients(relax.op.variance, [data1_numpy], target, dev, axis=[1, 3])
@pytest.mark.skipif(not tvm.testing.device_enabled("llvm"), reason="llvm not enabled")
def test_variance_keepdims():
target = "llvm"
dev = tvm.device(target)
data1_numpy = np.random.uniform(0, 16, (3, 3)).astype(np.float32)
relax_check_gradients(relax.op.variance, [data1_numpy], target, dev, keepdims=True, axis=1)
##################### Manipulate #####################
@pytest.mark.skipif(not tvm.testing.device_enabled("llvm"), reason="llvm not enabled")
def test_reshape():
target = "llvm"
dev = tvm.device(target)
data_numpy = np.random.uniform(0, 16, (2, 3, 5)).astype(np.float32)
relax_check_gradients(
relax.op.reshape, [data_numpy], target, dev, ignore_grads=[1], shape=(5, 6)
)
@pytest.mark.skipif(not tvm.testing.device_enabled("llvm"), reason="llvm not enabled")
def test_reshape_infer_dim():
target = "llvm"
dev = tvm.device(target)
data_numpy = np.random.uniform(0, 16, (2, 3, 5)).astype(np.float32)
relax_check_gradients(
relax.op.reshape, [data_numpy], target, dev, ignore_grads=[1], shape=(5, 2, 1, -1)
)
@pytest.mark.skipif(not tvm.testing.device_enabled("llvm"), reason="llvm not enabled")
def test_permute_dims():
target = "llvm"
dev = tvm.device(target)
data_numpy = np.random.uniform(0, 16, (2, 3, 4, 5)).astype(np.float32)
relax_check_gradients(relax.op.permute_dims, [data_numpy], target, dev)
@pytest.mark.skipif(not tvm.testing.device_enabled("llvm"), reason="llvm not enabled")
def test_permute_dims_with_axes():
target = "llvm"
dev = tvm.device(target)
data_numpy = np.random.uniform(0, 16, (2, 3, 4, 5)).astype(np.float32)
relax_check_gradients(
relax.op.permute_dims,
[data_numpy],
target,
dev,
axes=(0, 3, 1, 2),
)
@pytest.mark.skipif(not tvm.testing.device_enabled("llvm"), reason="llvm not enabled")
def test_concat():
target = "llvm"
dev = tvm.device(target)
data_numpy1 = np.random.uniform(1, 16, (3, 3)).astype(np.float32)
data_numpy2 = np.random.uniform(1, 16, (3, 4)).astype(np.float32)
data_numpy3 = np.random.uniform(1, 16, (3, 5)).astype(np.float32)
relax_check_gradients(
relax.op.concat,
[data_numpy1, data_numpy2, data_numpy3],
target,
dev,
tuple_input=True,
axis=1,
)
@pytest.mark.skipif(not tvm.testing.device_enabled("llvm"), reason="llvm not enabled")
def test_split_indices():
target = "llvm"
dev = tvm.device(target)
data_numpy = np.random.uniform(1, 16, (3, 12)).astype(np.float32)
relax_check_gradients(
relax.op.split,
[data_numpy],
target,
dev,
indices_or_sections=[3, 7],
axis=1,
)
@pytest.mark.skipif(not tvm.testing.device_enabled("llvm"), reason="llvm not enabled")
def test_split_section():
target = "llvm"
dev = tvm.device(target)
data_numpy = np.random.uniform(1, 16, (3, 12)).astype(np.float32)
relax_check_gradients(
relax.op.split,
[data_numpy],
target,
dev,
indices_or_sections=3,
axis=1,
)
@pytest.mark.skipif(not tvm.testing.device_enabled("llvm"), reason="llvm not enabled")
def test_reshape():
target = "llvm"
dev = tvm.device(target)
data_numpy = np.random.uniform(1, 16, (3, 4)).astype(np.float32)
relax_check_gradients(
relax.op.reshape,
[data_numpy],
target,
dev,
shape=(3, 2, 2),
ignore_grads=[1],
)
@pytest.mark.skipif(not tvm.testing.device_enabled("llvm"), reason="llvm not enabled")
def test_cumsum():
target = "llvm"
dev = tvm.device(target)
data_numpy1 = np.random.uniform(1, 16, (3, 3)).astype(np.float32)
relax_check_gradients(
relax.op.cumsum,
[data_numpy1],
target,
dev,
axis=1,
)
@pytest.mark.skipif(not tvm.testing.device_enabled("llvm"), reason="llvm not enabled")
def test_cumsum_no_axis():
target = "llvm"
dev = tvm.device(target)
data_numpy1 = np.random.uniform(1, 16, (3, 3)).astype(np.float32)
relax_check_gradients(
relax.op.cumsum,
[data_numpy1],
target,
dev,
)
@pytest.mark.skipif(not tvm.testing.device_enabled("llvm"), reason="llvm not enabled")
def test_expand_dims():
target = "llvm"
dev = tvm.device(target)
data_numpy = np.random.uniform(1, 16, (3, 12)).astype(np.float32)
relax_check_gradients(relax.op.expand_dims, [data_numpy], target, dev, axis=1)
@pytest.mark.skipif(not tvm.testing.device_enabled("llvm"), reason="llvm not enabled")
def test_expand_dims_list():
target = "llvm"
dev = tvm.device(target)
data_numpy = np.random.uniform(1, 16, (3, 12)).astype(np.float32)
relax_check_gradients(relax.op.expand_dims, [data_numpy], target, dev, axis=(0, 2, 3))
@pytest.mark.skipif(not tvm.testing.device_enabled("llvm"), reason="llvm not enabled")
def test_broadcast_to():
target = "llvm"
dev = tvm.device(target)
data_numpy = np.random.uniform(1, 16, (3, 4)).astype(np.float32)
relax_check_gradients(
relax.op.broadcast_to,
[data_numpy],
target,
dev,
shape=(2, 3, 4),
ignore_grads=[1],
)
##################### Index #####################
@pytest.mark.skipif(not tvm.testing.device_enabled("llvm"), reason="llvm not enabled")
def test_take():
target = "llvm"
dev = tvm.device(target)
data_numpy = np.random.uniform(0, 16, size=(2, 3, 4)).astype(np.float32)
indices = np.array([0, 1])
relax_check_gradients(
relax.op.take,
[data_numpy, indices],
target,
dev,
axis=1,
ignore_grads=[1],
)
@pytest.mark.skipif(not tvm.testing.device_enabled("llvm"), reason="llvm not enabled")
def test_take_no_axis():
target = "llvm"
dev = tvm.device(target)
data_numpy = np.random.uniform(0, 16, size=(5,)).astype(np.float32)
indices = np.array([1, 3])
relax_check_gradients(
relax.op.take,
[data_numpy, indices],
target,
dev,
ignore_grads=[1],
)
##################### Search #####################
@pytest.mark.skipif(not tvm.testing.device_enabled("llvm"), reason="llvm not enabled")
def test_where():
target = "llvm"
dev = tvm.device(target)
data1_numpy = np.random.uniform(0, 1, size=(3, 3)) > 0.5
data2_numpy = np.random.uniform(0, 16, size=(3, 3)).astype(np.float32)
data3_numpy = np.random.uniform(0, 16, size=(3, 3)).astype(np.float32)
relax_check_gradients(
relax.op.where,
[data1_numpy, data2_numpy, data3_numpy],
target,
dev,
ignore_grads=[0],
)
##################### Linear Algebra #####################
@pytest.mark.skipif(not tvm.testing.device_enabled("llvm"), reason="llvm not enabled")
def test_matmul_2_2():
target = "llvm"
dev = tvm.device(target)
data1_numpy = np.random.uniform(0, 16, (2, 3)).astype(np.float32)
data2_numpy = np.random.uniform(0, 16, (3, 4)).astype(np.float32)
relax_check_gradients(relax.op.matmul, [data1_numpy, data2_numpy], target, dev)
@pytest.mark.skipif(not tvm.testing.device_enabled("llvm"), reason="llvm not enabled")
def test_matmul_1_1():
target = "llvm"
dev = tvm.device(target)
data1_numpy = np.random.uniform(0, 16, (4,)).astype(np.float32)
data2_numpy = np.random.uniform(0, 16, (4,)).astype(np.float32)
relax_check_gradients(relax.op.matmul, [data1_numpy, data2_numpy], target, dev)
@pytest.mark.skipif(not tvm.testing.device_enabled("llvm"), reason="llvm not enabled")
def test_matmul_1_4():
target = "llvm"
dev = tvm.device(target)
data1_numpy = np.random.uniform(0, 16, (4,)).astype(np.float32)
data2_numpy = np.random.uniform(0, 16, (2, 3, 4, 5)).astype(np.float32)
relax_check_gradients(relax.op.matmul, [data1_numpy, data2_numpy], target, dev)
@pytest.mark.skipif(not tvm.testing.device_enabled("llvm"), reason="llvm not enabled")
def test_matmul_4_1():
target = "llvm"
dev = tvm.device(target)
data1_numpy = np.random.uniform(0, 16, (2, 3, 4, 5)).astype(np.float32)
data2_numpy = np.random.uniform(0, 16, (5,)).astype(np.float32)
relax_check_gradients(relax.op.matmul, [data1_numpy, data2_numpy], target, dev)
@pytest.mark.skipif(not tvm.testing.device_enabled("llvm"), reason="llvm not enabled")
def test_matmul_5_4():
target = "llvm"
dev = tvm.device(target)
data1_numpy = np.random.uniform(0, 16, (2, 3, 1, 4, 5)).astype(np.float32)
data2_numpy = np.random.uniform(0, 16, (3, 2, 5, 4)).astype(np.float32)
relax_check_gradients(
relax.op.matmul,
[data1_numpy, data2_numpy],
target,
dev,
)
##################### Datatype #####################
@pytest.mark.skipif(not tvm.testing.device_enabled("llvm"), reason="llvm not enabled")
def test_astype():
target = "llvm"
dev = tvm.device(target)
data_numpy = np.random.uniform(0, 16, size=(3, 3)).astype(np.float64)
relax_check_gradients(relax.op.astype, [data_numpy], target, dev, dtype="float32")
##################### Neural network #####################
@pytest.mark.skipif(not tvm.testing.device_enabled("llvm"), reason="llvm not enabled")
def test_relu():
target = "llvm"
dev = tvm.device(target)
data1_numpy = np.random.uniform(0.2, 1, (3, 3)).astype(np.float32)
sign = np.random.randint(0, 2, (3, 3)).astype(np.float32) * 2 - 1
data1_numpy *= sign
relax_check_gradients(relax.op.nn.relu, [data1_numpy], target, dev)
@pytest.mark.skipif(not tvm.testing.device_enabled("llvm"), reason="llvm not enabled")
def test_silu():
target = "llvm"
dev = tvm.device(target)
data1_numpy = np.random.uniform(0, 16, (3, 3)).astype(np.float32)
relax_check_gradients(relax.op.nn.silu, [data1_numpy], target, dev)
@pytest.mark.skipif(not tvm.testing.device_enabled("llvm"), reason="llvm not enabled")
def test_softmax():
target = "llvm"
dev = tvm.device(target)
data1_numpy = np.random.uniform(0, 16, (3, 3)).astype(np.float32)
relax_check_gradients(relax.op.nn.softmax, [data1_numpy], target, dev)
@pytest.mark.skipif(not tvm.testing.device_enabled("llvm"), reason="llvm not enabled")
def test_softmax_with_axis():
target = "llvm"
dev = tvm.device(target)
data1_numpy = np.random.uniform(0, 16, (3, 3)).astype(np.float32)
relax_check_gradients(relax.op.nn.softmax, [data1_numpy], target, dev, axis=1)
@pytest.mark.skipif(not tvm.testing.device_enabled("llvm"), reason="llvm not enabled")
def test_log_softmax():
target = "llvm"
dev = tvm.device(target)
data1_numpy = np.random.uniform(0, 16, (3, 3)).astype(np.float32)
relax_check_gradients(relax.op.nn.log_softmax, [data1_numpy], target, dev)
@pytest.mark.skipif(not tvm.testing.device_enabled("llvm"), reason="llvm not enabled")
def test_log_softmax_with_axis():
target = "llvm"
dev = tvm.device(target)
data1_numpy = np.random.uniform(0, 16, (3, 3)).astype(np.float32)
relax_check_gradients(relax.op.nn.log_softmax, [data1_numpy], target, dev, axis=1)
@pytest.mark.skipif(not tvm.testing.device_enabled("llvm"), reason="llvm not enabled")
def test_cross_entropy_with_logits():
target = "llvm"
dev = tvm.device(target)
data_numpy1 = np.random.uniform(1, 16, (3,)).astype(np.float32)
data_numpy2 = np.random.uniform(1, 16, (3,)).astype(np.float32)
relax_check_gradients(
relax.op.nn.cross_entropy_with_logits,
[data_numpy1, data_numpy2],
target,
dev,
)
@pytest.mark.skipif(not tvm.testing.device_enabled("llvm"), reason="llvm not enabled")
def test_cross_entropy_with_logits_batch():
target = "llvm"
dev = tvm.device(target)
data_numpy1 = np.random.uniform(1, 16, (2, 3)).astype(np.float32)
data_numpy2 = np.random.uniform(1, 16, (2, 3)).astype(np.float32)
relax_check_gradients(
relax.op.nn.cross_entropy_with_logits,
[data_numpy1, data_numpy2],
target,
dev,
)
@pytest.mark.parametrize(
"nll_reduction,nll_weighted,nll_ignore_index",
[
("mean", True, -1),
("sum", True, -1),
("none", True, -1),
("mean", True, 1),
("mean", True, 1),
("mean", False, 1),
],
)
@pytest.mark.skipif(not tvm.testing.device_enabled("llvm"), reason="llvm not enabled")
def test_nll_loss(nll_reduction, nll_weighted, nll_ignore_index):
target = "llvm"
dev = tvm.device(target)
data1_numpy = np.random.uniform(0, 16, (2, 3, 4)).astype(np.float32)
data2_numpy = np.random.randint(0, 3, (2, 4)).astype(np.int64)
# force a position in targets it not ignore_index, to avoid zero total weight
data2_numpy[0][0] = 0
# weight > 0
data3_numpy = np.random.uniform(1, 16, (3,)).astype(np.float32)
input = [data1_numpy, data2_numpy] + ([data3_numpy] if nll_weighted else [])
ignore_grads = [1] + ([2] if nll_weighted else [])
relax_check_gradients(
relax.op.nn.nll_loss,
input,
target,
dev,
ignore_grads=ignore_grads,
reduction=nll_reduction,
ignore_index=nll_ignore_index,
)
@pytest.mark.parametrize(
"nll_reduction1,nll_weighted1,nll_ignore_index1",
[
("mean", True, -1),
("sum", True, -1),
("none", True, -1),
],
)
@pytest.mark.skipif(not tvm.testing.device_enabled("llvm"), reason="llvm not enabled")
def test_nll_loss_no_batch(nll_reduction1, nll_weighted1, nll_ignore_index1):
target = "llvm"
dev = tvm.device(target)
data1_numpy = np.random.uniform(0, 16, (3,)).astype(np.float32)
data2_numpy = np.random.randint(0, 3, ()).astype(np.int64)
# weight > 0
data3_numpy = np.random.uniform(1, 16, (3,)).astype(np.float32)
input = [data1_numpy, data2_numpy] + ([data3_numpy] if nll_weighted1 else [])
ignore_grads = [1] + ([2] if nll_weighted1 else [])
relax_check_gradients(
relax.op.nn.nll_loss,
input,
target,
dev,
ignore_grads=ignore_grads,
reduction=nll_reduction1,
ignore_index=nll_ignore_index1,
)
@pytest.mark.parametrize(
"c2d_shape1,c2d_shape2,c2d_kwargs",
[
(
(3, 2, 10, 10),
(3, 2, 3, 3),
{},
),
(
(3, 2, 10, 10),
(3, 2, 1, 2),
{},
),
(
(3, 2, 10, 10),
(3, 2, 3, 3),
{"strides": (2, 2), "padding": (3, 2), "dilation": (1, 1)},
),
(
(3, 2, 10, 10),
(3, 2, 3, 3),
{"strides": (2, 1), "padding": (2, 2), "dilation": (1, 1)},
),
(
(3, 6, 10, 10),
(4, 3, 3, 3),
{"groups": 2},
),
(
(3, 2, 10, 10),
(4, 1, 3, 3),
{"groups": 2, "strides": (2, 2), "padding": (2, 2), "dilation": (1, 1)},
),
],
)
@pytest.mark.skipif(not tvm.testing.device_enabled("llvm"), reason="llvm not enabled")
def test_conv2d(c2d_shape1, c2d_shape2, c2d_kwargs):
target = "llvm"
dev = tvm.device(target)
import pytest
# Use smaller range to reduce numerical errors in gradient check
data1_numpy = np.random.uniform(0, 2, c2d_shape1).astype(np.float32)
data2_numpy = np.random.uniform(0, 2, c2d_shape2).astype(np.float32)
relax_check_gradients(
relax.op.nn.conv2d,
[data1_numpy, data2_numpy],
target,
dev,
**c2d_kwargs,
)
pool_params = [
(
(3, 3),
{},
),
(
(3, 3),
{"strides": (2, 2), "padding": (1, 2), "dilation": (1, 1), "count_include_pad": True},
),
(
(5, 5),
{
"strides": (2, 2),
"padding": (2, 1),
"dilation": (1, 1),
"ceil_mode": True,
"count_include_pad": True,
},
),
]
@pytest.mark.parametrize("pool_size,pool_kwargs", pool_params)
@pytest.mark.skipif(not tvm.testing.device_enabled("llvm"), reason="llvm not enabled")
def test_max_pool2d(pool_size, pool_kwargs):
target = "llvm"
dev = tvm.device(target)
data_numpy = np.random.uniform(0, 3, size=(3, 2, 10, 10)).astype(np.float32)
relax_check_gradients(
relax.op.nn.max_pool2d,
[data_numpy],
target,
dev,
pool_size=pool_size,
**pool_kwargs,
)
@pytest.mark.parametrize("pool_size,pool_kwargs", pool_params)
@pytest.mark.skipif(not tvm.testing.device_enabled("llvm"), reason="llvm not enabled")
def test_avg_pool2d(pool_size, pool_kwargs):
target = "llvm"
dev = tvm.device(target)
data_numpy = np.random.uniform(0, 3, size=(3, 2, 10, 10)).astype(np.float32)
relax_check_gradients(
relax.op.nn.avg_pool2d,
[data_numpy],
target,
dev,
pool_size=pool_size,
**pool_kwargs,
)
if __name__ == "__main__":
tvm.testing.main()