-
Notifications
You must be signed in to change notification settings - Fork 9
Add deduplication pass for initializer tensors #67
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
Add deduplication pass for initializer tensors #67
Conversation
Signed-off-by: Abhishek Herbert Samuel <[email protected]>
Signed-off-by: Abhishek Herbert Samuel <[email protected]>
f99fa0c
to
ae8f078
Compare
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.
It’s fine to use an AI for contribution. Please ensure however that the code actually works
Thank you for the feedback, Justin. I'll check if it works and then only send it here. |
…bgraph traversal Address reviewer feedback: - Optimized memory by grouping by dtype and shape before comparing values - Used iterate_graph to handle subgraphs - Validated on normal and subgraph models; deduplication works as expected Signed-off-by: Abhishek Herbert Samuel <[email protected]>
Signed-off-by: Abhishek Herbert Samuel <[email protected]>
Hi @justinchuby, I've pushed the finalized implementation and test as separate, signed commits. The following have been addressed: DeduplicateInitializersPass: Added under passes/common, follows repo conventions, uses (dtype, shape) → {tobytes: name} grouping for memory efficiency, and traverses all subgraphs via RecursiveGraphIterator. Test coverage: A dedicated unittest verifies correct deduplication in the main graph and ensures subgraphs remain isolated. Coding standards: Followed the structure and documentation style of other passes (e.g., topological_sort.py). Commit signed: Used -s with a clean message summarizing the functionality. I have also attached a screenshot of the unit test which passed successfully on my local copy of this repository. Please let me know if any final changes are needed. Thanks again for your guidance and mentorship throughout this PR! |
Please feel free to ask questions when you are going through the code base or need help understanding parts of the code. It would be helpful to take a look at other existing passes and usages to ensure they are implemented in a similar style. |
My concern with this pass in particular is that we are using the full bytes in the look up table. This is memory intensive. I wonder if there is a good (efficient) hash method that can be apply to the bytes content, and use the hash value in the look up table. Only when the hash matches do we compare the actual bytes. |
Hi @justinchuby, I’ll update the class to inherit from ir.passes.InPlacePass as suggested and move the main logic into the call method, following the repo’s conventions (like in constant_manipulation.py). Regarding the memory concern: Will push the changes shortly. Please let me know if I missed anything else. Appreciate your guidance! Warm regards, |
- Implemented DeduplicateInitializersPass to remove redundant initializers with identical shape, dtype, and values within individual graphs. - Ensured deduplication is confined to the same graph scope (no cross-subgraph merging). - Added unit tests covering: - Exact duplicates - Different shapes/dtypes - Scalars - Multiple duplicates - Non-deduplicable distinct values - Removed subgraph-related tests due to ONNX serialization behavior omitting their initializers. Signed-off-by: Abhishek Herbert Samuel <[email protected]>
Hi @justinchuby, Tests involving subgraph initializers were removed, as ONNX drops those during serialization, making them unreliable to assert against. Let me know if you'd like a different strategy for subgraph coverage. Thanks again for your guidance throughout! Warm regards, |
Codecov ReportAttention: Patch coverage is
Additional details and impacted files@@ Coverage Diff @@
## main #67 +/- ##
==========================================
+ Coverage 74.39% 74.44% +0.05%
==========================================
Files 37 38 +1
Lines 4648 4673 +25
Branches 950 954 +4
==========================================
+ Hits 3458 3479 +21
- Misses 839 841 +2
- Partials 351 353 +2 ☔ View full report in Codecov by Sentry. |
Signed-off-by: Abhishek Herbert Samuel <[email protected]>
a00be10
to
6b3e0b7
Compare
Signed-off-by: Abhishek Herbert Samuel <[email protected]>
Signed-off-by: Abhishek Herbert Samuel <[email protected]>
Sure @justinchuby, will fix it and maintain code consistency :) |
Thank you @xadupre @inisis @justinchuby for the feedback. Will make the requested changes and ensure that the PR is ready to be merged. |
…nd size limit - Avoids comparing large tensors >1024 elements to reduce performance overhead - Compares shape and dtype before accessing tensor content - Adds test coverage for subgraph deduplication (If node branches) - Passes all linters: ruff, mypy, editorconfig Signed-off-by: Abhishek Herbert Samuel <[email protected]>
@xadupre @justinchuby @inisis I have made the requested changes. Please check and let me know if it's ready for merging or if other changes need to be made prior to that. Thank you once again :) |
Hi @justinchuby, is the code I submitted fine? Please let me know if there are any issues so that I can resolve it. As of now it's showing that 20/21 checks have passed (with 1 skipped). |
Will take a look soon, thanks! |
Signed-off-by: Justin Chu <[email protected]>
Signed-off-by: Justin Chu <[email protected]>
Signed-off-by: Justin Chu <[email protected]>
…test.py Signed-off-by: Justin Chu <[email protected]>
Thank for your contribution. I updated your code to simplify some of the logic and moved to do simple byte comparison for now because we have a small enough size limit. |
Signed-off-by: Justin Chu <[email protected]>
Signed-off-by: Justin Chu <[email protected]>
Signed-off-by: Justin Chu <[email protected]>
Signed-off-by: Justin Chu <[email protected]>
Signed-off-by: Justin Chu <[email protected]>
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.
Pull Request Overview
This pull request adds a new graph transformation pass to deduplicate initializer tensors based on their content, data type, and shape.
- Introduces DeduplicateInitializersPass to remove redundant initializer tensors.
- Adds unit tests to verify deduplication behavior across various scenarios.
Reviewed Changes
Copilot reviewed 2 out of 2 changed files in this pull request and generated no comments.
File | Description |
---|---|
src/onnx_ir/passes/common/initializer_deduplication_test.py | Adds unit tests for deduplication behavior |
src/onnx_ir/passes/common/initializer_deduplication.py | Implements the deduplication pass for initializer tensors |
@justinchuby thank you for the mentorship and support throughout this PR. This was my first time contributing to an open source repository and I learnt a lot through this process. @xadupre @inisis @titaiwangms thank you for the constructive suggestions on this PR and related PR's (98,99) which helped bring this to completion. Looking forward to learning and building more in the ONNX community :) Warm regards, |
Summary
This PR adds a new graph transformation pass:
DeduplicateInitializersPass
.It removes duplicate initializer tensors (typically model weights) based on a unique fingerprint derived from:
tobytes()
)dtype
)All redundant initializers are removed, and nodes referencing them are updated to use the canonical (first-seen) tensor.
Implementation Details
(tobytes, dtype, shape) → name
graph.initializers.pop(...)
node.replace_input_with(...)
for correctness and safetyBenefits
File Added
src/onnx_ir/passes/common/deduplicate_initializers.py
Closes
Closes #66