Skip to content

Commit

Permalink
[TVMC][ETHOSN] Improve target string to avoid duplication (#11272)
Browse files Browse the repository at this point in the history
* [TVMC][ETHOSN] Improve target string to avoid duplication

Improves the TVMC target string to avoid duplication of the
NPU variant. The new target string will require the just the NPU
name followed by -variant=n78. The old target string is deprecated
and will be removed in a subsequent version of TVM.

Change-Id: I4638f36788df3f478435ac13d3531aad2b23f204

* fix linting

Change-Id: I76a9da511899f24a163be669877605cd1a440022

* fix make variant functions and update test error message

Change-Id: Iff553d4b255c0ce0b86bad42eaa94ee9b1c62508
  • Loading branch information
lhutton1 authored May 18, 2022
1 parent 7f1c54f commit 99caa65
Show file tree
Hide file tree
Showing 8 changed files with 50 additions and 23 deletions.
18 changes: 15 additions & 3 deletions python/tvm/driver/tvmc/composite_target.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,12 +18,13 @@
Provides support to composite target on TVMC.
"""
import logging
import warnings

# Make sure Vitis AI codegen is registered
import tvm.contrib.target.vitis_ai # pylint: disable=unused-import

from tvm.relay.op.contrib.arm_compute_lib import partition_for_arm_compute_lib
from tvm.relay.op.contrib.ethosn import partition_for_ethosn78
from tvm.relay.op.contrib.ethosn import partition_for_ethosn
from tvm.relay.op.contrib.cmsisnn import partition_for_cmsisnn
from tvm.relay.op.contrib.ethosu import partition_for_ethosu
from tvm.relay.op.contrib.bnns import partition_for_bnns
Expand Down Expand Up @@ -55,9 +56,9 @@
"config_key": "relay.ext.cmsisnn.options",
"pass_pipeline": partition_for_cmsisnn,
},
"ethos-n78": {
"ethos-n": {
"config_key": "relay.ext.ethos-n.options",
"pass_pipeline": partition_for_ethosn78,
"pass_pipeline": partition_for_ethosn,
},
"ethos-u": {
"config_key": "relay.ext.ethos-u.options",
Expand All @@ -71,6 +72,11 @@
"config_key": "relay.ext.vitis_ai.options",
"pass_pipeline": partition_for_vitis_ai,
},
# Deprecated in favour of "ethos-n".
"ethos-n78": {
"config_key": "relay.ext.ethos-n.options",
"pass_pipeline": partition_for_ethosn,
},
}


Expand Down Expand Up @@ -99,6 +105,12 @@ def get_codegen_by_target(name):
requested target codegen information
"""
try:
if name == "ethos-n78":
warnings.warn(
"Please use 'ethos-n' instead of the deprecated 'ethos-n78' target, "
"which will be removed in a later release of TVM.",
DeprecationWarning,
)
return REGISTERED_CODEGEN[name]
except KeyError:
raise TVMCException("Composite target %s is not defined in TVMC." % name)
18 changes: 15 additions & 3 deletions python/tvm/relay/op/contrib/ethosn.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
# pylint: disable=invalid-name, unused-argument
"""Arm(R) Ethos(TM)-N NPU supported operators."""
from enum import Enum
import warnings

import tvm.ir
from tvm.relay import transform
Expand Down Expand Up @@ -46,7 +47,7 @@ def ethosn_available():
return Available.SW_AND_HW if hw else Available.SW_ONLY


def partition_for_ethosn78(mod, params=None, **opts):
def partition_for_ethosn(mod, params=None, **opts):
"""Partition the graph greedily offloading supported
operators to Arm Ethos-N NPU.
Expand All @@ -61,8 +62,19 @@ def partition_for_ethosn78(mod, params=None, **opts):
-------
ret : annotated and partitioned module.
"""
if not opts or opts.get("variant", "").lower() != "ethos-n78":
raise ValueError("When targeting Ethos(TM)-N78, -variant=Ethos-N78 should be set.")
opts = opts or {}
if "variant" not in opts:
raise ValueError("Please specify a variant in the target string, e.g. -variant=n78.")

# -variant=ethos-n78 deprecated in favour of -variant=n78
if opts["variant"].lower() == "ethos-n78":
warnings.warn(
"Please use '-variant=n78' instead of the deprecated "
"'-variant=ethos-n78', which will be removed in TVM v0.9.",
DeprecationWarning,
)
elif opts["variant"] != "n78":
raise ValueError("When targeting Ethos(TM)-N78, -variant=n78 should be set.")

if params:
mod["main"] = bind_params_by_name(mod["main"], params)
Expand Down
11 changes: 8 additions & 3 deletions src/relay/backend/contrib/ethosn/codegen.cc
Original file line number Diff line number Diff line change
Expand Up @@ -213,9 +213,14 @@ String MakeVariant(Optional<EthosnCompilerConfig> configuration) {
String variant = configuration.value()->variant;
// Transform variant string to lowercase for comparison
std::string variant_string = variant.c_str();
std::transform(variant_string.begin(), variant_string.end(), variant_string.begin(), ::tolower);
std::string variant_n78 = "ethos-n78";
if (variant_string == variant_n78) {

// Checking deprecated variant format. Support for specifying
// the variant in this way only remains for backwards compatibility
// and will be removed in a later release of TVM.
std::string deprecated_variant_string = variant_string;
std::transform(deprecated_variant_string.begin(), deprecated_variant_string.end(),
deprecated_variant_string.begin(), ::tolower);
if (variant_string == "n78" || deprecated_variant_string == "ethos-n78") {
String tops = configuration.value()->tops;
String ple_ratio = configuration.value()->ple_ratio;
variant = "Ethos-N78_" + tops + "TOPS_" + ple_ratio + "PLE_RATIO";
Expand Down
2 changes: 1 addition & 1 deletion src/relay/backend/contrib/ethosn/codegen_ethosn.h
Original file line number Diff line number Diff line change
Expand Up @@ -251,7 +251,7 @@ struct EthosnCompilerConfigNode : public tvm::AttrsNode<EthosnCompilerConfigNode
String compiler_algorithm;

TVM_DECLARE_ATTRS(EthosnCompilerConfigNode, "ext.attrs.EthosnCompilerConfigNode") {
TVM_ATTR_FIELD(variant).describe("See Ethos-N documentation.").set_default("Ethos-N78");
TVM_ATTR_FIELD(variant).describe("See Ethos-N documentation.").set_default("n78");
TVM_ATTR_FIELD(sram_size)
.describe("Optionally override the default sram size. See Ethos(TM)-N documentation.")
.set_default("0");
Expand Down
14 changes: 7 additions & 7 deletions tests/python/contrib/test_ethosn/test_partition_params.py
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@
from tvm import relay
import numpy as np

from tvm.relay.op.contrib.ethosn import partition_for_ethosn78
from tvm.relay.op.contrib.ethosn import partition_for_ethosn
from tvm.testing import requires_ethosn


Expand All @@ -35,14 +35,14 @@ def test_ethosn78_partition_no_error():
res = relay.nn.bias_add(res, b, axis=1)

mod = tvm.IRModule.from_expr(res)
opts = {"variant": "Ethos-N78"}
partition_for_ethosn78(mod, **opts)
opts = {"variant": "n78"}
partition_for_ethosn(mod, **opts)


@requires_ethosn
def test_ethosn78_partition_undefined_variant():
with pytest.raises(
ValueError, match=r".*When targeting Ethos\(TM\)-N78, -variant=Ethos-N78 should be set.*"
ValueError, match=r".*Please specify a variant in the target string, e.g. -variant=n78.*"
):
a = relay.var("a", shape=[2, 7, 8, 8], dtype="uint8")
w = relay.const(np.random.uniform(-10, 10, (8, 7, 3, 3)).astype("uint8"))
Expand All @@ -53,13 +53,13 @@ def test_ethosn78_partition_undefined_variant():
res = relay.nn.bias_add(res, b, axis=1)

mod = tvm.IRModule.from_expr(res)
partition_for_ethosn78(mod)
partition_for_ethosn(mod)


@requires_ethosn
def test_ethosn78_partition_invalid_variant():
with pytest.raises(
ValueError, match=r".*When targeting Ethos\(TM\)-N78, -variant=Ethos-N78 should be set.*"
ValueError, match=r".*When targeting Ethos\(TM\)-N78, -variant=n78 should be set.*"
):
a = relay.var("a", shape=[2, 7, 8, 8], dtype="uint8")
w = relay.const(np.random.uniform(-10, 10, (8, 7, 3, 3)).astype("uint8"))
Expand All @@ -71,4 +71,4 @@ def test_ethosn78_partition_invalid_variant():

mod = tvm.IRModule.from_expr(res)
opts = {"variant": "Ethos-N"}
partition_for_ethosn78(mod, **opts)
partition_for_ethosn(mod, **opts)
4 changes: 1 addition & 3 deletions tests/python/driver/tvmc/test_compiler.py
Original file line number Diff line number Diff line change
Expand Up @@ -419,9 +419,7 @@ def test_compile_tflite_module_with_external_codegen_cmsisnn(
def test_compile_tflite_module_with_external_codegen_ethos_n78(tflite_mobilenet_v1_1_quant):
pytest.importorskip("tflite")
tvmc_model = tvmc.load(tflite_mobilenet_v1_1_quant)
tvmc_package = tvmc.compile(
tvmc_model, target="ethos-n78 -variant=ethos-n78, llvm", dump_code="relay"
)
tvmc_package = tvmc.compile(tvmc_model, target="ethos-n -variant=n78, llvm", dump_code="relay")
dumps_path = tvmc_package.package_path + ".relay"

# check for output types
Expand Down
2 changes: 1 addition & 1 deletion tests/python/driver/tvmc/test_composite_target.py
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@
def test_get_codegen_names():
names = tvmc.composite_target.get_codegen_names()

assert "ethos-n78" in names
assert "ethos-n" in names
assert "vitis-ai" in names
assert len(names) > 0

Expand Down
4 changes: 2 additions & 2 deletions tests/python/driver/tvmc/test_target.py
Original file line number Diff line number Diff line change
Expand Up @@ -153,10 +153,10 @@ def test_parse_quotes_and_separators_on_options():


def test_parse_multiple_target_with_opts_ethos_n78():
targets = parse_target("ethos-n78 -myopt=value, llvm -device=arm_cpu --system-lib")
targets = parse_target("ethos-n -myopt=value, llvm -device=arm_cpu --system-lib")

assert len(targets) == 2
assert "ethos-n78" == targets[0]["name"]
assert "ethos-n" == targets[0]["name"]
assert "myopt" in targets[0]["opts"]
assert "value" == targets[0]["opts"]["myopt"]
assert "llvm" == targets[1]["name"]
Expand Down

0 comments on commit 99caa65

Please sign in to comment.