Exemple #1
0
def test_split():
    if not ethosn_available():
        return

    trials = [
        ((1, 16, 16, 32), (2, 7, 10), 2),
        ((1, 12, 8, 16), 3, 1),
        ((1, 33), 11, 1),
    ]

    np.random.seed(0)
    for shape, splits, axis in trials:
        outputs = []
        inputs = {
            "a":
            tvm.nd.array(
                np.random.randint(0, high=256, size=shape, dtype="uint8"))
        }
        for npu in [False, True]:
            model = _get_model(shape, "uint8", splits, axis)
            mod = tei.make_module(model, {})
            output_count = splits if type(splits) == int else len(splits) + 1
            outputs.append(
                tei.build_and_run(mod, inputs, output_count, {}, npu=npu))

        tei.verify(outputs, 0)
Exemple #2
0
def test_output_order():
    if not ethosn_available():
        return

    def get_model(input_shape, var_names):
        """Return a model"""

        a = relay.var(next(var_names), shape=input_shape, dtype="uint8")

        z = relay.op.clip(a, 0, 255)
        b = relay.op.clip(z, 0, 15)
        c = relay.op.clip(z, 16, 31)
        d = relay.op.clip(z, 32, 47)
        e = relay.op.clip(z, 48, 63)
        f = relay.op.clip(z, 64, 79)
        g = relay.op.clip(z, 80, 95)
        h = relay.op.clip(z, 96, 111)
        i = relay.op.clip(z, 112, 127)
        return relay.Tuple((d, c, e, f, i, b, h, g))

    inputs = {
        "a":
        tvm.nd.array(
            np.random.randint(0, high=255, size=(1, 16, 16, 4),
                              dtype="uint8")),
    }

    outputs = []
    for npu in [False, True]:
        model = get_model(inputs["a"].shape, iter(inputs))
        mod = tei.make_module(model, [])
        outputs.append(tei.build_and_run(mod, inputs, 8, {}, npu=npu))

    tei.verify(outputs, 1)
Exemple #3
0
def test_sigmoid_failure():
    if not ethosn_available():
        return

    trials = [
        ((2, 4, 4, 4), 64, 0.2, 0, 1 / 256, "uint8", "batch size=2, batch size must = 1"),
        (
            (1, 4, 4, 4),
            64,
            0.2,
            0,
            1 / 256,
            "int8",
            "dtype='int8', dtype must be either uint8 or int32",
        ),
        (
            (1, 4, 4, 4),
            64,
            0.2,
            0,
            1,
            "uint8",
            "output quantization params=(0, 1), must = (0, 1/256)",
        ),
    ]

    for shape, input_zp, input_sc, output_zp, output_sc, dtype, err_msg in trials:
        model = _get_model(shape, input_zp, input_sc, output_zp, output_sc, dtype)
        model = tei.make_ethosn_composite(model, "ethos-n.qnn_sigmoid")
        mod = tei.make_ethosn_partition(model)
        tei.test_error(mod, {}, err_msg)
Exemple #4
0
def test_fullyconnected():
    if not ethosn_available():
        return

    trials = [
        ((1, 1024), 71, 0.580, 79, 1.498),
        ((1, 4096), 166, 1.724, 117, 0.180),
        ((1, 16384), 101, 1.372, 21, 1.346),
    ]
    np.random.seed(0)
    for shape, input_zp, input_sc, kernel_zp, kernel_sc in trials:
        inputs = {
            "a":
            tvm.nd.array(
                np.random.randint(0, high=255, size=shape, dtype="uint8")),
        }
        outputs = []
        output_zp, output_sc = tei.get_conv2d_qnn_params(
            input_zp, input_sc, kernel_zp, kernel_sc, shape[0], shape[1], 1)
        for npu in [False, True]:
            model, params = _get_model(
                shape,
                shape,
                input_zp,
                input_sc,  # input zp, sc
                kernel_zp,
                kernel_sc,  # kernel
                output_zp,
                output_sc,  # output
                "uint8",
            )
            mod = tei.make_module(model, params)
            outputs.append(tei.build_and_run(mod, inputs, 1, params, npu=npu))
        tei.verify(outputs, 1)
