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

[Torch] Add initial control flow support #4964

Merged
merged 15 commits into from
Mar 10, 2020

Conversation

masahi
Copy link
Member

@masahi masahi commented Feb 28, 2020

This adds support for parsing Torchscript prim::If and prim::Loop nodes. This is also the first attempt at translating from the output of torch.jit.script(...). See the test cases for currently supported Python construct.

The related discussion (with an example IR dump): https://discuss.tvm.ai/t/discuss-adding-a-pytorch-frontend/5026/24

The CI is blocked by unrelated sphinx issue, but it is ready for review.

cc @zhiics @icemelon9 @wweic @jroesch @MarisaKirisame @alexwong @tqchen @junrushao1994 @ajtulloch @yinghai

@zhiics
Copy link
Member

zhiics commented Feb 28, 2020

@masahi Thank you very much for the nice work! I am familiar the TF control-flow, and trying to read more about PyTorch control-flow constructs. Will have a careful review by tomorrow.

Copy link
Contributor

@alexwong alexwong left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Some small comments, also reading up on control flow in Torch.

python/tvm/relay/frontend/pytorch.py Outdated Show resolved Hide resolved
@MarisaKirisame
Copy link
Contributor

can you dont call it parse? parse is for converting strings to an ast. converting ast to ast is a converter.

nice work otherwise.

@masahi
Copy link
Member Author

masahi commented Feb 29, 2020

Tests passed!!

can you dont call it parse? parse is for converting strings to an ast. converting ast to ast is a converter.

no probelm, will do.

@alexwong @zhiics a good way to get familiar with torch script is to try and tweak simple examples. For example,

import torch


class SimpleLoop(torch.nn.Module):
    def forward(self, inp):
        a = inp
        for i in range(10):
            a += i
        return a


class SimpleWhileLoop(torch.nn.Module):
    def forward(self, inp):
        a = inp
        i = 0
        while i < 10:
            a += i
            i += 1
        return a


print(torch.jit.script(SimpleLoop()).graph)
print(torch.jit.script(SimpleWhileLoop()).graph)

would print

graph(%self : __torch__.SimpleLoop,
      %inp.1 : Tensor):
  %10 : int = prim::Constant[value=1]()
  %6 : bool = prim::Constant[value=1]() # test.py:7:8
  %3 : int = prim::Constant[value=10]() # test.py:7:23
  %a : Tensor = prim::Loop(%3, %6, %inp.1) # test.py:7:8
    block0(%i.1 : int, %a.5 : Tensor):
      %a.2 : Tensor = aten::add_(%a.5, %i.1, %10) # test.py:8:12
      -> (%6, %a.2)
  return (%a)

graph(%self : __torch__.SimpleWhileLoop,
      %inp.1 : Tensor):
  %i.1 : int = prim::Constant[value=0]() # test.py:15:12
  %4 : int = prim::Constant[value=9223372036854775807]() # test.py:16:8
  %6 : int = prim::Constant[value=10]() # test.py:16:18
  %16 : int = prim::Constant[value=1]() # test.py:18:17
  %39 : bool = prim::Constant[value=1]()
  %a : Tensor, %i : int = prim::Loop(%4, %39, %inp.1, %i.1) # test.py:16:8
    block0(%8 : int, %a.5 : Tensor, %i.8 : int):
      %a.2 : Tensor = aten::add_(%a.5, %i.8, %16) # test.py:17:12
      %i.6 : int = aten::add(%i.8, %16) # test.py:18:12
      %7 : bool = aten::lt(%i.6, %6) # test.py:16:14
      -> (%7, %a.2, %i.6)
  return (%a)

hopefully it is much simpler than tensorflow control flow.

@MarisaKirisame
Copy link
Contributor

One thing to keep in mind is that torchscript has mutation, continue, while... So the design should be prepared to generate code in A-Normal Form for correctness. Right now it is not needed as they are all purely functional, but the architecture shouldnt make such a change as simple as possible (e.g. not requiring rewriting all the code).

@masahi
Copy link
Member Author

masahi commented Feb 29, 2020

@MarisaKirisame I have something relevant to share. I was told by one of the torchscript devs on their forum that he is working on a "functionalization" pass pytorch/pytorch#33020, and that could help my use case. I'm not sure what exactly it does, but from looking at their code it seems it tries to find a "functional" subset of nodes, i.e. nodes with no impure operation, and extract it as a subgraph. I guess it helps applying some of their optimizations more aggressively.

He also has others related PRs ongoing that aim at making the graph "more pure". One on removing inplace op pytorch/pytorch#33186, another on removing list append pytorch/pytorch#33199. I literally encountered these impure ops when I was trying to convert more realistic lstm models than the one I have in this PR, so these new feature in Torch could be useful to us later.

@MarisaKirisame
Copy link
Contributor

// Functional Graphs are not responsible for maintaining aliasing
// relationships. If an output of a functional graph escapes scope
// or is mutated then we might change semantics of the program if
// aliasing relationships are changed.

... WTF
I dont think lots of smartness should go in the converter - suppose there is multiple converter, it need multiple smart hacks to remove reference or such.
A better design IMO is to use PartialEvaluator/DeadCodeElimination/SomeOtherCustomPass to remove the reference, but the converter will produce code will effect and reference without much cleaning.

python/tvm/relay/frontend/pytorch.py Outdated Show resolved Hide resolved
python/tvm/relay/frontend/pytorch.py Show resolved Hide resolved
python/tvm/relay/frontend/pytorch.py Show resolved Hide resolved
@masahi masahi force-pushed the torch-control-flow branch 3 times, most recently from a83a729 to b1333cb Compare March 5, 2020 05:57
@masahi
Copy link
Member Author

masahi commented Mar 10, 2020

@zhiics @MarisaKirisame @alexwong Comments were addressed and I have no plan of updating this PR further. Can we merge this?

Copy link
Member

@zhiics zhiics left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM

@MarisaKirisame could you take a look and approve explicitly if it looks good to you as well?

@zhiics zhiics merged commit 06e9542 into apache:master Mar 10, 2020
@zhiics
Copy link
Member

zhiics commented Mar 10, 2020

Thanks @masahi @MarisaKirisame @alexwong

trevor-m pushed a commit to trevor-m/tvm that referenced this pull request Apr 16, 2020
* Add support for prim::If and prim::Loop with test cases

* rebase and fix tests

* add some comments

* simplifying, fix float cast

* parse -> convert

* recursivly retrive ops in get_all_op_names

* use multiple return values from block correctly, simplify loop convert

* choose dtype properly for zeros and ones

* simplifying, replace convert_inputs with _get_relay_input_vars

* fix for while loop with non input dependent init cond

* add assert on loop var update

* move the condition around

* better testing for seg models

* rebase fix, disable inception v3 in quant test as it is too slow to
load with torch-1.4 + torchvision 0.5

* simplify and add more comparison op converter
zhiics pushed a commit to neo-ai/tvm that referenced this pull request Apr 17, 2020
* Add support for prim::If and prim::Loop with test cases

* rebase and fix tests

* add some comments

* simplifying, fix float cast

* parse -> convert

* recursivly retrive ops in get_all_op_names

* use multiple return values from block correctly, simplify loop convert

* choose dtype properly for zeros and ones

* simplifying, replace convert_inputs with _get_relay_input_vars

* fix for while loop with non input dependent init cond

* add assert on loop var update

* move the condition around

* better testing for seg models

* rebase fix, disable inception v3 in quant test as it is too slow to
load with torch-1.4 + torchvision 0.5

* simplify and add more comparison op converter
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants