Skip to content

Commit

Permalink
[ETHOSN] Apply FoldConstant before NPU partitioning (#13848)
Browse files Browse the repository at this point in the history
Introduced FoldConstant before NPU partitioning.
Added a qnn.add test where both inputs are constants.
Updated the number of operators remaining in the host code
for ssd_mobilenet_v1 as the FoldConstant reduces the number
of operators.
  • Loading branch information
ashutosh-arm authored Jan 27, 2023
1 parent 2bfdcbe commit 16b1958
Show file tree
Hide file tree
Showing 3 changed files with 58 additions and 13 deletions.
1 change: 1 addition & 0 deletions python/tvm/relay/op/contrib/ethosn.py
Original file line number Diff line number Diff line change
Expand Up @@ -129,6 +129,7 @@ def partition_for_ethosn(mod, params=None, **opts):

passes = [
transform.InferType(),
transform.FoldConstant(fold_qnn=True),
transform.MergeComposite(pattern_table()),
transform.AnnotateTarget("ethos-n"),
transform.MergeCompilerRegions(),
Expand Down
68 changes: 56 additions & 12 deletions tests/python/contrib/test_ethosn/test_addition.py
Original file line number Diff line number Diff line change
Expand Up @@ -41,20 +41,28 @@ def _get_model(
):
"""Return a model and any parameters it may have"""

iinfo = np.iinfo(dtype)
data_min = iinfo.min
data_max = iinfo.max
def create_or_assign_constant(shape, dtype, default_data):
"""Creates new numpy array or assigns default_data if available."""

iinfo = np.iinfo(dtype)
data_min = iinfo.min
data_max = iinfo.max

nparray = None
if default_data:
nparray = np.array(default_data, dtype=dtype).reshape(shape)
else:
nparray = np.random.randint(data_min, data_max + 1, size=shape, dtype=dtype)

return relay.const(nparray, dtype=dtype)

if lhs_is_constant:
a_data = np.array(constant_data, dtype=dtype).reshape(lhs_shape)
a = relay.const(a_data, dtype=dtype)
a = create_or_assign_constant(lhs_shape, dtype, constant_data)
else:
a = relay.var("a", shape=lhs_shape, dtype=dtype)

if rhs_is_constant:
b_data = np.array(constant_data, dtype=dtype).reshape(rhs_shape)
np.random.randint(data_min, data_max + 1, size=rhs_shape, dtype=dtype)
b = relay.const(b_data, dtype=dtype)
b = create_or_assign_constant(rhs_shape, dtype, constant_data)
else:
b = relay.var("b", shape=rhs_shape, dtype=dtype)

Expand Down Expand Up @@ -125,6 +133,46 @@ def test_addition(dtype, shape):
tei.verify(outputs, dtype, 1)


@requires_ethosn
@pytest.mark.parametrize("dtype", ["uint8", "int8"])
@pytest.mark.parametrize(
"lhs_shape,lhs_is_constant,rhs_shape,rhs_is_constant",
[
((1, 4, 4, 8), True, (1, 1, 1, 8), True),
((4,), True, (1, 16, 12, 4), True),
((1, 1, 1, 8), True, (1, 4, 4, 8), True),
((1, 16, 12, 4), True, (4,), True),
],
)
def test_addition_both_inputs_constants(
dtype, lhs_shape, lhs_is_constant, rhs_shape, rhs_is_constant
):
"""Check if addition is simplified when both inputs are constants."""
np.random.seed(0)

lhs_zp, lhs_sc, rhs_zp, rhs_sc, out_zp, out_sc = _get_addition_qnn_params(dtype)

model = _get_model(
lhs_shape,
rhs_shape,
lhs_zp,
lhs_sc,
rhs_zp,
rhs_sc,
out_zp,
out_sc,
dtype,
lhs_is_constant=lhs_is_constant,
rhs_is_constant=rhs_is_constant,
)
from tvm.relay.op.contrib import partition_for_ethosn # pylint: disable=import-outside-toplevel

mod = tei.make_module(model, {})
assert "qnn.add" in mod.astext(False)
mod = partition_for_ethosn(mod, {})
assert "qnn.add" not in mod.astext(False)


@requires_ethosn
@pytest.mark.parametrize("dtype", ["uint8", "int8"])
@pytest.mark.parametrize(
Expand All @@ -145,9 +193,6 @@ def test_addition_to_depthwise(dtype, lhs_shape, lhs_is_constant, rhs_shape, rhs
data_max = iinfo.max
lhs_zp, lhs_sc, rhs_zp, rhs_sc, out_zp, out_sc = _get_addition_qnn_params(dtype)

constant_shape = lhs_shape if lhs_is_constant else rhs_shape
constant_data = np.random.randint(data_min, data_max + 1, size=constant_shape, dtype=dtype)

model = _get_model(
lhs_shape,
rhs_shape,
Expand All @@ -160,7 +205,6 @@ def test_addition_to_depthwise(dtype, lhs_shape, lhs_is_constant, rhs_shape, rhs
dtype,
lhs_is_constant=lhs_is_constant,
rhs_is_constant=rhs_is_constant,
constant_data=constant_data,
)
input_shape = rhs_shape if lhs_is_constant else lhs_shape
input_name = "b" if lhs_is_constant else "a"
Expand Down
2 changes: 1 addition & 1 deletion tests/python/contrib/test_ethosn/test_networks.py
Original file line number Diff line number Diff line change
Expand Up @@ -218,6 +218,6 @@ def test_ssd_mobilenet_v1():
input_dict={"normalized_input_image_tensor": (1, 300, 300, 3)},
compile_hash=_compile_hash,
output_count=4,
host_ops=26,
host_ops=14,
npu_partitions=1,
)

0 comments on commit 16b1958

Please sign in to comment.