Skip to content

Commit

Permalink
use fixed_point_multiply to define fraction_size
Browse files Browse the repository at this point in the history
  • Loading branch information
Aleksei-grovety committed Feb 13, 2024
1 parent 0c030c2 commit 5e9e432
Show file tree
Hide file tree
Showing 5 changed files with 27 additions and 42 deletions.
13 changes: 0 additions & 13 deletions python/tvm/relay/backend/contrib/ethosu/util.py
Original file line number Diff line number Diff line change
Expand Up @@ -264,19 +264,6 @@ def is_copying_constants_disabled() -> bool:
return bool(compiler_attrs.disable_copying_constants)


def is_fixed_point_enabled() -> bool:
"""Determine whether calculation with fixed point is enabled"""
compiler_attrs = tvm.get_global_func("relay.ext.ethos-u.get_compiler_attrs")()
return bool(compiler_attrs.enable_fixed_point)


def get_fixed_point_fraction_size() -> int:
"""Function to get the number of bits used to
represent the fractional part of a fixed point number"""
compiler_attrs = tvm.get_global_func("relay.ext.ethos-u.get_compiler_attrs")()
return int(compiler_attrs.fixed_point_fraction_size)


def is_striping_enabled() -> bool:
"""Determine whether the cascader is enabled"""
compiler_attrs = tvm.get_global_func("relay.ext.ethos-u.get_compiler_attrs")()
Expand Down
23 changes: 16 additions & 7 deletions python/tvm/relay/op/contrib/ethosu.py
Original file line number Diff line number Diff line change
Expand Up @@ -1948,28 +1948,31 @@ class MatMulFixedPointParams:

@requires_vela
def __init__(self, func_body):
from tvm.relay.backend.contrib.ethosu.util import QDenseArgs, get_fixed_point_fraction_size
from tvm.relay.backend.contrib.ethosu.util import QDenseArgs

self.fraction_size = get_fixed_point_fraction_size()
dense_fixed_point = func_body.args[0]
dense = dense_fixed_point.args[0]
# fixed_point_multiply relay operation uses multiplier with 31 fractional bits
# so to determine the size of the fraction use the formula: 31 - shift
self.fraction_size = 31 - dense_fixed_point.attrs.shift
fract_scale = tvm.relay.Constant(tvm.nd.array(np.array(1 / 2**self.fraction_size)))
fract_zero_point = tvm.relay.Constant(tvm.nd.array(np.array(0, dtype="int32")))
dense = func_body