Exemple #5
0
def test_pooling():
    if not ethosn_available():
        return

    trials = [
        ((1, 8, 8, 8), relay.nn.max_pool2d, (2, 2), (2, 2), (0, 0, 0, 0),
         "NHWC"),
        ((1, 9, 9, 9), relay.nn.max_pool2d, (2, 2), (2, 2), (0, 0, 1, 1),
         "NHWC"),
        ((1, 9, 9, 9), relay.nn.max_pool2d, (3, 3), (2, 2), (0, 0, 0, 0),
         "NHWC"),
        ((1, 8, 8, 8), relay.nn.max_pool2d, (3, 3), (2, 2), (0, 0, 1, 1),
         "NHWC"),
        ((1, 8, 8, 8), relay.nn.avg_pool2d, (3, 3), (1, 1), (1, 1, 1, 1),
         "NHWC"),
    ]

    for shape, typef, size, stride, pad, layout in trials:
        inputs = {
            "a":
            tvm.nd.array(
                np.random.randint(low=0, high=255, size=shape, dtype="uint8")),
        }
        outputs = []
        model = _get_model(shape, typef, size, stride, pad, layout, "uint8")
        for npu in [False, True]:
            mod = tei.make_module(model, {})
            outputs.append(tei.build_and_run(mod, inputs, 1, {}, npu=npu))

        tei.verify(outputs, 1)
Exemple #6
0
def test_conv2d_failure():
    if not ethosn_available():
        return

    trials = [
        ((1, 4, 4, 4), 1, 1, 0, 1, 0, 1, 0, 1, "none", (1, 1), (1, 1), 1,
         "uint8", 8, "HWIO",
         "Overall scale (of the input * weights / output) should be in the range [0, 1)"
         ),
        ((1, 4, 4,
          4), 1, 1, 0, 1, 0, 1, 0, 1, "none", (1, 1), (1, 1), 1, "int8", 8,
         "HWIO", "dtype='int8', dtype must be either uint8 or int32"),
        ((1, 4, 4, 4), 2, 2, 0, 1, 0, 1, 0, 2, "both", (1, 1), (1, 1), 1,
         "uint8", 8, "HWIO",
         "both op and attr padding exist, must be either op/attr only or no padding"
         ),
        ((1, 4, 4, 4), 1, 1, 0, 1, 0, 1, 0, 2, "none", (1, 1, 1), (1, 1), 1,
         "uint8", 8, "HWIO", "stride size=3, stride size must = 2"),
        ((1, 4, 4, 4), 1, 1, 0, 1, 0, 1, 0, 2, "none", (1, 1), (2, 1), 1,
         "uint8", 8, "HWIO", "dilation=[2, 1], dilation must = [1, 1]"),
        ((2, 4, 4, 4), 1, 1, 0, 1, 0, 1, 0, 2, "none", (1, 1), (1, 1), 1,
         "uint8", 8, "HWIO", "batch size=2, batch size must = 1"),
    ]

    np.random.seed(0)
    for shape, kernel_h, kernel_w, input_zp, input_sc, kernel_zp,\
        kernel_sc, output_zp, output_sc, pad, stride, dilation,\
        groups, dtype, out_channels, weight_format, err_msg in trials:
        model, params = _get_model(shape, kernel_h, kernel_w, input_zp,
                                   input_sc, kernel_zp, kernel_sc, output_zp,
                                   output_sc, pad, stride, dilation, groups,
                                   dtype, out_channels, weight_format)
        model = tei.make_ethosn_composite(model, "ethos-n.qnn_conv2d")
        mod = tei.make_ethosn_partition(model)
        tei.test_error(mod, {}, err_msg)
Exemple #7
0
def test_addition_failure():
    if not ethosn_available():
        return

    trials = [
        (
            (2, 4, 4, 4),
            "uint8",
            0,
            1,
            0,
            1,
            0,
            1,
            "batch size=2, batch size must = 1; batch size=2, batch size must = 1",
        ),
        (
            (1, 4, 4, 4),
            "int8",
            0,
            1,
            0,
            1,
            0,
            1,
            "dtype='int8', dtype must be either uint8 or int32; dtype='int8', dtype must be either uint8 or int32",
        ),
    ]

    for shape, dtype, lhs_zp, lhs_sc, rhs_zp, rhs_sc, out_zp, out_sc, err_msg in trials:
        model = _get_model(shape, lhs_zp, lhs_sc, rhs_zp, rhs_sc, out_zp,
                           out_sc, dtype)
        mod = tei.make_ethosn_partition(model)
        tei.test_error(mod, {}, err_msg)
