Skip to content

Commit

Permalink
[BYOC][ACL] Prevent dilated pooling (apache#8149)
Browse files Browse the repository at this point in the history
* [BYOC][ACL] Prevent dilated pooling

 Added check preventing avg_pool2d and max_pool2d to be
scheduled for execution via ACL* runtime if dilation other
than (1, 1) is provided as ACL does not currently support
dilation attribute in pooling layer.

*ACL stands for "Compute Library for the Arm® Architecture"

Change-Id: If8f65d3a154e09f880bec73dd756d9f985a20ff2

* linter

Change-Id: If91809350786e69f59596301e0cbd3def6815cd0
  • Loading branch information
d-smirnov authored and Trevor Morris committed Jun 17, 2021
1 parent 230796a commit 361f49a
Show file tree
Hide file tree
Showing 3 changed files with 72 additions and 39 deletions.
12 changes: 10 additions & 2 deletions python/tvm/relay/op/contrib/arm_compute_lib.py
Original file line number Diff line number Diff line change
Expand Up @@ -397,6 +397,14 @@ def qnn_dense(expr):
return True


def check_dilation(attrs):
"""Prevents offloading if dilation other than (1, 1)"""
if not isinstance(attrs, relay.op.op_attrs.GlobalPool2DAttrs):
if not (len(attrs.dilation) == 2 and attrs.dilation[0] == 1 and attrs.dilation[1] == 1):
return False
return True


@tvm.ir.register_op_attr("nn.max_pool2d", "target.arm_compute_lib")
def max_pool2d(expr):
"""Check if the external ACL codegen for maxpool2d should be used."""
Expand All @@ -406,7 +414,7 @@ def max_pool2d(expr):
typ = args[0].checked_type
if typ.dtype not in ["float32", "uint8"]:
return False
return True
return check_dilation(attrs)


@tvm.ir.register_op_attr("nn.avg_pool2d", "target.arm_compute_lib")
Expand All @@ -424,7 +432,7 @@ def avg_pool2d(expr, from_quantized_composite=False):
if attrs.layout != "NHWC":
return False

return True
return check_dilation(attrs)


@tvm.ir.register_op_attr("nn.global_max_pool2d", "target.arm_compute_lib")
Expand Down
4 changes: 3 additions & 1 deletion src/runtime/contrib/arm_compute_lib/acl_runtime.cc
Original file line number Diff line number Diff line change
Expand Up @@ -381,9 +381,9 @@ class ACLRuntime : public JSONRuntimeBase {
void CreatePoolingLayer(CachedLayer* layer, const JSONGraphNode& node) {
std::vector<std::string> padding = node.GetAttr<std::vector<std::string>>("padding");
std::vector<std::string> strides = node.GetAttr<std::vector<std::string>>("strides");
std::vector<std::string> dilation = node.GetAttr<std::vector<std::string>>("dilation");
bool ceil_mode = std::stoi(node.GetAttr<std::vector<std::string>>("ceil_mode")[0]);
arm_compute::PadStrideInfo pad_stride_info = MakeACLPadStride(padding, strides, ceil_mode);

auto attr_pool_size = node.GetAttr<std::vector<std::string>>("pool_size");
int pool_size_h = std::stoi(attr_pool_size[0]);
int pool_size_w = std::stoi(attr_pool_size[1]);
Expand All @@ -408,6 +408,8 @@ class ACLRuntime : public JSONRuntimeBase {
LOG(FATAL) << "Pooling type not supported";
}

ICHECK(dilation.size() == 2 && dilation[0] == "1" && dilation[1] == "1")
<< "Dilation other than (1, 1) not supported";
arm_compute::PoolingLayerInfo pool_info =
arm_compute::PoolingLayerInfo(pool_type, arm_compute::Size2D(pool_size_h, pool_size_w),
arm_compute::DataLayout::NHWC, pad_stride_info, exclude_pad);
Expand Down
95 changes: 59 additions & 36 deletions tests/python/contrib/test_arm_compute_lib/test_pooling.py
Original file line number Diff line number Diff line change
Expand Up @@ -169,34 +169,37 @@ def test_pooling():

fp32_dtype = ("float32", -127, 128, 0.001, 0.001)
uint8_dtype = ("uint8", 0, 255, 1, 0)

# fmt: off
trials = [
["nn.max_pool2d", fp32_dtype, (3, 3), (2, 2), (0, 0), False, False, (27, 27, 512)],
["nn.max_pool2d", fp32_dtype, (2, 2), (2, 2), (0, 0), False, True, (16, 16, 16)],
["nn.max_pool2d", fp32_dtype, (3, 3), (2, 2), (1, 1), True, True, (15, 15, 16)],
["nn.max_pool2d", fp32_dtype, (2, 2), (2, 2), (0, 1), False, False, (16, 16, 16)],
["nn.max_pool2d", uint8_dtype, (3, 3), (2, 2), (0, 1), False, False, (16, 16, 16)],
["nn.max_pool2d", uint8_dtype, (2, 2), (2, 2), (1, 1), True, True, (15, 15, 16)],
["nn.avg_pool2d", fp32_dtype, (2, 2), (2, 2), (1, 1), False, False, (16, 16, 16)],
["nn.avg_pool2d", fp32_dtype, (2, 2), (2, 2), (0, 0), False, True, (16, 16, 16)],
["nn.avg_pool2d", fp32_dtype, (3, 3), (2, 2), (0, 1), True, False, (15, 15, 16)],
["nn.max_pool2d", fp32_dtype, (3, 3), (2, 2), (1, 1), (0, 0), False, False, (27, 27, 512), (0, 1),],
["nn.max_pool2d", fp32_dtype, (2, 2), (2, 2), (1, 1), (0, 0), False, True, (16, 16, 16), (0, 1),],
["nn.max_pool2d", fp32_dtype, (3, 3), (2, 2), (1, 1), (1, 1), True, True, (15, 15, 16), (0, 1),],
["nn.max_pool2d", fp32_dtype, (2, 2), (2, 2), (1, 1), (0, 1), False, False, (16, 16, 16), (0, 1),],
["nn.max_pool2d", uint8_dtype, (3, 3), (2, 2), (1, 1), (0, 1), False, False, (16, 16, 16), (0, 1),],
["nn.max_pool2d", uint8_dtype, (2, 2), (2, 2), (1, 1), (1, 1), True, True, (15, 15, 16), (0, 1),],
["nn.max_pool2d", uint8_dtype, (2, 2), (2, 2), (3, 2), (1, 1), True, True, (15, 15, 16), (1, 0),],
["nn.avg_pool2d", fp32_dtype, (2, 2), (2, 2), (1, 1), (1, 1), False, False, (16, 16, 16), (0, 1),],
["nn.avg_pool2d", fp32_dtype, (2, 2), (2, 2), (1, 1), (0, 0), False, True, (16, 16, 16), (0, 1),],
["nn.avg_pool2d", fp32_dtype, (3, 3), (2, 2), (3, 2), (0, 1), True, False, (15, 15, 16), (1, 0),],
# 20.05: "exclude_padding equal false is not supported for AVG Pooling with padding on quantized types"
# ["nn.avg_pool2d", uint8_dtype, (2, 2), (2, 2), (1, 1), False, True, (16, 16, 16)],
["nn.avg_pool2d", uint8_dtype, (3, 3), (2, 2), (0, 1), False, False, (16, 16, 16)],
["nn.l2_pool2d", fp32_dtype, (2, 2), (2, 2), (0, 1), True, False, (16, 16, 16)],
["nn.l2_pool2d", fp32_dtype, (3, 3), (2, 2), (0, 0), False, False, (16, 16, 16)],
["nn.l2_pool2d", fp32_dtype, (2, 2), (2, 2), (1, 1), False, True, (15, 15, 16)],
["nn.avg_pool2d", uint8_dtype, (3, 3), (2, 2), (1, 1), (0, 1), False, False, (16, 16, 16), (0, 1),],
["nn.l2_pool2d", fp32_dtype, (2, 2), (2, 2), (1, 1), (0, 1), True, False, (16, 16, 16), (0, 1),],
["nn.l2_pool2d", fp32_dtype, (3, 3), (2, 2), (1, 1), (0, 0), False, False, (16, 16, 16), (0, 1),],
["nn.l2_pool2d", fp32_dtype, (2, 2), (2, 2), (1, 1), (1, 1), False, True, (15, 15, 16), (0, 1),],
]

# fmt: on
for (
typef,
(dtype, low, high, atol, rtol),
size,
stride,
dilation,
pad,
ceil_mode,
count_include_pad,
input_shape,
(tvm_ops, acl_partitions),
) in trials:
shape = (1, *input_shape)
outputs = []
Expand All @@ -205,7 +208,16 @@ def test_pooling():
}

func = _get_pooling_model(
shape, dtype, typef, size, stride, pad, ceil_mode, count_include_pad, iter(inputs)
shape,
dtype,
typef,
size,
stride,
dilation,
pad,
ceil_mode,
count_include_pad,
iter(inputs),
)

config = {
Expand All @@ -215,15 +227,25 @@ def test_pooling():
"pooling type": typef,
"dtype": dtype,
"padding": pad,
"dilation": dilation,
"ceil_mode": ceil_mode,
"count_include_pad": count_include_pad,
"inputs": inputs,
}
verify_saturation = True if dtype == "uint8" else False

for acl in [False, True]:
outputs.append(
build_and_run(func, inputs, 1, None, device, enable_acl=acl, config=config)[0]
build_and_run(
func,
inputs,
1,
None,
device,
enable_acl=acl,
tvm_ops=tvm_ops,
acl_partitions=acl_partitions,
config=config,
)[0]
)

verify(outputs, atol=atol, rtol=rtol, config=config, verify_saturation=verify_saturation)
Expand Down Expand Up @@ -283,25 +305,25 @@ def test_codegen_pooling():

fp32_dtype = ("float32", -127, 128)
uint8_dtype = ("uint8", 0, 255)

# fmt: off
trials = [
["nn.max_pool2d", fp32_dtype, (2, 2), (2, 2), (1, 1), (0, 0), False, True, (16, 16, 16)],
["nn.max_pool2d", fp32_dtype, (3, 3), (2, 2), (1, 1), (1, 1), True, True, (15, 15, 16)],
["nn.max_pool2d", fp32_dtype, (2, 2), (2, 2), (1, 1), (0, 1), False, False, (16, 16, 16)],
["nn.max_pool2d", uint8_dtype, (3, 3), (2, 2), (1, 1), (0, 1), False, False, (16, 16, 16)],
["nn.max_pool2d", uint8_dtype, (2, 2), (2, 2), (1, 1), (1, 1), True, True, (15, 15, 16)],
["nn.max_pool2d", uint8_dtype, (2, 2), (2, 2), (3, 2), (1, 1), True, True, (15, 15, 16)],
["nn.avg_pool2d", fp32_dtype, (2, 2), (2, 2), (1, 1), (1, 1), False, False, (16, 16, 16)],
["nn.avg_pool2d", fp32_dtype, (2, 2), (2, 2), (1, 1), (1, 1), False, False, (16, 16, 16)],
["nn.avg_pool2d", fp32_dtype, (2, 2), (2, 2), (1, 1), (0, 0), False, True, (16, 16, 16)],
["nn.avg_pool2d", fp32_dtype, (3, 3), (2, 2), (3, 2), (0, 1), True, False, (15, 15, 16)],
["nn.avg_pool2d", uint8_dtype, (2, 2), (2, 2), (1, 1), (1, 1), False, True, (16, 16, 16)],
["nn.avg_pool2d", uint8_dtype, (3, 3), (2, 2), (1, 1), (0, 1), False, False, (16, 16, 16)],
["nn.l2_pool2d", fp32_dtype, (2, 2), (2, 2), (1, 1), (0, 1), True, False, (15, 15, 16)],
["nn.l2_pool2d", fp32_dtype, (3, 3), (2, 2), (1, 1), (0, 0), False, False, (16, 16, 16)],
["nn.l2_pool2d", fp32_dtype, (2, 2), (2, 2), (1, 1), (1, 1), False, True, (15, 15, 16)],
["nn.max_pool2d", fp32_dtype, (2, 2), (2, 2), (1, 1), (0, 0), False, True, (16, 16, 16), (0, 1),],
["nn.max_pool2d", fp32_dtype, (3, 3), (2, 2), (1, 1), (1, 1), True, True, (15, 15, 16), (0, 1),],
["nn.max_pool2d", fp32_dtype, (2, 2), (2, 2), (1, 1), (0, 1), False, False, (16, 16, 16), (0, 1),],
["nn.max_pool2d", uint8_dtype, (3, 3), (2, 2), (1, 1), (0, 1), False, False, (16, 16, 16), (0, 1),],
["nn.max_pool2d", uint8_dtype, (2, 2), (2, 2), (1, 1), (1, 1), True, True, (15, 15, 16), (0, 1),],
["nn.max_pool2d", uint8_dtype, (2, 2), (2, 2), (3, 2), (1, 1), True, True, (15, 15, 16), (1, 0),],
["nn.avg_pool2d", fp32_dtype, (2, 2), (2, 2), (1, 1), (1, 1), False, False, (16, 16, 16), (0, 1),],
["nn.avg_pool2d", fp32_dtype, (2, 2), (2, 2), (1, 1), (1, 1), False, False, (16, 16, 16), (0, 1),],
["nn.avg_pool2d", fp32_dtype, (2, 2), (2, 2), (1, 1), (0, 0), False, True, (16, 16, 16), (0, 1),],
["nn.avg_pool2d", fp32_dtype, (3, 3), (2, 2), (3, 2), (0, 1), True, False, (15, 15, 16), (1, 0),],
["nn.avg_pool2d", uint8_dtype, (2, 2), (2, 2), (1, 1), (1, 1), False, True, (16, 16, 16), (0, 1),],
["nn.avg_pool2d", uint8_dtype, (3, 3), (2, 2), (1, 1), (0, 1), False, False, (16, 16, 16), (0, 1),],
["nn.l2_pool2d", fp32_dtype, (2, 2), (2, 2), (1, 1), (0, 1), True, False, (15, 15, 16), (0, 1),],
["nn.l2_pool2d", fp32_dtype, (3, 3), (2, 2), (1, 1), (0, 0), False, False, (16, 16, 16), (0, 1),],
["nn.l2_pool2d", fp32_dtype, (2, 2), (2, 2), (1, 1), (1, 1), False, True, (15, 15, 16), (0, 1),],
]

# fmt: on
for (
typef,
(dtype, low, high),
Expand All @@ -312,14 +334,15 @@ def test_codegen_pooling():
ceil_mode,
count_include_pad,
input_shape,
(tvm_ops, acl_partitions),
) in trials:
shape = (1, *input_shape)
inputs = {"a"}
args = (shape, dtype, typef, size, stride, dilation, pad, False, False)
func = _get_pooling_model(*args, iter(inputs))
exp_codegen = _get_expected_pooling_codegen(*args)

verify_codegen(func, exp_codegen, 1)
verify_codegen(func, exp_codegen, acl_partitions, tvm_ops)


def test_codegen_global_pooling():
Expand Down

0 comments on commit 361f49a

Please sign in to comment.