Skip to content

Conversation

@driazati
Copy link
Contributor

@driazati driazati commented Oct 1, 2019

Resolve static methods as functions

Fixes #26792

Differential Revision: D17695094

Resolve static methods as functions

Fixes #26792
@driazati driazati requested a review from apaszke as a code owner October 1, 2019 20:28
@facebook-github-bot facebook-github-bot added the oncall: jit Add this issue/PR to JIT oncall triage queue label Oct 1, 2019
@pytorchbot pytorchbot added the module: pybind Related to our Python bindings / interactions with other Python libraries label Oct 1, 2019
@driazati driazati requested a review from eellison October 2, 2019 20:44
@eellison
Copy link
Contributor

eellison commented Oct 2, 2019

Going forward I'm not sure if we should implement a feature for nn.Modules without also implementing it for User Defined Classes.

@driazati
Copy link
Contributor Author

driazati commented Oct 3, 2019

@eellison it should work for class types too, added a test

@eellison
Copy link
Contributor

eellison commented Oct 7, 2019

Could you add a tests for when two different classes define a static method with the same name, and those two methods are used in the same function ?

@driazati
Copy link
Contributor Author

@pytorchbot rebase this please

Copy link
Contributor

@eellison eellison left a comment

Choose a reason for hiding this comment

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

Looks good i just have a couple questions / nits

retval = resolver->resolveValue(ident, method, range);
}

if (!retval) {
Copy link
Contributor

Choose a reason for hiding this comment

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

Why was this change made?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

iirc classes can be resolved both by resolveValue and resolveType, so this makes sure resolveValue goes first

Copy link
Contributor

Choose a reason for hiding this comment

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

Still dont really understand why this was changed

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Static methods aren't put on to class types but resolved into functions directly from Python, so if the class is resolved as a type then it won't find the static methods

return x * 100

def forward(self, x):
return x - M.my_method(x) + N.my_method(x)
Copy link
Contributor

Choose a reason for hiding this comment

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

How does this serialize if we're not inlining methods ? Could you print out the source ?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

We still do inlining:

graph(%self : ClassType<N>,
      %x.1 : Tensor):
  %23 : int = prim::Constant[value=100]() # test/test_jit.py:3654:27
  %22 : int = prim::Constant[value=1]()
  %24 : Tensor = aten::add(%x.1, %23, %22) # test/test_jit.py:3654:23
  %7 : Tensor = aten::sub(%x.1, %24, %22) # test/test_jit.py:3668:23
  %26 : Tensor = aten::mul(%x.1, %23) # test/test_jit.py:3665:23
  %12 : Tensor = aten::add(%7, %26, %22) # test/test_jit.py:3668:23
  return (%12)

With inlining off the methods get correctly mangled:

graph(%self : ClassType<N>,
      %x.1 : Tensor):
  %9 : Function = prim::Constant[name="my_method"]()
  %6 : int = prim::Constant[value=1]()
  %4 : Function = prim::Constant[name="my_method"]()
  %5 : Tensor = prim::CallFunction(%4, %x.1) # test/test_jit.py:3668:27
  %7 : Tensor = aten::sub(%x.1, %5, %6) # test/test_jit.py:3668:23
  %10 : Tensor = prim::CallFunction(%9, %x.1) # test/test_jit.py:3668:44
  %12 : Tensor = aten::add(%7, %10, %6) # test/test_jit.py:3668:23
  return (%12)
Archive:  a.pt
 extracting: a/version               
 extracting: a/data.pkl              
  inflating: a/code/__torch__.py     
  inflating: a/code/__torch__.py.debug_pkl  
  inflating: a/code/__torch__/___torch_mangle_0.py  
  inflating: a/code/__torch__/___torch_mangle_0.py.debug_pkl  
  inflating: a/code/__torch__/___torch_mangle_1.py  
  inflating: a/code/__torch__/___torch_mangle_1.py.debug_pkl  
 extracting: a/constants.pkl         
[dev] ~/d/pytorch > cat ^C
[dev] ~/d/pytorch > cd ^C
[dev] ~/d/pytorch > cat a/code/__torch__/___torch_mangle_0.py   (base) [ 15:22:38 ]
op_version_set = 1
def my_method(x: Tensor) -> Tensor:
  return torch.add(x, 100, 1)
[dev] ~/d/pytorch > cat a/code/__torch__/___torch_mangle_1.py   (base) [ 15:22:50 ]
op_version_set = 1
def my_method(x: Tensor) -> Tensor:
  return torch.mul(x, 100)
[dev] ~/d/pytorch >                                             (base) [ 15:22:53 ]

and the tests still work

Copy link
Contributor

@eellison eellison left a comment

Choose a reason for hiding this comment

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

Looks good

retval = resolver->resolveValue(ident, method, range);
}

if (!retval) {
Copy link
Contributor

Choose a reason for hiding this comment

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

Still dont really understand why this was changed

@facebook-github-bot
Copy link
Contributor

@driazati merged this pull request in 8cdc262.

facebook-github-bot pushed a commit that referenced this pull request Nov 5, 2019
Summary:
Type objects in python have an attribute `__abstractmethods__` that throws when it is accessed, so we were failing with an AttributeError whenever a type was used in TorchScript.

This pr prevents that error from happening. We can't just throw when a type is used because it could be used to access a static method: #27163
Pull Request resolved: #28053

Differential Revision: D18332347

Pulled By: eellison

fbshipit-source-id: 9c7f2220f92674ad4d903621d9762cecc566ab0d
thiagocrepaldi pushed a commit to thiagocrepaldi/pytorch that referenced this pull request Feb 4, 2020
Summary:
Resolve static methods as functions

Fixes pytorch#26792
](https://our.intern.facebook.com/intern/diff/17695094/)
Pull Request resolved: pytorch#27163

Pulled By: driazati

Differential Revision: D17695094

fbshipit-source-id: 4671cae1a92526a35c83b8d9c12a50aa5442412b
@facebook-github-bot facebook-github-bot deleted the driazati/staticm branch July 13, 2020 17:55
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Merged module: pybind Related to our Python bindings / interactions with other Python libraries oncall: jit Add this issue/PR to JIT oncall triage queue

Projects

None yet

Development

Successfully merging this pull request may close these issues.

torch.jit.script cannot compile forward() calling a @staticmethod annotated method

6 participants