Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add TVMC Frontend for PaddlePaddle #9083

Merged
merged 48 commits into from
Oct 6, 2021
Merged
Show file tree
Hide file tree
Changes from 47 commits
Commits
Show all changes
48 commits
Select commit Hold shift + click to select a range
5b39c79
Merge pull request #2 from apache/main
jiangjiajun Aug 3, 2021
22a20be
fix some problems for matmul
Aug 3, 2021
1a7f180
fix some problems for matmul
Aug 3, 2021
3f604e9
add alpha parameter for matmul
Aug 4, 2021
fe6de07
remove unnecessary condition
Aug 4, 2021
dfb9cb1
add TranslatedLayer which support model loaded by jit.load
Aug 4, 2021
36ab16e
add mul operator support
Aug 5, 2021
63b0138
Add padding mode support for conv/pool2d
wjj19950828 Aug 5, 2021
dbfa687
Merge branch 'paddle_frontend' into add_paddingmode_support
wjj19950828 Aug 5, 2021
1967d46
support 4 two-tuples
wjj19950828 Aug 5, 2021
360989b
Merge branch 'add_paddingmode_support' of https://github.com/wjj19950…
wjj19950828 Aug 5, 2021
f4932bf
add paddle test case
heliqi Aug 5, 2021
0c92955
add paddle conv2d case
heliqi Aug 5, 2021
1e85fc0
Merge pull request #4 from heliqi/paddle_frontend
jiangjiajun Aug 6, 2021
b0b8094
update test_forward.py
Aug 6, 2021
35fccb2
fix paddle convert_matmul
heliqi Aug 6, 2021
094f44e
add paddle multiply and matmul op test case
heliqi Aug 6, 2021
2b0a14c
Merge pull request #5 from heliqi/paddle_frontend
jiangjiajun Aug 6, 2021
9df2340
Merge pull request #3 from wjj19950828/add_paddingmode_support
jiangjiajun Aug 10, 2021
4520515
add test case and fix bug
heliqi Aug 11, 2021
1d599c1
delete import pandas
heliqi Aug 11, 2021
75ef19b
add paddlepaddle tests
heliqi Aug 13, 2021
67ca20d
modify the variable name of convert_reshape
heliqi Aug 13, 2021
b31fa57
Merge pull request #6 from heliqi/paddle_frontend
jiangjiajun Aug 13, 2021
6f91fc5
formatting
heliqi Aug 13, 2021
a0aee15
formatting
heliqi Aug 13, 2021
544dfde
Merge pull request #7 from heliqi/paddle_frontend
jiangjiajun Aug 13, 2021
80d308a
use black to format python code
Aug 13, 2021
202893c
pylint check
heliqi Aug 17, 2021
ad758c8
Merge pull request #10 from heliqi/paddle_frontend
jiangjiajun Aug 17, 2021
a281d60
Remove fluid api
jiangjiajun Aug 18, 2021
c2d4bf5
Merge pull request #11 from jiangjiajun/jason
jiangjiajun Aug 18, 2021
be0e04e
black format
heliqi Aug 18, 2021
2a82fdb
Merge pull request #12 from heliqi/paddle_frontend
jiangjiajun Aug 18, 2021
96f8ad3
Merge branch 'upstream-main' into paddle_frontend
junrushao Aug 23, 2021
b58108d
Merge remote-tracking branch 'upstream/main' into paddle_frontend
junrushao Aug 26, 2021
87ad400
Merge pull request #14 from apache/main
jiangjiajun Aug 30, 2021
a487ccd
Add Paddle Frontend for TVMC
jiangjiajun Aug 30, 2021
938c22e
Merge branch 'apache:main' into paddle_tvmc_frontend
jiangjiajun Sep 22, 2021
3a4e10f
refine code format
jiangjiajun Sep 23, 2021
a5859cc
add test case for tvmc
heliqi Sep 27, 2021
6188344
Merge pull request #53 from heliqi/paddle_tvmc_frontend
jiangjiajun Sep 27, 2021
745f72d
fix pylint check
heliqi Sep 28, 2021
2be1f9b
Merge pull request #54 from heliqi/paddle_tvmc_frontend
jiangjiajun Sep 28, 2021
d51d606
Merge branch 'apache:main' into paddle_tvmc_frontend
jiangjiajun Sep 28, 2021
13e545d
gen_requirements add paddlepaddle
heliqi Sep 28, 2021
5e314a3
Merge pull request #56 from heliqi/paddle_tvmc_frontend
jiangjiajun Sep 29, 2021
f21f45e
Trigger CI
jiangjiajun Oct 5, 2021
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions python/gen_requirements.py
Original file line number Diff line number Diff line change
Expand Up @@ -146,6 +146,7 @@
"future", # Hidden dependency of torch.
"onnx",
"onnxruntime",
"paddlepaddle",
"tensorflow",
"tflite",
"torch",
Expand Down
26 changes: 26 additions & 0 deletions python/tvm/driver/tvmc/frontends.py
Original file line number Diff line number Diff line change
Expand Up @@ -265,12 +265,38 @@ def load(self, path, shape_dict=None, **kwargs):
return relay.frontend.from_pytorch(traced_model, input_shapes, **kwargs)