Exemple #8
0
def test_addition():
    if not ethosn_available():
        return

    trials = [
        ((1, 22, 9, 9), 24, 1.057, 253, 0.452),
        ((1, 27, 21, 16), 79, 0.850, 24, 0.380),
        ((1, 7, 12, 28), 125, 1.293, 239, 0.320),
        ((1, 14, 9, 6), 14, 0.942, 227, 1.562),
        ((1, 13, 16, 22), 15, 0.727, 180, 0.461),
    ]
    np.random.seed(0)
    for shape, rhs_zp, rhs_sc, lhs_zp, lhs_sc in trials:
        outputs = []
        inputs = {
            "a":
            tvm.nd.array(
                np.random.randint(0, high=255, size=shape, dtype="uint8")),
            "b":
            tvm.nd.array(
                np.random.randint(0, high=255, size=shape, dtype="uint8")),
        }
        out_zp, out_sc = _get_addition_qnn_params(lhs_zp, lhs_sc, rhs_zp,
                                                  rhs_sc)
        model = _get_model(shape, lhs_zp, lhs_sc, rhs_zp, rhs_sc, out_zp,
                           out_sc, "uint8")
        for npu in [False, True]:
            mod = tei.make_module(model, [])
            outputs.append(tei.build_and_run(mod, inputs, 1, {}, npu=npu))

        tei.verify(outputs, 2)
Exemple #9
0
def test_conv2d():
    if not ethosn_available():
        return

    trials = [
        [(1, 17, 20, 26), 4, 3, 1, 'attr', (2, 2), (1, 1)],
        [(1, 30, 27, 30), 5, 5, 3, 'none', (1, 1), (1, 1)],
        [(1, 14, 28, 11), 6, 2, 2, 'op', (2, 2), (1, 1)],
        [(1, 9, 20, 30), 7, 1, 5, 'none', (1, 1), (1, 1)],
        [(1, 21, 21, 22), 8, 5, 1, 'attr', (2, 2), (1, 1)],
        [(1, 21, 25, 29), 9, 2, 5, 'op', (1, 1), (1, 1)],
        [(1, 31, 28, 15), 10, 1, 2, 'attr', (2, 2), (1, 1)],
        [(1, 21, 21, 8), 11, 3, 3, 'none', (1, 1), (1, 1)],
        [(1, 5, 11, 6), 12, 5, 2, 'op', (2, 2), (1, 1)],
        [(1, 12, 7, 18), 13, 1, 3, 'op', (1, 1), (1, 1)],
        [(1, 24, 6, 26), 14, 3, 5, 'none', (2, 2), (1, 1)],
        [(1, 19, 24, 16), 15, 2, 1, 'attr', (1, 1), (1, 1)],
    ]

    np.random.seed(0)
    for depthwise in [False, True]:
        for shape, out_channels, kernel_h, kernel_w, pad, stride, dilation in trials:
            if depthwise:
                out_channels = shape[3]
                groups = out_channels
                kernel_w = kernel_h
                weight_format = "HWOI"
                stride = (1, 1) if kernel_w == 1 else (2, 2)
            else:
                groups = 1
                weight_format = "HWIO"

            outputs = []
            inputs = {
                "a":
                tvm.nd.array(
                    np.random.randint(0, high=255, size=shape, dtype="uint8")),
            }
            input_zp = np.random.randint(0, 255)
            input_sc = np.random.random() * 2
            kernel_zp = np.random.randint(0, 255)
            kernel_sc = np.random.random() * 2
            output_zp, output_sc = _get_conv2d_qnn_params(
                input_zp, input_sc, kernel_zp, kernel_sc, kernel_h, kernel_w,
                shape[3])
            model, params = _get_model(shape, kernel_h, kernel_w, input_zp,
                                       input_sc, kernel_zp, kernel_sc,
                                       output_zp, output_sc, pad, stride,
                                       dilation, groups, "uint8", out_channels,
                                       weight_format)
            for npu in [False, True]:
                mod = tei.make_module(model, params)
                outputs.append(
                    tei.build_and_run(mod, inputs, 1, params, npu=npu))

            tei.verify(outputs, 1)
Exemple #10
0
def test_constant_duplication():
    if not ethosn_available():
        return

    model, params = _get_model()
    mod = tei.make_module(model, params)
    res = tei.build(mod, params, npu=True, expected_host_ops=1)
    for key, value in res.params.items():
        assert key == "p0"
        assert value.numpy().size == 64
