-
Notifications
You must be signed in to change notification settings - Fork 26.3k
[export] add translations for SymInt/Bool deserialization; FloorDiv #136802
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
Conversation
🔗 Helpful Links🧪 See artifacts and rendered test results at hud.pytorch.org/pr/136802
Note: Links to docs will display an error until the docs builds have been completed. ❌ 8 New FailuresAs of commit b53cc2d with merge base 46f158b ( NEW FAILURES - The following jobs have failed:
This comment was automatically generated by Dr. CI and updates every 15 minutes. |
|
This pull request was exported from Phabricator. Differential Revision: D63493615 |
…136802) Summary: fix for #136797 We have an issue with deserialization for symbolic expressions, where the original expression has a structure mismatch with the deserialized expression. This happens because we serialize the expressions into strings, and deserialize using sympy.sympify(). This seems to cause issues with custom torch sympy.Functions, in this case FloorDiv. In this case, this alters the structure from `FloorDiv(a, b)` into `sympy.floor(a, PowByNatural(b, -1))`, or `sympy.floor(sympy.Mul(*a), PowByNatural(b, -1))` if a is also a sympy.Mul. This seems to break downstream when we call torch.empty_strided() on this expression, and the PowByNatural has an invalid ValueRange (e.g. [0, -1]). This fixes that by adding translations after deserialization, to pattern match and transform expressions into the original format. Other potential strategies are a) we could also serialize SymInts as sympy.Expr structures, but that seems a lot more involved and BC breaking, or b) we could modify sympy.sympify(?), but I don't know if this is possible. Test Plan: test_export/test_serialize Differential Revision: D63493615
e48c4b9 to
ff4fe54
Compare
|
This pull request was exported from Phabricator. Differential Revision: D63493615 |
|
This pull request was exported from Phabricator. Differential Revision: D63493615 |
ff4fe54 to
f359edf
Compare
|
@ezyang would you know of a better way to do this? It seems like even if we let the invalid ValueRange pass or flip min/max, PowByNatural + ValueRanges is the thing to avoid, because it still means we lose precision when truncating the range to ints (e.g. [0, -1]). |
torch/_export/serde/serialize.py
Outdated
| compiler_max=vr.upper, # type: ignore[arg-type] | ||
| ) | ||
|
|
||
| sym = _translate_deserialized_sym_expr(sym) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
should this line go directly after line 1526?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
updated
|
So, the proper way to fix this is to stop serializing the Sympy string expressions as strings, for which we have NO stability or even round-trippability guarantee. Sympy expressions are supposed to be roundtrippable to FX IR, and back, via the Python reference / sympy interpreter stuff (there are some bugs / incompleteness, but we should fix those anyway.) But I'm guessing you didn't want to hear that? Lol. |
Hahaha no but this makes total sense |
|
If you are dead set on string format, I'd probably still want to have a customized printer and parser. In particular the parser needs to override the mapping of FloorDiv to which class. As a stopgap, we could potentially rename functions in torch.utils._sympy.functions so they don't conflict with Sympy |
|
I think we had the same problem with inductor cache right? site-packages/torch/utils/_sympy/interp.py:159] [0/1] failed while executing pow_by_natural([VR[0, int_oo], VR[-1, -1]])
site-packages/torch/_inductor/codecache.py:609] [0/1] Can't pickle
site-packages/torch/_inductor/codecache.py:609] [0/1] Traceback (most recent call last):
site-packages/torch/_inductor/codecache.py:609] [0/1] File "/opt/conda/lib/python3.11/site-packages/torch/_inductor/codecache.py", line 605, in dumps
site-packages/torch/_inductor/codecache.py:609] [0/1] pickler.dump(obj)
site-packages/torch/_inductor/codecache.py:609] [0/1] AttributeError: Can't pickle local object 'make_opaque_unary_fn.<locals>.OpaqueUnaryFn'
site-packages/torch/utils/_sympy/interp.py:159] [0/1] failed while executing pow_by_natural([VR[0, int_oo], VR[-1, -1]]) |
…136802) Summary: fix for #136797 We have an issue with deserialization for symbolic expressions, where the original expression has a structure mismatch with the deserialized expression. This happens because we serialize the expressions into strings, and deserialize using sympy.sympify(). This seems to cause issues with custom torch sympy.Functions, in this case FloorDiv. In this case, this alters the structure from `FloorDiv(a, b)` into `sympy.floor(a, PowByNatural(b, -1))`, or `sympy.floor(sympy.Mul(*a), PowByNatural(b, -1))` if a is also a sympy.Mul. This seems to break downstream when we call torch.empty_strided() on this expression, and the PowByNatural has an invalid ValueRange (e.g. [0, -1]). This fixes that by adding translations after deserialization, to pattern match and transform expressions into the original format. Other potential strategies are a) we could also serialize SymInts as sympy.Expr structures, but that seems a lot more involved and BC breaking, or b) we could modify sympy.sympify(?), but I don't know if this is possible. Test Plan: test_export/test_serialize Differential Revision: D63493615
f359edf to
b53cc2d
Compare
|
This pull request was exported from Phabricator. Differential Revision: D63493615 |
|
Yeah, I think we should just move to not string format, and add to the export serialization schema |
|
Is this related right? |
|
Do I need to open a new ticket for #136802 (comment) or we are on the same page here? |
|
Is there a roadmap to review this? |
|
Is this stalled? |
|
I've tried to hotpatch the latest nightly with this PR and the deserializzation issue is still here. |
Summary: Latest attempt after [136802](#136802) and [140084](#140084) got shelved. This keeps the string format for `expr_str`, but calls `sympy.printing.repr.srepr(s)` instead of `str(s)`, which prints expressions more explicitly, e.g. ``` ((2*x)//(3*y + 4)) -> "FloorDiv(Mul(Integer(2), Symbol('x')), Add(Mul(Integer(3), Symbol('y')), Integer(4)))" ``` This is nice because: - we have better roundtrippability for deserialization, robust to pretty printing changes like [this](https://github.com/pytorch/pytorch/blob/6c9bfd52b6a76ddff053bcff4d23ea7f4c280e9a/torch/utils/_sympy/functions.py#L208) that caused the issue in the first place. - this preserves the BC surface for both 1) sigmoid thrift serialization, by keeping the string format, and 2) deserialization for old IRs, since `sympy.sympify(...)` still handles the old `str(s)` format. - more memory efficient than storing ASTs; the [AST attempt](#140084) increased artifact size by 20% on some toy programs. - doesn't even require a schema version bump. Additionally to push some test cases over the line, this redoes expression processing (handling ranges, symbol caching) by doing bottom-up processing instead of the current hacky-ish workflow. Test Plan: test_serdes, test_serialize, internal tests broken by AST PR Reviewed By: zhxchen17 Differential Revision: D66283208
Summary: Latest attempt after [136802](#136802) and [140084](#140084) got shelved. This keeps the string format for `expr_str`, but calls `sympy.printing.repr.srepr(s)` instead of `str(s)`, which prints expressions more explicitly, e.g. ``` ((2*x)//(3*y + 4)) -> "FloorDiv(Mul(Integer(2), Symbol('x')), Add(Mul(Integer(3), Symbol('y')), Integer(4)))" ``` This is nice because: - we have better roundtrippability for deserialization, robust to pretty printing changes like [this](https://github.com/pytorch/pytorch/blob/6c9bfd52b6a76ddff053bcff4d23ea7f4c280e9a/torch/utils/_sympy/functions.py#L208) that caused the issue in the first place. - this preserves the BC surface for both 1) sigmoid thrift serialization, by keeping the string format, and 2) deserialization for old IRs, since `sympy.sympify(...)` still handles the old `str(s)` format. - more memory efficient than storing ASTs; the [AST attempt](#140084) increased artifact size by 20% on some toy programs. - doesn't even require a schema version bump. Additionally to push some test cases over the line, this redoes expression processing (handling ranges, symbol caching) by doing bottom-up processing instead of the current hacky-ish workflow. Test Plan: test_serdes, test_serialize, internal tests broken by AST PR Differential Revision: D66283208 Pull Request resolved: #141284 Approved by: https://github.com/zhxchen17
…141284) Summary: Latest attempt after [136802](pytorch#136802) and [140084](pytorch#140084) got shelved. This keeps the string format for `expr_str`, but calls `sympy.printing.repr.srepr(s)` instead of `str(s)`, which prints expressions more explicitly, e.g. ``` ((2*x)//(3*y + 4)) -> "FloorDiv(Mul(Integer(2), Symbol('x')), Add(Mul(Integer(3), Symbol('y')), Integer(4)))" ``` This is nice because: - we have better roundtrippability for deserialization, robust to pretty printing changes like [this](https://github.com/pytorch/pytorch/blob/6c9bfd52b6a76ddff053bcff4d23ea7f4c280e9a/torch/utils/_sympy/functions.py#L208) that caused the issue in the first place. - this preserves the BC surface for both 1) sigmoid thrift serialization, by keeping the string format, and 2) deserialization for old IRs, since `sympy.sympify(...)` still handles the old `str(s)` format. - more memory efficient than storing ASTs; the [AST attempt](pytorch#140084) increased artifact size by 20% on some toy programs. - doesn't even require a schema version bump. Additionally to push some test cases over the line, this redoes expression processing (handling ranges, symbol caching) by doing bottom-up processing instead of the current hacky-ish workflow. Test Plan: test_serdes, test_serialize, internal tests broken by AST PR Differential Revision: D66283208 Pull Request resolved: pytorch#141284 Approved by: https://github.com/zhxchen17
…141284) Summary: Latest attempt after [136802](pytorch#136802) and [140084](pytorch#140084) got shelved. This keeps the string format for `expr_str`, but calls `sympy.printing.repr.srepr(s)` instead of `str(s)`, which prints expressions more explicitly, e.g. ``` ((2*x)//(3*y + 4)) -> "FloorDiv(Mul(Integer(2), Symbol('x')), Add(Mul(Integer(3), Symbol('y')), Integer(4)))" ``` This is nice because: - we have better roundtrippability for deserialization, robust to pretty printing changes like [this](https://github.com/pytorch/pytorch/blob/6c9bfd52b6a76ddff053bcff4d23ea7f4c280e9a/torch/utils/_sympy/functions.py#L208) that caused the issue in the first place. - this preserves the BC surface for both 1) sigmoid thrift serialization, by keeping the string format, and 2) deserialization for old IRs, since `sympy.sympify(...)` still handles the old `str(s)` format. - more memory efficient than storing ASTs; the [AST attempt](pytorch#140084) increased artifact size by 20% on some toy programs. - doesn't even require a schema version bump. Additionally to push some test cases over the line, this redoes expression processing (handling ranges, symbol caching) by doing bottom-up processing instead of the current hacky-ish workflow. Test Plan: test_serdes, test_serialize, internal tests broken by AST PR Differential Revision: D66283208 Pull Request resolved: pytorch#141284 Approved by: https://github.com/zhxchen17
|
Looks like this PR hasn't been updated in a while so we're going to go ahead and mark this as |
|
if this is going to be close as stale do we still have a ticket to track this? |
|
Was this fixed by #141284? |
|
I've tested on Nov, 2 and it was merge on Nov, 22. So probably it is ok |
Summary:
fix for #136797
We have an issue with deserialization for symbolic expressions, where the original expression has a structure mismatch with the deserialized expression. This happens because we serialize the expressions into strings, and deserialize using sympy.sympify().
This seems to cause issues with custom torch sympy.Functions, in this case FloorDiv. In this case, the expression
FloorDiv(a, b)turns intosympy.floor(a, PowByNatural(b, -1)), orsympy.floor(sympy.Mul(*a), PowByNatural(b, -1))if a is also a sympy.Mul. This seems to break downstream when we call torch.empty_strided() on this expression, and the PowByNatural has an invalid ValueRange (e.g. [0, -1]).This fixes that by adding translations after deserialization, to pattern match and transform expressions into the original format. Other potential strategies are a) we could also serialize SymInts as sympy.Expr structures, but that seems a lot more involved and BC breaking, or b) we could modify sympy.sympify(?), but I don't know if this is possible.
Test Plan: test_export/test_serialize
Differential Revision: D63493615