[jit] Add module attributes#17309
[jit] Add module attributes#17309driazati wants to merge 34 commits intopytorch:masterfrom driazati:attr
Conversation
|
@pytorchbot rebase this please |
|
A few questions here:
Basically |
|
This is pretty rough right now and won't have full support for a while, but:
|
zdevito
left a comment
There was a problem hiding this comment.
Great start -- I've put some comments inline about some issues that we need to resolve about figure out the right types for attributes, and how to structure the Module class.
torch/csrc/jit/script/module.h
Outdated
| // to the slots where parameters are kept while also allow parameters | ||
| // to be reassigned | ||
| std::unique_ptr<at::Tensor> parameter; | ||
| struct NamedInput { |
There was a problem hiding this comment.
It's not always an input, so NamedIValue would be a better term.
torch/csrc/jit/script/module.h
Outdated
| auto retval = graph_->copy(); | ||
| for (auto inp : member_inputs) { | ||
| inputs.push_back(*inp); | ||
| for (auto inp : member_inputs_) { |
There was a problem hiding this comment.
The if statement here is going wreck havoc later. I think inputs/outputs should be flipped to IValue.
| Module() | ||
| : modules("Module"), | ||
| parameters("Parameter"), | ||
| attributes("Attributes"), |
There was a problem hiding this comment.
We should be careful how we structure things here so that it mirrors how a python class works.
We probably want to drop the is_parameter flag and simply use the separate lists (attributes vs parameters) to decide whether something is a parameter. Things that were previously buffers should go in the attributes list.
torch/jit/__init__.py
Outdated
| return self.__getattr__('forward').graph | ||
| return Module.__getattr__(self, attr) | ||
|
|
||
| def _is_attribute(self, attr, value): |
There was a problem hiding this comment.
This seems brittle because it has to look through every other potential place where getattr looks to make sure it doesn't fall into one of these categories. Is there a better way to structure this?
torch/jit/__init__.py
Outdated
| """.format(type(v).__name__, attr, constants))) | ||
|
|
||
|
|
||
| def _get_type(value): |
There was a problem hiding this comment.
I am not a fan of adding this. It will need to be an exhaustive list, and we already have similar stuff in C++ for converting python values. It also cannot be done correctly: If a list is empty or a dict is empty we cannot infer the type. We should use the existing C++ code that figure out the type and IValue information from a python class rather than reimplement it here. We should also consider how we could inform the Module about the right type for things like empty dictionaries where the type is not inferrable.
zdevito
left a comment
There was a problem hiding this comment.
Looks pretty good. I have a few comments that should be addressed and then it is ready to land.
torch/csrc/jit/export.cpp
Outdated
There was a problem hiding this comment.
In its current form, won't landing this will break serialization of buffers?
There was a problem hiding this comment.
This was from an old commit and was fixed to use a flag
| return std::make_shared<SimpleValue>(m.get_or_add_parameter(v->slot())); | ||
| } else if (NamedInput* v = module->find_attribute(field)) { | ||
| return std::make_shared<SimpleValue>( | ||
| m.get_or_add_attribute(v->type, v->slot())); |
There was a problem hiding this comment.
get_or_add_attribute should take a NamedInput* rather than both a type and a IValue*. Otherwise it is too easy to accidentally pass the wrong type.
torch/csrc/jit/script/init.cpp
Outdated
| // python method. If so return this as a python value. | ||
| py::object py_module = py::cast(module); | ||
| if (py::object attr = py::getattr(py_module, field.c_str(), py::none())) { | ||
| if (py::isinstance( |
There was a problem hiding this comment.
Attributes should be registered during the init process. Doing it lazily here does not follow the same pattern of parameters, and it prevents a user from having an attribute exist even when a method doesn't reference it. I see trouble with this when, for instance, someone uses a non-python way of defining a Method and it can't see the attributes because they are in a Python-only state at the moment.
facebook-github-bot
left a comment
There was a problem hiding this comment.
@driazati has imported this pull request. If you are a Facebook employee, you can view this diff on Phabricator.
facebook-github-bot
left a comment
There was a problem hiding this comment.
@driazati has imported this pull request. If you are a Facebook employee, you can view this diff on Phabricator.
* upstream/master: (24 commits) Automatic update of fbcode/onnx to 96c58ceeacf0f2b73d752e413e4fd78787a12da3 (pytorch#17676) Set the default ONNX opset to the latest stable opset (i.e., 9) (pytorch#17736) Add module attributes (pytorch#17309) - refactoring serialization of ONNX initializers to be name-based (pytorch#17420) ONNX Export for Max and Average Pooling in CEIL_MODE use flake8-mypy (pytorch#17721) use fp16<->fp32 intrinsic (pytorch#17496) Implement a Caffe2 standalone LSTM operator (pytorch#17726) caffe2:libtorch_cuda depends on caffe2:caffe2_gpu (pytorch#17729) add tensor and cost inference functions (pytorch#17684) ONNX Export Narrow op Keep the dim_type of hinted shape as BATCH if possible (pytorch#17734) fix different round behavior on CPU and GPU pytorch#16498 (pytorch#17443) Warn about memory overlaps on expanded tensors (pytorch#17576) fix exp fam. formula refactor caffe2 operator constructors - 10/9 (pytorch#17659) Improve ONNX symbolic for logsoftmax and softmax (pytorch#17672) Enable using CMD when building cpp extensions on Windows Do not rename net boundary inputs/outputs during ssaRewrite. (pytorch#17545) Reapply D14078519 (pytorch#17596) ...
Similar to
nn.Parameters, this PR lets you store anyIValueon a module as an attribute on aScriptModule(only from the Python front-end currently). To mark something as an attribute, it should wrapped injit.Attribute(value, type)(ex.self.table = torch.jit.Attribute(table, Dict[str, torch.Tensor]))Followup Work:
self.trainingto be aboolattribute instead of a buffer