Skip to content

[nativert] Move GraphSignature to pytorch core#152969

Closed
yiming0416 wants to merge 1 commit intopytorch:mainfrom
yiming0416:export-D73895378
Closed

[nativert] Move GraphSignature to pytorch core#152969
yiming0416 wants to merge 1 commit intopytorch:mainfrom
yiming0416:export-D73895378

Conversation

@yiming0416
Copy link
Contributor

@yiming0416 yiming0416 commented May 6, 2025

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.cpp

Differential Revision: D73895378

@pytorch-bot
Copy link

pytorch-bot bot commented May 6, 2025

🔗 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 Failures

As of commit 7a34259 with merge base 5163bf0 (image):
💚 Looks good so far! There are no failures yet. 💚

This comment was automatically generated by Dr. CI and updates every 15 minutes.

@facebook-github-bot
Copy link
Contributor

This pull request was exported from Phabricator. Differential Revision: D73895378

@facebook-github-bot
Copy link
Contributor

This pull request was exported from Phabricator. Differential Revision: D73895378

@facebook-github-bot
Copy link
Contributor

This pull request was exported from Phabricator. Differential Revision: D73895378

@cyyever

This comment was marked as resolved.

@yiming0416

This comment was marked as resolved.

@facebook-github-bot
Copy link
Contributor

This pull request was exported from Phabricator. Differential Revision: D73895378

@zhxchen17

This comment was marked as resolved.

@zhxchen17 zhxchen17 requested a review from Skylion007 May 7, 2025 17:25
@facebook-github-bot
Copy link
Contributor

This pull request was exported from Phabricator. Differential Revision: D73895378

Comment on lines 112 to 125
Copy link
Contributor

Choose a reason for hiding this comment

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

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

Copy link
Contributor Author

Choose a reason for hiding this comment

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

@swolchok This representation of GraphSignature in nativert follows the existingExportGraphSignature (https://docs.pytorch.org/docs/stable/export.html#torch.export.ExportGraphSignature)

Copy link
Contributor Author

Choose a reason for hiding this comment

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

@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.

Comment on lines 125 to 141
Copy link
Contributor

Choose a reason for hiding this comment

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

here we are duplicating the map keys again! can't we just iterate over the map?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

@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?

Copy link
Contributor

@swolchok swolchok May 12, 2025

Choose a reason for hiding this comment

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

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.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

@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.

Copy link
Contributor

Choose a reason for hiding this comment

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

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)

Copy link
Contributor Author

Choose a reason for hiding this comment

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

@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

Copy link
Contributor

Choose a reason for hiding this comment

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

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.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

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?

Copy link
Contributor

Choose a reason for hiding this comment

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

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?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

@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.

Comment on lines 351 to 333
Copy link
Contributor

Choose a reason for hiding this comment

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

if we kept our data nicely deduplicated in the first place we wouldn't have to do this expensive operation here

Copy link
Collaborator

Choose a reason for hiding this comment

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

True, can we not just use an ordered set?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

@Skylion007 do you mind elaborating?

Copy link
Contributor

@malfet malfet left a comment

Choose a reason for hiding this comment

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

Neither RFC nor this PR sheds any light on what is graph signature and why is it needed for native runtime

@Skylion007

This comment was marked as resolved.

@facebook-github-bot
Copy link
Contributor

This pull request was exported from Phabricator. Differential Revision: D73895378

@yiming0416
Copy link
Contributor Author

@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!

@facebook-github-bot
Copy link
Contributor

This pull request was exported from Phabricator. Differential Revision: D73895378

@facebook-github-bot
Copy link
Contributor

This pull request was exported from Phabricator. Differential Revision: D73895378

@facebook-github-bot
Copy link
Contributor

This pull request was exported from Phabricator. Differential Revision: D73895378

@facebook-github-bot
Copy link
Contributor

This pull request was exported from Phabricator. Differential Revision: D73895378

@pytorch-bot pytorch-bot bot added the ciflow/trunk Trigger trunk jobs on your pull request label May 20, 2025
@facebook-github-bot
Copy link
Contributor

This pull request was exported from Phabricator. Differential Revision: D73895378

@facebook-github-bot
Copy link
Contributor

This pull request was exported from Phabricator. Differential Revision: D73895378

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
@facebook-github-bot
Copy link
Contributor

This pull request was exported from Phabricator. Differential Revision: D73895378

@facebook-github-bot
Copy link
Contributor

@pytorchbot merge

(Initiating merge automatically since Phabricator Diff has merged)

@pytorch-bot
Copy link

pytorch-bot bot commented May 20, 2025

This PR has pending changes requested. Please address the comments and update the PR before merging.

@yiming0416
Copy link
Contributor Author

@pytorchbot merge -f "landed internally"

@pytorchmergebot
Copy link
Collaborator

Merge started

Your change will be merged immediately since you used the force (-f) flag, bypassing any CI checks (ETA: 1-5 minutes). Please use -f as last resort and instead consider -i/--ignore-current to continue the merge ignoring current failures. This will allow currently pending tests to finish and report signal before the merge.

Learn more about merging in the wiki.

Questions? Feedback? Please reach out to the PyTorch DevX Team

Advanced Debugging
Check the merge workflow status
here

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

Labels

ciflow/trunk Trigger trunk jobs on your pull request fb-exported Merged topic: not user facing topic category

Projects

None yet

Development

Successfully merging this pull request may close these issues.

8 participants