Skip to content

[JIT] Refactor attributes to support buffers and parameters as first class citizens, add support for iterating over named_buffers() - #37905

Closed
voznesenskym wants to merge 40 commits into
pytorch:masterfrom
voznesenskym:voznesenskym/named_buffers
Closed

voznesenskym wants to merge 40 commits into
pytorch:masterfrom
voznesenskym:voznesenskym/named_buffers

Conversation

@voznesenskym

Copy link
Copy Markdown
Collaborator

First part of #36211 - still a WIP, but asking for commentary to ensure this is the direction we want to go in.

@voznesenskym
voznesenskym requested a review from apaszke as a code owner May 6, 2020 02:58
@facebook-github-bot facebook-github-bot added the oncall: jit Add this issue/PR to JIT oncall triage queue label May 6, 2020
@voznesenskym
voznesenskym requested a review from suo May 6, 2020 02:59
@voznesenskym voznesenskym changed the title [WIP] [RFC] Add support for iterating over named_buffers() [WIP] [RFC] [JIT] Add support for iterating over named_buffers() May 6, 2020
@dr-ci

dr-ci Bot commented May 6, 2020 •

Copy link
Copy Markdown

💊 CI failures summary and remediations

As of commit 436f389 (more details on the Dr. CI page):


  • 1/1 failures possibly* introduced in this PR
    • 1/1 non-CircleCI failure(s)

ci.pytorch.org: 1 failed


This comment was automatically generated by Dr. CI (expand for details).Follow this link to opt-out of these comments for your Pull Requests.

Please report bugs/suggestions on the GitHub issue tracker.

See how this bot performed.

This comment has been revised 126 times.

@suo suo left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Some high level thoughts, haven't had a chance to look deeply:

  1. We should probably first tackle the change where we add buffers as a first-class concept on ClassType, separately from adding a named_buffers() iterator.
  2. is_parameter and was_registered_as_buffer are mutually exclusive. Conceivably there should be an enum that expresses the three types of tensor of attributes directly (parameters, buffers, regular attributes).

@voznesenskym

voznesenskym commented May 6, 2020 •

Copy link
Copy Markdown
Collaborator Author

@suo - Good suggestion. Making it a first class citizen + adding an enum would let us have a single collection to manage what we have in each slot on ClassType. I'll go back to the drawing board and look at how we can cleanly manage all 3. Looking at it, perhaps we can remove attributeNames_, attributeTypes_ parameterSlots_, and instead have a single std::vector<AttributeType> where AttributeType contains:

  • the value for the enum you mentioned
  • the attribute name (string) (if relevant)
  • the attributeType (TypePtr)

Thoughts?

@suo

suo commented May 6, 2020

Copy link
Copy Markdown
Member

Yeah I think that's a good overall direction. Some minor bits of context that may help guide the data structure decision:

  1. Runtime objects (instances of a ClassType) do not know about names, they store their attributes in a flat vector of IValue slots, to avoid hash table lookups in getattr. So we need a way of efficiently retrieving the slot of something by name on ClassType.
  2. Objects may want to look up name/type/parameter status by slot.
  3. It's okay to trade efficiency of retrieval in ClassType (which is a compile-time construct) for efficiency of retrieval in ivalue::Object (which is run-time). But that might not be relevant for this.

@voznesenskym voznesenskym changed the title [WIP] [RFC] [JIT] Add support for iterating over named_buffers() [JIT] Refactor attributes to support buffers and parameters as first class citizens, add support for iterating over named_buffers() May 10, 2020
@voznesenskym
voznesenskym requested a review from suo May 13, 2020 05:03
Comment thread aten/src/ATen/core/jit_type.h Resolved

@suo suo left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Nice! This is definitely on the right track. I left a somewhat unusual number of bikeshedding comments—this is a core API so we want to get the naming/concepts consistent.

Comment thread aten/src/ATen/core/jit_type.h Resolved
Comment thread aten/src/ATen/core/type.cpp Resolved
Comment thread aten/src/ATen/core/type.cpp Outdated

size_t slot = attributes_.size();