Exemple #11
0
def test_split_add_concat():
    if not ethosn_available():
        return

    def get_model(input_shape, var_names):
        """Return a model"""

        a = relay.var(next(var_names), shape=input_shape, dtype="uint8")
        split_scale = relay.const(0.25, "float32")
        split_zp = relay.const(100, "int32")
        add_scale = relay.const(0.75, "float32")
        add_zp = relay.const(120, "int32")
        axis = 2

        split = relay.split(a, indices_or_sections=4, axis=axis)
        b = relay.qnn.op.add(
            split[0],
            split[1],
            lhs_scale=split_scale,
            lhs_zero_point=split_zp,
            rhs_scale=split_scale,
            rhs_zero_point=split_zp,
            output_scale=add_scale,
            output_zero_point=add_zp,
        )
        conc = relay.qnn.op.concatenate(
            [b, split[2], split[3]],
            input_scales=(add_scale, split_scale, split_scale),
            input_zero_points=(add_zp, split_zp, split_zp),
            output_scale=add_scale,
            output_zero_point=add_zp,
            axis=axis,
        )
        return conc

    inputs = {
        "a":
        tvm.nd.array(
            np.random.randint(0, high=255, size=(1, 16, 16, 4),
                              dtype="uint8")),
    }

    outputs = []
    for npu in [False, True]:
        model = get_model(inputs["a"].shape, iter(inputs))
        mod = tei.make_module(model, [])
        outputs.append(tei.build_and_run(mod, inputs, 1, {}, npu=npu))

    tei.verify(outputs, 2)
Exemple #12
0
def _test_image_network(
    model_url,
    model_sub_path,
    input_dict,
    compile_hash,
    output_count,
    run=True,
    host_ops=0,
    npu_partitions=1,
):
    if not ethosn_available():
        return

    def get_model():
        if model_url[-3:] in ("tgz", "zip"):
            model_path = tf_testing.get_workload_official(
                model_url,
                model_sub_path,
            )
        else:
            model_path = download.download_testdata(
                model_url,
                model_sub_path,
            )
        return _get_tflite_model(model_path, input_dict, "uint8")

    outputs = []
    inputs = {}
    for input_name in input_dict:
        input_shape = input_dict[input_name]
        inputs[input_name] = tei.get_real_image(input_shape[1], input_shape[2])

    for npu in [False, True]:
        mod, params = get_model()
        graph, lib, params = tei.build(mod,
                                       params,
                                       npu=npu,
                                       expected_host_ops=host_ops,
                                       npu_partitions=npu_partitions)
        if npu:
            tei.assert_lib_hash(lib, compile_hash)
        if run:
            outputs.append(
                tei.run(graph, lib, params, inputs, output_count, npu=npu))

    if run:
        tei.verify(outputs, 1, verify_saturation=False)
Exemple #13
0
def test_multiple_command_streams(dtype):
    """Check that multiple Ethos-N partitions are correctly handled.

    If there's more than one Ethos-N graph partition, more than one command
    stream will be created. This should be handled correctly by both the
    Ethos-N codegen and Ethos-N runtime module. This test checks against a
    simple graph which creates two Ethos-N partitions and checks the result
    against an 'all-CPU' run through TVM.
    """
    def get_model(dtype):
        """
        max_pool2d
             |
            abs
             |
        max_pool2d
        """
        x = relay.var("x", shape=(1, 4, 4, 4), dtype=dtype)
        out = relay.nn.max_pool2d(x, (2, 2), (2, 2),
                                  layout="NHWC")  # supported
        out = relay.op.abs(out)  # not supported
        out = relay.nn.max_pool2d(out, (2, 2), (2, 2),
                                  layout="NHWC")  # supported
        return out

    np.random.seed(0)
    inputs = {
        "x":
        tvm.nd.array(
            np.random.randint(np.iinfo(dtype).min,
                              np.iinfo(dtype).max + 1,
                              size=(1, 4, 4, 4),
                              dtype=dtype))
    }
    model = get_model(dtype)
    mod = tei.make_module(model, {})

    # Mock inference is only supported when the whole graph is offloaded to the NPU
    if ethosn_available() == Available.SW_ONLY:
        tei.build(mod, {}, npu=True, expected_host_ops=1, npu_partitions=2)
    else:
        tei.build_and_run(mod,
                          inputs,
                          1, {},
                          npu=True,
                          expected_host_ops=1,
                          npu_partitions=2)