self.activation = None
self.weights = TensorParams(
dense.args[QDenseArgs.WEIGHTS.value],
dense.args[QDenseArgs.WEIGHTS.value].args[0].args[0],
None,
fract_scale,
fract_zero_point,
)
self.ifm = TensorParams(
dense.args[QDenseArgs.IFM.value],
dense.args[QDenseArgs.IFM.value].args[0].args[0],
None,
fract_scale,
fract_zero_point,
)
self.ofm = TensorParams(
dense,
func_body,
None,
fract_scale,
fract_zero_point,
Expand All @@ -1995,7 +1998,13 @@ def is_valid(self) -> bool:


def matmul_fixed_point_pattern():
return is_op("nn.dense")(wildcard(), wildcard())
ifm = is_op("cast")(wildcard())
ifm2 = is_op("cast")(wildcard())
ifm = is_op("fixed_point_multiply")(ifm)
ifm2 = is_op("fixed_point_multiply")(ifm2)
dense = is_op("nn.dense")(ifm, ifm2)
dense = is_op("fixed_point_multiply")(dense)
return is_op("cast")(dense)


class HardSwishParams:
Expand Down
6 changes: 0 additions & 6 deletions src/relay/backend/contrib/ethosu/compiler_attrs.cc
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,6 @@ struct EthosUCompilerConfigNode : public tvm::AttrsNode<EthosUCompilerConfigNode
Bool enable_cascader = Bool(false);
Bool enable_striping = Bool(false);
Bool disable_copying_constants = Bool(false);
Integer fixed_point_fraction_size = Integer(0);
String dev_force_block_config;
String dev_max_open_plans;
String dev_max_closed_plans;
Expand Down Expand Up @@ -73,11 +72,6 @@ struct EthosUCompilerConfigNode : public tvm::AttrsNode<EthosUCompilerConfigNode
"the linker script for section \".rodata.tvm\" that the constants are located in SRAM)")
.set_default(Bool(false));
String dev_warning = "Option is intended for development and debugging purposes only. ";
TVM_ATTR_FIELD(fixed_point_fraction_size)
.describe(
"Fraction size refers to the number of bits used to represent the fractional part of a "
"fixed point number for non-quantized int16 operations")
.set_default(Integer(0));
TVM_ATTR_FIELD(dev_force_block_config)
.describe((dev_warning + String("Force the block config to a given value; format = "
"\"[BLK_HEIGHT]x[BLK_WIDTH]x[BLK_DEPTH]\""))
Expand Down
4 changes: 0 additions & 4 deletions tests/python/contrib/test_ethosu/infra.py
Original file line number Diff line number Diff line change
Expand Up @@ -124,7 +124,6 @@ def create_test_runner(
enable_cascader=False,
enable_striping=False,
workspace_pools=None,
fixed_point_fraction_size=0,
):

file_dir = os.path.dirname(os.path.abspath(__file__))
Expand Down Expand Up @@ -169,7 +168,6 @@ def create_test_runner(
"accelerator_config": accel,
"enable_cascader": enable_cascader,
"enable_striping": enable_striping,
"fixed_point_fraction_size": fixed_point_fraction_size,
},
"tir.usmp.enable": enable_usmp,
"tir.usmp.algorithm": "hill_climb",
Expand Down Expand Up @@ -335,7 +333,6 @@ def compare_ethosu_with_reference(
output_tolerance=0,
print_cmm=False,
enable_cascader=None,
fixed_point_fraction_size=0,
):
if enable_cascader is None:
enable_cascader = "u65" not in accel_type
Expand All @@ -362,7 +359,6 @@ def compare_ethosu_with_reference(
enable_cascader=enable_cascader,
enable_striping=False,
workspace_pools=workspace_pools,
fixed_point_fraction_size=fixed_point_fraction_size,
)
compiled_models = build_source(
mod,
Expand Down
23 changes: 11 additions & 12 deletions tests/python/contrib/test_ethosu/test_codegen.py
Original file line number Diff line number Diff line change
Expand Up @@ -1637,42 +1637,41 @@ def test_ethosu_matmul_fixed_point(accel_type, ifm_shape, ofm_channels, fract_si
def create_model():
ifm = relay.var("ifm", shape=ifm_shape, dtype=dtype)
ifm2 = relay.var("ifm2", shape=weights_shape, dtype=dtype)
dense = relay.nn.dense(ifm, ifm2)
ifm_fixed_point = relay.cast(ifm, "int32")
ifm2_fixed_point = relay.cast(ifm2, "int32")
ifm_fixed_point = relay.fixed_point_multiply(ifm_fixed_point, 2**31 - 1, 0)
ifm2_fixed_point = relay.fixed_point_multiply(ifm2_fixed_point, 2**31 - 1, 0)
dense = relay.nn.dense(ifm_fixed_point, ifm2_fixed_point)
dense = relay.fixed_point_multiply(dense, 1, 16)
dense = relay.cast(dense, dtype)
return tvm.IRModule.from_expr(relay.Function([ifm, ifm2], dense))

def generate_ref(input_data, weights):
return np.matmul(input_data, np.transpose(weights))

def convert_to_fixed_point(arr, fract_size):
fract_fact = 0b1 << fract_size
return np.array(arr * fract_fact, dtype=np.int16)

cpu_mod = create_model()
ethosu_mod = partition_for_ethosu(cpu_mod)

input_data = {
"ifm": np.random.uniform(-0.5, 0.5, size=ifm_shape),
"ifm2": np.random.uniform(-0.5, 0.5, size=weights_shape),
}
output_data = generate_ref(input_data["ifm"], input_data["ifm2"])

input_data = {
"ifm": convert_to_fixed_point(input_data["ifm"], fract_size),
"ifm2": convert_to_fixed_point(input_data["ifm2"], fract_size),
}
output_data = {"output": convert_to_fixed_point(output_data, fract_size)}
output_data = generate_ref_data(cpu_mod, input_data)
output_data = {"output": output_data["output"].astype("int16")}
tolerance = convert_to_fixed_point(tolerance, fract_size)

config = {"fixed_point_fraction_size": fract_size}
with tvm.transform.PassContext(config={"relay.ext.ethos-u.options": config}):
ethosu_mod = partition_for_ethosu(cpu_mod)

infra.compare_ethosu_with_reference(
ethosu_mod,
input_data,
output_data,
accel_type,
enable_cascader=False,
output_tolerance=tolerance,
fixed_point_fraction_size=fract_size,
)


Expand Down

0 comments on commit 5e9e432

Please sign in to comment.