ATTRIBUTE_KIND_ENUM kind = ATTRIBUTE_KIND_ENUM::REGULAR_ATTRIBUTE;

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Should we consider just making ATTRIBUTE_KIND_ENUM something that the user sets? Hiding allows some weird behavior. For example: right now you can call addAttribute and have something be both a parameter and buffer—this code would silently mark the attribute as a parameter.

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

I'd rather keep it as a detail of our system, and then provide safeguards. Users already signal if something is a buffer or parameter by how they register it with our module.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

curious what happens in eager if someone registers the same name/value pair as a parameter and buffer…

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

I'll add a test for this!

Comment thread aten/src/ATen/core/jit_type.h Resolved
Comment thread test/test_jit.py Outdated
torch.jit.script(f)


def named_buffers_are_iterable(self):

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

I think unittest expects test methods to start with test_?

Comment thread test/test_jit.py Resolved
const SourceRange& loc,
Function& m);

std::shared_ptr<SugaredModuleDict> getSugaredNamedBufferDict(

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Probably we should rename SugaredModuleDict something more general, to reflact that it is not just being used as for named_modules() anymore.

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

Agreed. Any suggestions?

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

SugaredDict?

Comment thread aten/src/ATen/core/jit_type.h Resolved
Comment thread aten/src/ATen/core/jit_type.h Resolved
Comment thread aten/src/ATen/core/jit_type.h Resolved

@suo suo left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

nice, very close!

Comment thread aten/src/ATen/core/jit_type.h Outdated
return attributeType_;
}

const std::string getName() const {

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

nit: ref

Comment thread aten/src/ATen/core/jit_type.h Resolved
Comment thread torch/csrc/jit/api/module.h Outdated
type()->addOrCheckAttribute(name, TensorType::get());
bool is_param = false;
bool is_buffer = true;
type()->addOrCheckAttribute(name, TensorType::get(), is_param, is_buffer);

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Hmm…having a lot of boolean defaults in a row is getting a little scary. For example, there is a bug here, because you are actually setting is_param = false, allow_any = true, is_buffer=false, which is not what you want. I think either we should undefault them or change it to something more declarative than several flags

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

Agreed. I know you said it earlier and I pushed back, but I find myself coming around to the idea of replacing it with our enum.

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

I like your earlier suggestion of utilizing our enum. Since this would be a large (but relatively simple) change, are you fine with me moving the attribute adding APIs to the new enum in a subsequent diff?

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

yeah I think that makes sense!

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

This is still a bug, right?

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

Yea, I thought I pushed a fix. will update.

// attributes and parameters.
if (is_module) {
std::vector<std::string> params;
std::vector<std::string> buffers;

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Nice! Before committing this, we'll have to test for forward compatibility. Basically, can you save() with buffers, then load() using a version of pytorch that does not understand buffer serialization.

Based on skimming the import code, I think there will be an FC issue. Let's chat directly about the steps to take here.

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

Agreed, let me figure out the best way to do so.

@suo suo linked an issue May 15, 2020 that may be closed by this pull request
Comment thread torch/csrc/jit/api/module.h Outdated
at::Tensor v,
bool is_buffer) {
type()->addOrCheckAttribute(name, TensorType::get(), !is_buffer);
type()->addOrCheckAttribute(name, TensorType::get(), !is_buffer, is_buffer);

@suo suo May 17, 2020 •

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Same here (is_buffer is being passed to allow_any)

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

Yeah, will fix. Good catch.

@suo suo left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

looks good! I recommend sanity-checking the FC changes manually if you haven't already.

@voznesenskym

Copy link
Copy Markdown
Collaborator Author

FC tests completed via:

  1. Saving models locally on current commit
  2. Switching branches
  3. Rebuilding pytorch
  4. Loading models on older versions (b9c5375)

@facebook-github-bot facebook-github-bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

@voznesenskym has imported this pull request. If you are a Facebook employee, you can view this diff on Phabricator.

@facebook-github-bot

Copy link
Copy Markdown
Contributor

@voznesenskym merged this pull request in f6f1384.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Merged oncall: jit Add this issue/PR to JIT oncall triage queue

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[JIT] support self.named_buffers and self.named_parameters in TorchScript

4 participants