Exemple #14
0
def test_multiple_command_streams():
    """Check that multiple Ethos-N partitions are correctly handled.

    If there's more than one Ethos-N graph partition, more than one command
    stream will be created. This should be handled correctly by both the
    Ethos-N codegen and Ethos-N runtime module. This test checks against a
    simple graph which creates two Ethos-N partitions and checks the result
    against an 'all-CPU' run through TVM.
    """
    if ethosn_available() != Available.SW_AND_HW:
        return

    def get_model():
        """
        max_pool2d
             |
            abs
             |
        max_pool2d
        """
        x = relay.var("x", shape=(1, 4, 4, 4), dtype="uint8")
        out = relay.nn.max_pool2d(x, (2, 2), (2, 2),
                                  layout="NHWC")  # supported
        out = relay.op.abs(out)  # not supported
        out = relay.nn.max_pool2d(out, (2, 2), (2, 2),
                                  layout="NHWC")  # supported
        return out

    np.random.seed(0)
    outputs = []
    inputs = {
        "x":
        tvm.nd.array(
            np.random.randint(0, high=256, size=(1, 4, 4, 4), dtype="uint8"))
    }
    for npu in [False, True]:
        model = get_model()
        mod = tei.make_module(model, {})
        outputs.append(
            tei.build_and_run(mod,
                              inputs,
                              1, {},
                              npu=npu,
                              expected_host_ops=1,
                              npu_partitions=2))

    tei.verify(outputs, 0)
Exemple #15
0
def test_relu_failure():
    if not ethosn_available():
        return

    trials = [
        ((1, 4, 4, 4, 4), "uint8", 65, 78,
         "dimensions=5, dimensions must be <= 4"),
        ((1, 8, 4, 2), "int8", 1, 254,
         "dtype='int8', dtype must be either uint8 or int32"),
        ((1, 8, 4, 2), "uint8", 254, 1, "Relu has lower bound > upper bound"),
        ((2, 2, 2, 2), "uint8", 1, 63, "batch size=2, batch size must = 1; "),
    ]

    for shape, dtype, a_min, a_max, err_msg in trials:
        model = _get_model(shape, dtype, a_min, a_max)
        mod = tei.make_ethosn_partition(model)
        tei.test_error(mod, {}, err_msg)
Exemple #16
0
def test_split_with_asym_concats():
    if not ethosn_available():
        return

    def get_model(shape, splits, axis):
        a = relay.var("a", shape=shape, dtype="uint8")
        split = relay.op.split(a, indices_or_sections=splits, axis=axis)
        zeroi = relay.const(1, "int32")
        zerof = relay.const(0.5, "float32")
        con1 = relay.qnn.op.concatenate(
            [split[0], split[1]],
            input_scales=[zerof] * 2,
            input_zero_points=[zeroi] * 2,
            output_scale=zerof,
            output_zero_point=zeroi,
            axis=axis,
        )
        con2 = relay.qnn.op.concatenate(
            [split[2], split[3]],
            input_scales=[zerof] * 2,
            input_zero_points=[zeroi] * 2,
            output_scale=zerof,
            output_zero_point=zeroi,
            axis=axis,
        )
        return relay.Tuple((con2, con1))

    trials = [
        ((1, 16, 16, 32), (2, 7, 10), 2),
    ]

    np.random.seed(0)
    for shape, splits, axis in trials:
        outputs = []
        inputs = {
            "a":
            tvm.nd.array(
                np.random.randint(0, high=256, size=shape, dtype="uint8"))
        }
        for npu in [False, True]:
            model = get_model(shape, splits, axis)
            mod = tei.make_module(model, {})
            outputs.append(tei.build_and_run(mod, inputs, 2, {}, npu=npu))

        tei.verify(outputs, 0)
Exemple #17
0
def requires_ethosn(*args):
    """Mark a test as requiring Arm(R) Ethos(TM)-N to run.

    Parameters
    ----------
    f : function
        Function to mark
    """
    marks = [
        pytest.mark.ethosn,
        pytest.mark.skipif(
            not ethosn_available(),
            reason=("Arm(R) Ethos(TM)-N support not enabled.  "
                    "Set USE_ETHOSN=ON in config.cmake to enable, "
                    "and ensure that hardware support is present."),
        ),
    ]
    return _compose(args, marks)
