[jit] Add dictionary as output of tracer#31860
[jit] Add dictionary as output of tracer#31860wanchaol merged 12 commits intogh/wanchaol/75/basefrom
Conversation
💊 Build failures summary and remediationsAs of commit 89ad086 (more details on the Dr. CI page): 💚 💚 Looks good so far! There are no failures yet. 💚 💚 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. This comment has been revised 39 times. |
0cf4e6f to
9938cc8
Compare
9938cc8 to
9f81e8d
Compare
|
The surprising behavior demonstrated in #31860 (review) is actually not caused by the limitation of static dict, but rather the size Tensor has been casted to Python int in the import torch
def foo_list(x):
rv = []
for i in range(x.size(0)):
rv.append(x[i])
return rv
traced = torch.jit.trace(foo_list, (torch.randn(3, 1)))
print(traced(torch.randn(3, 1)))
print(traced(torch.randn(5, 1)))
def foo_tuple(x):
return tuple(x[i] for i in range(x.size(0)))
traced = torch.jit.trace(foo_tuple, (torch.randn(3, 1)))
print(traced(torch.randn(3, 1)))
print(traced(torch.randn(5, 1))) |
|
So if we are going to add a flag to prevent this silently wrong behavior, maybe it should be guarding the casting (but it will be a breaking change, right now the tracer only gives warning). |
@bddppq you are right, the case only happens in dynamic control flow, and casting currently gives a warning to the user that might get ignored by user who don't read the doc and understand the internals of tracer. The general issue might not only happening for tensor casting though, i.e. user could check Had a discussion with @jamesr66a and other folks today. The short term plan is to guard the risk behavior under a
|
Summary: This add dictionary as a supported output of tracer. Test Plan: Reviewers: Subscribers: Tasks: Tags: Differential Revision: [D20638438](https://our.internmc.facebook.com/intern/diff/D20638438) [ghstack-poisoned]
Summary: This add dictionary as a supported output of tracer. Test Plan: Reviewers: Subscribers: Tasks: Tags: Differential Revision: [D20638438](https://our.internmc.facebook.com/intern/diff/D20638438) [ghstack-poisoned]
Summary: This add dictionary as a supported output of tracer. Test Plan: Reviewers: Subscribers: Tasks: Tags: Differential Revision: [D20638438](https://our.internmc.facebook.com/intern/diff/D20638438) [ghstack-poisoned]
Summary: This add dictionary as a supported output of tracer. Test Plan: Reviewers: Subscribers: Tasks: Tags: Differential Revision: [D20638438](https://our.internmc.facebook.com/intern/diff/D20638438) [ghstack-poisoned]
jamesr66a
left a comment
There was a problem hiding this comment.
Cool, I had a question about how we're doing ordering for Tensor-keyed dictionaries. I want to make sure that's safe and stable across compilation/machines etc
| TypePtr key_type = dict.keyType(); | ||
| TypePtr value_type = dict.valueType(); | ||
|
|
||
| if (!(key_type->cast<StringType>() || key_type->cast<TensorType>()) || |
There was a problem hiding this comment.
This is kinda hard to read in the !(A || B) || !C form. Can we do something like:
bool key_type_valid = key_type->cast<StringType>() || key_type->cast<TensorType>();
bool value_type_valid = value_type->cast<TensorType>();
if (!key_type_valid || !value_type_valid) {
<...>
| << "or dict[Tensor, Tensor] can be a dictionary output of a traced function"; | ||
| throw std::runtime_error(os.str()); | ||
| } | ||
| const auto order = iterationOrder(dict); |
There was a problem hiding this comment.
Not an issue with your PR, but I looked at the declaration of iterationOrder and I'm not sure what it does :p. It could use some comments or a rename to indicate its function
There was a problem hiding this comment.
iterationOrder will return a pair of ivalues that ordered by CompareKeys, in the case that key is Tensor, it's ordered by TensorImpl pointer address.
There was a problem hiding this comment.
Can you (or someone) add that as a comment?
| std::iota(perm.begin(), perm.end(), 0); | ||
| std::sort(perm.begin(), perm.end(), [&](int64_t i, int64_t j) { | ||
| return keys[i]->unique() < keys[j]->unique(); | ||
| }); |
There was a problem hiding this comment.
Can you comment on the stability of these unique IDs? Doesn't Value::unique() potentially depend on the order of compilation of values?
There was a problem hiding this comment.
I think this is quite stable, by the time we generate the output, the tracer already record the values of the dict keys, and the tracer record the keys based on the order of encountering tensors, so unique() should depend on the order of that, and tracing the same program will always generate the same sequence of unique ids.
Summary: This add dictionary as a supported output of tracer. Test Plan: Reviewers: Subscribers: Tasks: Tags: Differential Revision: [D20638438](https://our.internmc.facebook.com/intern/diff/D20638438) [ghstack-poisoned]
Summary: This add dictionary as a supported output of tracer. Test Plan: Reviewers: Subscribers: Tasks: Tags: Differential Revision: [D20638438](https://our.internmc.facebook.com/intern/diff/D20638438) [ghstack-poisoned]
Summary: This add dictionary as a supported output of tracer. Test Plan: Reviewers: Subscribers: Tasks: Tags: Differential Revision: [D20638438](https://our.internmc.facebook.com/intern/diff/D20638438) [ghstack-poisoned]
Summary: This add dictionary as a supported output of tracer. Test Plan: Reviewers: Subscribers: Tasks: Tags: Differential Revision: [D20638438](https://our.internmc.facebook.com/intern/diff/D20638438) [ghstack-poisoned]
|
something weird happens with ghstack on this PR, replace this with #36696 |
Stack from ghstack:
Summary:
This add dictionary as a supported output of tracer.
Test Plan:
Reviewers:
Subscribers:
Tasks:
Tags:
Differential Revision: D20638438