class PaddleFrontend(Frontend):
"""PaddlePaddle frontend for TVMC"""

@staticmethod
def name():
return "paddle"

@staticmethod
def suffixes():
return ["pdmodel", "pdiparams"]

def load(self, path, shape_dict=None, **kwargs):
# pylint: disable=C0415
import paddle

paddle.enable_static()
paddle.disable_signal_handler()

# pylint: disable=E1101
exe = paddle.static.Executor(paddle.CPUPlace())
prog, _, _ = paddle.static.load_inference_model(path, exe)

return relay.frontend.from_paddle(prog, shape_dict=shape_dict, **kwargs)


ALL_FRONTENDS = [
KerasFrontend,
OnnxFrontend,
TensorflowFrontend,
TFLiteFrontend,
PyTorchFrontend,
PaddleFrontend,
]


Expand Down
14 changes: 13 additions & 1 deletion tests/python/driver/tvmc/conftest.py
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ def download_and_untar(model_url, model_sub_path, temp_dir):
model_tar_name = os.path.basename(model_url)
model_path = download_testdata(model_url, model_tar_name, module=["tvmc"])

if model_path.endswith("tgz") or model_path.endswith("gz"):
if model_path.endswith("tgz") or model_path.endswith("gz") or model_path.endswith("tar"):
tar = tarfile.open(model_path)
tar.extractall(path=temp_dir)
tar.close()
Expand Down Expand Up @@ -137,6 +137,18 @@ def onnx_resnet50():
return model_file


@pytest.fixture(scope="session")
def paddle_resnet50(tmpdir_factory):
base_url = "https://bj.bcebos.com/x2paddle/models"
model_url = "paddle_resnet50.tar"
model_file = download_and_untar(
"{}/{}".format(base_url, model_url),
"paddle_resnet50/model",
temp_dir=tmpdir_factory.mktemp("data"),
)
return model_file


@pytest.fixture(scope="session")
def onnx_mnist():
base_url = "https://github.com/onnx/models/raw/master/vision/classification/mnist/model"
Expand Down
78 changes: 78 additions & 0 deletions tests/python/driver/tvmc/test_compiler.py
Original file line number Diff line number Diff line change
Expand Up @@ -273,6 +273,84 @@ def test_cross_compile_options_aarch64_onnx_module(onnx_resnet50):
assert os.path.exists(dumps_path)


def verify_compile_paddle_module(model, shape_dict=None):
pytest.importorskip("paddle")
tvmc_model = tvmc.load(model, "paddle", shape_dict=shape_dict)
tvmc_package = tvmc.compile(tvmc_model, target="llvm", dump_code="ll", desired_layout="NCHW")
dumps_path = tvmc_package.package_path + ".ll"

# check for output types
assert type(tvmc_package) is TVMCPackage
assert type(tvmc_package.graph) is str
assert type(tvmc_package.lib_path) is str
assert type(tvmc_package.params) is bytearray
assert os.path.exists(dumps_path)


def test_compile_paddle_module(paddle_resnet50):
# some CI environments wont offer Paddle, so skip in case it is not present
pytest.importorskip("paddle")
# Check default compilation.
verify_compile_paddle_module(paddle_resnet50)
# Check with manual shape override
shape_string = "inputs:[1,3,224,224]"
shape_dict = tvmc.common.parse_shape_string(shape_string)
verify_compile_paddle_module(paddle_resnet50, shape_dict)


# This test will be skipped if the AArch64 cross-compilation toolchain is not installed.
@pytest.mark.skipif(
not shutil.which("aarch64-linux-gnu-gcc"), reason="cross-compilation toolchain not installed"
)
def test_cross_compile_aarch64_paddle_module(paddle_resnet50):
# some CI environments wont offer paddle, so skip in case it is not present
pytest.importorskip("paddle")

tvmc_model = tvmc.load(paddle_resnet50, "paddle")
tvmc_package = tvmc.compile(
tvmc_model,
target="llvm -device=arm_cpu -mtriple=aarch64-linux-gnu -mattr=+neon",
dump_code="asm",
cross="aarch64-linux-gnu-gcc",
)
dumps_path = tvmc_package.package_path + ".asm"