Exemple #18
0
def test_mobilenet_v1():
    # If this test is failing due to a hash mismatch, please notify @mbaret and
    # @Leo-arm. The hash is there to catch any changes in the behaviour of the
    # codegen, which could come about from either a change in Support Library
    # version or a change in the Ethos-N codegen. To update this requires running
    # on hardware that isn't available in CI.
    hw = ethosn_available()
    _test_image_network(
        model_url="https://storage.googleapis.com/download.tensorflow.org/"
        "models/mobilenet_v1_2018_08_02/mobilenet_v1_1.0_224_quant.tgz",
        model_sub_path="mobilenet_v1_1.0_224_quant.tflite",
        input_dict={"input": (1, 224, 224, 3)},
        compile_hash="81637c89339201a07dc96e3b5dbf836a",
        output_count=1,
        run=(hw == Available.SW_AND_HW),
        host_ops=3,
        npu_partitions=1,
    )
def test_depth_to_space_failure():
    if not ethosn_available():
        return

    trials = [
        ((2, 16, 16, 16), 2, "uint8", "NHWC",
         "batch size=2, batch size must = 1"),
        ((1, 16, 16, 16), 2, "int8", "NHWC",
         "dtype='int8', dtype must be either uint8 or int32"),
        ((1, 16, 16, 16), 4, "uint8", "NHWC",
         "Only block size of 2 is supported"),
        ((1, 16, 16, 16), 2, "uint8", "NCHW",
         "layout=NCHW, layout must = NHWC"),
    ]

    for shape, block, dtype, layout, err_msg in trials:
        model = _get_model(shape, block, dtype, layout)
        mod = tei.make_ethosn_partition(model)
        tei.test_error(mod, {}, err_msg)
Exemple #20
0
def test_input_tuples():
    if not ethosn_available():
        return

    def get_model(shapes, axis):
        tup = []
        for i, shape in enumerate(shapes):
            a = relay.var("in" + str(i), shape=shape, dtype="uint8")
            tup.append(a)

        zeroi = relay.const(1, "int32")
        zerof = relay.const(0.5, "float32")
        con = relay.qnn.op.concatenate(
            tup,
            input_scales=[zerof] * len(shapes),
            input_zero_points=[zeroi] * len(shapes),
            output_scale=zerof,
            output_zero_point=zeroi,
            axis=axis,
        )

        return con

    np.random.seed(0)
    inputs = {
        "in0":
        tvm.nd.array(np.random.randint(0, high=256, size=(1, 4),
                                       dtype="uint8")),
        "in1":
        tvm.nd.array(np.random.randint(0, high=256, size=(1, 6),
                                       dtype="uint8")),
    }
    outputs = []
    for npu in [False, True]:
        model = get_model([(1, 4), (1, 6)], 1)
        if not npu:
            mod = tei.make_module(model, {})
        else:
            mod = tei.make_ethosn_partition(model)
        lib = tei.build(mod, {}, npu=False)
        outputs.append(tei.run(lib, inputs, 1, npu=npu))

    tei.verify(outputs, 0)
Exemple #21
0
def test_concatenate():
    if not ethosn_available():
        return

    trials = [
        ([(1, 4), (1, 6)], 1),
        ([(1, 16, 4), (1, 16, 4)], 1),
        ([(1, 25, 4, 16)] * 3, 3),
        ([(1, 25, 4, 16), (1, 25, 5, 16), (1, 25, 6, 16)], 2),
    ]

    for shapes, axis in trials:
        outputs = []
        inputs = _get_inputs(shapes)
        for npu in [False, True]:
            model = _get_model(shapes, "uint8", axis)
            mod = tei.make_module(model, {})
            outputs.append(tei.build_and_run(mod, inputs, 1, {}, npu=npu))

        tei.verify(outputs, 0)
Exemple #22
0
def test_split_failure():
    if not ethosn_available():
        return

    trials = [
        ((1, 4, 4, 4, 4), "uint8", 4, 2,
         "dimensions=5, dimensions must be <= 4;"),
        ((1, 4, 4, 4), "int8", 4, 2,
         "dtype='int8', dtype must be either uint8 or int32;"),
        ((2, 4, 4, 4), "uint8", 4, 2, "batch size=2, batch size must = 1;"),
        ((1, 4, 4, 4), "uint8", 1, 0,
         "Split cannot be performed along batch axis (axis 0);"),
        ((1, 4, 4, 4), "uint8", 4, 3,
         "Split along the channels dimension (axis 3) requires all output sizes (specified in splitInfo.m_Sizes) to be multiples of 16;"
         ),
    ]

    for shape, dtype, splits, axis, err_msg in trials:
        model = _get_model(shape, dtype, splits, axis)
        mod = tei.make_ethosn_partition(model)
        tei.test_error(mod, {}, err_msg)
