[nativert] Move GraphSignature to pytorch core#152969
[nativert] Move GraphSignature to pytorch core#152969yiming0416 wants to merge 1 commit intopytorch:mainfrom
Conversation
🔗 Helpful Links🧪 See artifacts and rendered test results at hud.pytorch.org/pr/152969
Note: Links to docs will display an error until the docs builds have been completed. ✅ No FailuresAs of commit 7a34259 with merge base 5163bf0 ( This comment was automatically generated by Dr. CI and updates every 15 minutes. |
|
This pull request was exported from Phabricator. Differential Revision: D73895378 |
|
This pull request was exported from Phabricator. Differential Revision: D73895378 |
ecec4a7 to
75169ac
Compare
|
This pull request was exported from Phabricator. Differential Revision: D73895378 |
75169ac to
7f46ae6
Compare
This comment was marked as resolved.
This comment was marked as resolved.
This comment was marked as resolved.
This comment was marked as resolved.
|
This pull request was exported from Phabricator. Differential Revision: D73895378 |
7f46ae6 to
61f2d89
Compare
This comment was marked as resolved.
This comment was marked as resolved.
|
This pull request was exported from Phabricator. Differential Revision: D73895378 |
61f2d89 to
1172604
Compare
There was a problem hiding this comment.
this many maps of strings to other strings is an efficiency code smell.
- why do we have multiple parallel maps keyed by the same string? couldn't we, for example, map each input to a struct containing its parameters, buffers, tensor constants, and custom objects?
- is a string really the right data type for all this stuff?
More context about what is really going on here would be helpful for making concrete suggestions
There was a problem hiding this comment.
@swolchok This representation of GraphSignature in nativert follows the existingExportGraphSignature (https://docs.pytorch.org/docs/stable/export.html#torch.export.ExportGraphSignature)
There was a problem hiding this comment.
@swolchok Oh I believe there is some misunderstanding. these maps are not keyed by the same string.
As the the input in inputsToParameters_ and inputsToBuffers_ are not the same inputs.
There was a problem hiding this comment.
here we are duplicating the map keys again! can't we just iterate over the map?
There was a problem hiding this comment.
@swolchok again, these follow the existing ExportGraphSignature in torch.export (please see my comments above). And later on we rely on these strings for weight look-up and loading. If we don't store them and just iterate over the map, it might add some overhead every time we access them?
There was a problem hiding this comment.
If we don't store them and just iterate over the map, it might add some overhead every time we access them?
if we use a good hash table (such c10::FastMap), I would not expect iterating over map keys to be materially more expensive than iterating over an array.
these follow the existing ExportGraphSignature
Directly porting Python data structures to C++ is not necessarily appropriate. Python strings are stored by pointer and are often interned (if my sources are to be trusted), whereas C++ std::string is a value type with no interning. Efficiency demands on C++ code are also typically higher; Python is by its nature inefficient and so micro-optimizing Python code and data structures tends to miss the point.
There was a problem hiding this comment.
@swolchok I changed unordered_set to c10::FastSet and unordered_map to c10::FastMap
But I have to keep these std::vector<std::string>, because we need to maintain the order of these strings as it is an important assumption in nativert for weight loading and some unused weight optimization later.
There was a problem hiding this comment.
we need to maintain the order of these strings as it is an important assumption in nativert for weight loading and some unused weight optimization later.
sounds like a great code comment, together with a pointer to the components that care.
How big is this data structure typically? Could we do something like store std::string_view or std::string* in the maps (except the ones that get touched in replaceAllUses!) since the data is owned by the vectors? (note that this would require appropriate care to make sure the referenced strings don't get moved, such as by vector reallocation)
There was a problem hiding this comment.
@swolchok I think we can't use string_view here because the strings stored in parameters_ are loaded from an in-memory representation of the serialized json format torch::_export::GraphSignature and we free it after torch::native::GraphSignature is constructed. So we have to store actual strings.
There was an attempt to dedupe attributes in GraphSignature in D69926343, but it was reverted as it required C++20. I think we can revisit this later when PyTorch build supports C++20
There was a problem hiding this comment.
I think we can't use string_view here because the strings stored in parameters_ are loaded from an in-memory representation of the serialized json format torch::_export::GraphSignature and we free it after torch::native::GraphSignature is constructed. So we have to store actual strings.
I meant that the string_view or string* would refer to the string data owned by the std::vectors in this class, not in the input.
There was a problem hiding this comment.
I meant that the string_view or string* would refer to the string data owned by the std::vectors in this class, not in the input.
@swolchok I see your points, and I have given that a try. Unfortunately under the current design it's difficult to avoid vector reallocation, so using string_view in the map to refer to strings in the vector will cause downstream weight loading failures. Therefore, we'd prefer to keep the current implementation. We'll definitely resume the attempt to optimize this, as we did in D69926343, when the PyTorch build supports C++20.
Do you think that's okay? Are there any other blocking comments on this PR?
There was a problem hiding this comment.
it's difficult to avoid vector reallocation
AIUI replaceAllUses is the only non-const method in this class. I understand why it's difficult to avoid reallocation for the vectors it touches, but it looks like there is a significant subset of the state that is never modified after construction. Why is it difficult to avoid reallocation for that subset?
There was a problem hiding this comment.
@swolchok In the latest version I have done the duplication. Now we only have two maps inputsToWeights_ and inputsToCustomObjs_ actually saving the strings (these two maps are disjoint). Rest of the maps and vectors will use string_view to refer the strings saved in these two maps.
There was a problem hiding this comment.
if we kept our data nicely deduplicated in the first place we wouldn't have to do this expensive operation here
There was a problem hiding this comment.
True, can we not just use an ordered set?
malfet
left a comment
There was a problem hiding this comment.
Neither RFC nor this PR sheds any light on what is graph signature and why is it needed for native runtime
This comment was marked as resolved.
This comment was marked as resolved.
|
This pull request was exported from Phabricator. Differential Revision: D73895378 |
56241c7 to
4c98c19
Compare
|
@swolchok Sorry for pinging again but can you please take a look at my response above and let me know if there is any other blocking comments? Thanks! |
|
This pull request was exported from Phabricator. Differential Revision: D73895378 |
4c98c19 to
5714072
Compare
|
This pull request was exported from Phabricator. Differential Revision: D73895378 |
5714072 to
6b31ae7
Compare
|
This pull request was exported from Phabricator. Differential Revision: D73895378 |
6b31ae7 to
a9e970f
Compare
|
This pull request was exported from Phabricator. Differential Revision: D73895378 |
a9e970f to
444dc5e
Compare
|
This pull request was exported from Phabricator. Differential Revision: D73895378 |
444dc5e to
24de774
Compare
|
This pull request was exported from Phabricator. Differential Revision: D73895378 |
24de774 to
5109eaf
Compare
Summary: Pull Request resolved: pytorch#152969 An in-memory representation of `GraphSignature` which will be consumed by the runtime. Test Plan: Added tests under `test/cpp/nativert/test_graph_signature.cpp` Reviewed By: zhxchen17 Differential Revision: D73895378
|
This pull request was exported from Phabricator. Differential Revision: D73895378 |
|
@pytorchbot merge (Initiating merge automatically since Phabricator Diff has merged) |
|
This PR has pending changes requested. Please address the comments and update the PR before merging. |
|
@pytorchbot merge -f "landed internally" |
Merge startedYour change will be merged immediately since you used the force (-f) flag, bypassing any CI checks (ETA: 1-5 minutes). Please use Learn more about merging in the wiki. Questions? Feedback? Please reach out to the PyTorch DevX Team |
Summary:
Torch Native Runtime RFC: pytorch/rfcs#72
Added an in-memory representation for input and output specs of a graph. The GraphSignature class models the input and output specs of an exported graph produced by torch.export, which holds the graph information deserialized from the pt2 archive package. Runtime relies on the GraphSignature for weight name lookup and weight loading.
The serialization schema is defined in torch/_export/serde/schema.py
See more at: https://docs.pytorch.org/docs/stable/export.html#torch.export.ExportGraphSignature
Test Plan: Added tests under
test/cpp/nativert/test_graph_signature.cppDifferential Revision: D73895378