# check for output types
assert type(tvmc_package) is TVMCPackage
assert type(tvmc_package.graph) is str
assert type(tvmc_package.lib_path) is str
assert type(tvmc_package.params) is bytearray
assert os.path.exists(dumps_path)


# This test will be skipped if the AArch64 cross-compilation toolchain is not installed.
@pytest.mark.skipif(
not shutil.which("aarch64-linux-gnu-gcc"), reason="cross-compilation toolchain not installed"
)
def test_cross_compile_options_aarch64_paddle_module(paddle_resnet50):
# some CI environments wont offer paddle, so skip in case it is not present
pytest.importorskip("paddle")

fake_sysroot_dir = utils.tempdir().relpath("")

tvmc_model = tvmc.load(paddle_resnet50, "paddle")
tvmc_package = tvmc.compile(
tvmc_model,
target="llvm -device=arm_cpu -mtriple=aarch64-linux-gnu -mattr=+neon",
dump_code="asm",
cross="aarch64-linux-gnu-gcc",
cross_options="--sysroot=" + fake_sysroot_dir,
)
dumps_path = tvmc_package.package_path + ".asm"

# check for output types
assert type(tvmc_package) is TVMCPackage
assert type(tvmc_package.graph) is str
assert type(tvmc_package.lib_path) is str
assert type(tvmc_package.params) is bytearray
assert os.path.exists(dumps_path)


@tvm.testing.requires_opencl
def test_compile_opencl(tflite_mobilenet_v1_0_25_128):
pytest.importorskip("tflite")
Expand Down
18 changes: 18 additions & 0 deletions tests/python/driver/tvmc/test_frontends.py
Original file line number Diff line number Diff line change
Expand Up @@ -84,6 +84,14 @@ def test_guess_frontend_tensorflow():
assert type(sut) is tvmc.frontends.TensorflowFrontend


def test_guess_frontend_paddle():
# some CI environments wont offer Paddle, so skip in case it is not present
pytest.importorskip("paddle")

sut = tvmc.frontends.guess_frontend("a_model.pdmodel")
assert type(sut) is tvmc.frontends.PaddleFrontend


def test_guess_frontend_invalid():
with pytest.raises(TVMCException):
tvmc.frontends.guess_frontend("not/a/file.txt")
Expand Down Expand Up @@ -161,6 +169,16 @@ def test_load_model__pb(pb_mobilenet_v1_1_quant):
assert "MobilenetV1/Conv2d_0/weights" in tvmc_model.params.keys()


def test_load_model__paddle(paddle_resnet50):
# some CI environments wont offer Paddle, so skip in case it is not present
pytest.importorskip("paddle")

tvmc_model = tvmc.load(paddle_resnet50, model_format="paddle")
assert type(tvmc_model) is TVMCModel
assert type(tvmc_model.mod) is IRModule
assert type(tvmc_model.params) is dict


def test_load_model___wrong_language__to_keras(tflite_mobilenet_v1_1_quant):
# some CI environments wont offer TensorFlow/Keras, so skip in case it is not present
pytest.importorskip("tensorflow")
Expand Down
25 changes: 25 additions & 0 deletions tests/python/driver/tvmc/test_tvmc_common.py
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,31 @@ def _is_layout_transform(node):
assert any(layout_transform_calls), "Expected 'layout_transform NCWH->NHWC' not found"


def test_compile_paddle_module_nchw_to_nhwc(paddle_resnet50):
# some CI environments wont offer Paddle, so skip in case it is not present
pytest.importorskip("paddle")

tvmc_model = tvmc.frontends.load_model(paddle_resnet50, "paddle")
before = tvmc_model.mod

expected_layout = "NHWC"
after = tvmc.common.convert_graph_layout(before, expected_layout)

layout_transform_calls = []

def _is_layout_transform(node):
if isinstance(node, tvm.relay.expr.Call):
layout_transform_calls.append(
node.op.name == "layout_transform"
and node.attrs.src_layout == "NCHW"
and node.attrs.dst_layout == "NHWC"
)

tvm.relay.analysis.post_order_visit(after["main"], _is_layout_transform)

assert any(layout_transform_calls), "Expected 'layout_transform NCWH->NHWC' not found"


def test_compile_tflite_module__same_layout__nhwc_to_nhwc(tflite_mobilenet_v1_1_quant):
# some CI environments wont offer TFLite, so skip in case it is not present
pytest.importorskip("tflite")
Expand Down