Exemple #23
0
def test_sigmoid():
    if not ethosn_available():
        return

    trials = [
        (1, 16, 16, 16),
        (1, 8, 8),
    ]

    np.random.seed(0)
    for shape in trials:
        inputs = {
            "a": tvm.nd.array(np.random.randint(0, high=255, size=shape, dtype="uint8")),
        }
        outputs = []
        for npu in [False, True]:
            model = _get_model(shape, 64, 0.02, 0, 1 / 256, "uint8")
            mod = tei.make_module(model, [])
            outputs.append(tei.build_and_run(mod, inputs, 1, {}, npu=npu))

        tei.verify(outputs, 1)
def test_depth_to_space():
    if not ethosn_available():
        return

    trials = [
        (1, 16, 16, 16),
        (1, 64, 32, 16),
    ]

    for shape in trials:
        inputs = {
            "a":
            tvm.nd.array(
                np.random.randint(0, high=255, size=shape, dtype="uint8")),
        }
        outputs = []
        for npu in [False, True]:
            model = _get_model(shape, 2, "uint8", "NHWC")
            mod = tei.make_module(model, {})
            outputs.append(tei.build_and_run(mod, inputs, 1, {}, npu=npu))

        tei.verify(outputs, 1)
Exemple #25
0
def test_relu():
    if not ethosn_available():
        return

    trials = [
        ((1, 4, 4, 4), 65, 178),
        ((1, 8, 4, 2), 1, 254),
        ((1, 16), 12, 76),
    ]

    for shape, a_min, a_max in trials:
        inputs = {
            "a":
            tvm.nd.array(
                np.random.randint(0, high=255, size=shape, dtype="uint8")),
        }
        outputs = []
        for npu in [False, True]:
            model = _get_model(inputs["a"].shape, "uint8", a_min, a_max)
            mod = tei.make_module(model, {})
            outputs.append(tei.build_and_run(mod, inputs, 1, {}, npu=npu))

        tei.verify(outputs, 1)
def test_output_tuple_propagation():
    """This tests the case where the output tuple must be inferred
    as having dummy tensor information."""
    if not ethosn_available():
        return

    def get_model():
        a = relay.var("a", shape=(1, 4, 4, 16), dtype="uint8")
        split = relay.op.split(a, indices_or_sections=4, axis=2)
        return relay.Tuple((split[0], split[1], split[2], split[3]))

    np.random.seed(0)
    outputs = []
    inputs = {
        "a":
        tvm.nd.array(
            np.random.randint(0, high=256, size=(1, 4, 4, 16), dtype="uint8"))
    }
    for npu in [False, True]:
        model = get_model()
        mod = tei.make_module(model, {})
        outputs.append(tei.build_and_run(mod, inputs, 4, {}, npu=npu))

    tei.verify(outputs, 0)
Exemple #27
0
def test_concatenate_failure():
    if not ethosn_available():
        return

    trials = [
        ([(1, 4, 4, 4, 4), (1, 4, 4, 4, 4)], "uint8", 1,
         "dimensions=5, dimensions must be <= 4;"),
        ([(1, 4, 4, 4), (1, 4, 4, 4)], "uint8", 3,
         "Concatenation along the channels dimension (axis 3) requires input tensors with a multiple of 16 channels;"
         ),
        ([(1, 4, 4, 4), (1, 4, 4, 4)], "int8", 2,
         "dtype='int8', dtype must be either uint8 or int32; dtype='int8', dtype must be either uint8 or int32;"
         ),
        ([(2, 4, 4, 4), (2, 4, 4, 4)], "uint8", 2,
         "batch size=2, batch size must = 1; batch size=2, batch size must = 1;"
         ),
        ([(1, 4, 4, 4), (1, 4, 4, 4)], "uint8", 0,
         "Concatenation cannot be performed along batch axis (axis 0);"),
    ]

    for shapes, dtype, axis, err_msg in trials:
        model = _get_model(shapes, dtype, axis)
        mod = tei.make_ethosn_partition(model)
        tei.test_error(mod, {}, err_msg)
Exemple #28
0
    graph, lib, params, dumps = tvmc.compile(
        tflite_mobilenet_v1_0_25_128,
        target="opencl",
        target_host="llvm",
        alter_layout="NCHW",
    )

    # check for output types
    assert type(graph) is str
    assert type(lib) is tvm.runtime.module.Module
    assert type(params) is dict
    assert type(dumps) is dict


@pytest.mark.skipif(
    not ethosn_available(),
    reason=
    "--target=ethos-n77 is not available. TVM built with 'USE_ETHOSN OFF'",
)
def test_compile_tflite_module_with_external_codegen(
        tflite_mobilenet_v1_1_quant):
    pytest.importorskip("tflite")

    graph, lib, params, dumps = tvmc.compile(tflite_mobilenet_v1_1_quant,
                                             target="ethos-n77, llvm",
                                             dump_code="relay")

    # check for output types
    assert type(graph) is str
    assert type(lib) is tvm.runtime.module.Module
    assert type(params) is dict
def _test_image_network(
    model_url,
    model_sub_path,
    input_dict,
    compile_hash,
    output_count,
    host_ops=0,
    npu_partitions=1,
    run=False,
):
    """Test an image network.

    Parameters
    ----------
    model_url : str
        The URL to the model.
    model_sub_path : str
        The name of the model file.
    input_dict : dict
        The input dict.
    compile_hash : str, set
        The compile hash(es) to check the compilation output against.
    output_count : int
        The expected number of outputs.
    host_ops : int
        The expected number of host operators.
    npu_partitions : int
        The expected number of Ethos-N partitions.
    run : bool
        Whether or not to try running the network. If hardware isn't
        available, the run will still take place but with a mocked
        inference function, so the results will be incorrect. This is
        therefore just to test the runtime flow is working rather than
        to check the correctness/accuracy.

    """
    if not ethosn_available():
        return

    def get_model():
        if model_url[-3:] in ("tgz", "zip"):
            model_path = tf_testing.get_workload_official(
                model_url,
                model_sub_path,
            )
        else:
            model_path = download.download_testdata(
                model_url,
                model_sub_path,
            )
        return _get_tflite_model(model_path, input_dict, "uint8")

    inputs = {}
    for input_name in input_dict:
        input_shape = input_dict[input_name]
        inputs[input_name] = tei.get_real_image(input_shape[1], input_shape[2])

    mod, params = get_model()
    m = tei.build(mod, params, npu=True, expected_host_ops=host_ops, npu_partitions=npu_partitions)
    tei.assert_lib_hash(m.get_lib(), compile_hash)
    if run:
        tei.run(m, inputs, output_count, npu=True)
Exemple #30
0
def test_pooling_failure():
    if not ethosn_available():
        return

    trials = [
        (
            (2, 8, 8, 8),
            relay.nn.max_pool2d,
            (2, 2),
            (2, 2),
            (0, 0, 0, 0),
            "NHWC",
            "uint8",
            "batch size=2, batch size must = 1",
        ),
        (
            (1, 8, 8, 8),
            relay.nn.max_pool2d,
            (2, 2),
            (2, 2),
            (0, 0, 0, 0),
            "NHWC",
            "int8",
            "dtype='int8', dtype must be either uint8 or int32",
        ),
        (
            (1, 8, 8, 8),
            relay.nn.max_pool2d,
            (2, 2),
            (2, 2),
            (0, 0, 0, 0),
            "NCHW",
            "uint8",
            "data format=NCHW, data format must = NHWC",
        ),
        (
            (1, 8, 8, 8),
            relay.nn.max_pool2d,
            (2, 2),
            (2, 2, 2),
            (0, 0, 0, 0),
            "NHWC",
            "uint8",
            "stride size=3, stride size must = 2",
        ),
        (
            (1, 8, 8, 8),
            relay.nn.max_pool2d,
            (2, 2, 2),
            (2, 2),
            (0, 0, 0, 0),
            "NHWC",
            "uint8",
            "dimensions=3, dimensions must = 2",
        ),
    ]

    for shape, typef, size, stride, pad, layout, dtype, err_msg in trials:
        model = _get_model(shape, typef, size, stride, pad, layout, dtype)
        mod = tei.make_ethosn_partition(model)
        tei.test_error(mod, {}, err_msg)