Skip to content
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

Introduce _VarInfo internally to reduce memory footprint in value propagation #189

Merged
merged 46 commits into from
Dec 10, 2024

Conversation

neNasko1
Copy link
Contributor

@neNasko1 neNasko1 commented Nov 6, 2024

Fixes #187 by making the current user-facing Var be a wrapper around a helper class VarInfo, where Var is a pair (VarInfo, PropValue).

The idea is to have VarInfo be the object that is passed around inside of all functions and be pointed to by all Node-s, so concrete propagated values can be garbage collected correctly.

Checklist for implementation

  • Provide better typing around input_prop_values dictionary
  • Fix adapt_node
  • Fix documentation
  • Add a CHANGELOG.rst entry
  • Fix Var-s passed to manual inference
  • Make tests passing

Breaking changes checklist

  • Examine the performance implications?
  • Examine downstream repos, does the change brake anything we rely on?

Copy link
Collaborator

@cbourjau cbourjau left a comment

Choose a reason for hiding this comment

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

Thanks for taking this on and great work to already make the tests pass! I am trying to grok the details of the implementation. While doing so I already left a few high-level comments. I am not quite convinced that the use of a meta class is buying us much with respect to the introduced complexity/scariness of it. Would you mind adding type hints for its use and/or point out where it would provide a mypy-testable benefit compared to a simpler/dynamic structure such as a dict[str, Var]s?

src/spox/_exceptions.py Outdated Show resolved Hide resolved
src/spox/_node.py Outdated Show resolved Hide resolved
src/spox/_node.py Outdated Show resolved Hide resolved
src/spox/_fields.py Outdated Show resolved Hide resolved
src/spox/opset/ai/onnx/ml/v3.py Outdated Show resolved Hide resolved
src/spox/_node.py Outdated Show resolved Hide resolved
src/spox/_node.py Outdated Show resolved Hide resolved
@jbachurski
Copy link
Collaborator

jbachurski commented Nov 9, 2024

Are you sure there isn’t a cleaner way of doing this? Or perhaps some simpler hack. It feels like a significant change.
I wonder if your standpoint on value propagation changed, Christian @cbourjau - it was mostly intended as an experimental side-feature to improve experimentation back when I added it, not something that should be relied on in live systems. So I’m not sure a large change is worth it to improve the GC behaviour.
I’m afraid I won’t be able to help review this as I’m pretty starved on time.

@cbourjau
Copy link
Collaborator

cbourjau commented Nov 9, 2024

Thanks for your feedback @jbachurski ! Let me provide a little more context.

I wonder if your standpoint on value propagation changed, Christian ?

Yes, it did indeed! ndonnx makes it very easy to try out NumPy code with constant arrays. So much so that it is perfectly reasonable to quickly convert large NumPy arrays into ndonnx ones and to throw them at our code. While technically still a "debugging" feature, it is now used very commonly during development and on very large graphs. The value propagation in ndonnx is currently re-implemented there, but I believe it would be cleaner to do it properly here in Spox on the operator level.

@jbachurski
Copy link
Collaborator

While technically still a "debugging" feature, it is now used very commonly during development and on very large graphs. The value propagation in ndonnx is currently re-implemented there, but I believe it would be cleaner to do it properly here in Spox on the operator level.

Curious. Yes, I noticed that it was early on and found it surprising, but I didn't want to question it :)
I imagine it would be cleaner like so indeed – good luck 🍀

I'll let you know in case I come up with something accidentally but yeah, it's unfortunately an extremely busy period for me to think over this design aspect.

@neNasko1 neNasko1 requested a review from cbourjau November 20, 2024 00:20
Copy link
Collaborator

@cbourjau cbourjau left a comment

Choose a reason for hiding this comment

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

I'm afraid running this PR against this branch in ndonnx (which makes extensive use of Spox's value propagation) gives rise to a lot of warnings of the type:

spox._exceptions.InferenceWarning:
 Output type for variable expanded of ai.onnx@21::Unsqueeze was not concrete - ValueError: Tensor int32[...] does not specify the shape -- in ?.

These warnings do not appear when running on spox from the main branch.

You can make pytest fail on these warnings in the ndonnx test suite by running it as follows:

pytest tests -W="error:Output type for variable"

Do you think you can take a look into what is going on here?

src/spox/_var.py Outdated Show resolved Hide resolved
src/spox/_standard.py Outdated Show resolved Hide resolved
src/spox/_standard.py Outdated Show resolved Hide resolved
@neNasko1
Copy link
Contributor Author

neNasko1 commented Nov 28, 2024

I'm afraid running this PR against this branch in ndonnx (which makes extensive use of Spox's value propagation) gives rise to a lot of warnings of the type:

spox._exceptions.InferenceWarning:
 Output type for variable expanded of ai.onnx@21::Unsqueeze was not concrete - ValueError: Tensor int32[...] does not specify the shape -- in ?.

These warnings do not appear when running on spox from the main branch.

You can make pytest fail on these warnings in the ndonnx test suite by running it as follows:

pytest tests -W="error:Output type for variable"

Do you think you can take a look into what is going on here?

This is caused by the fact that validate_types was being called before actually performing the value propagation.

Currently this type-validation is "optional", however AFAIK this is not really optional as validate is not exposed publicly. Should we deprecate this option.

@neNasko1 neNasko1 requested a review from cbourjau November 28, 2024 00:26
Copy link
Collaborator

@cbourjau cbourjau left a comment

Choose a reason for hiding this comment

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

Thanks for looking into the warnings on the ndonnx side! I think this PR is converging :). Could you add type hints to all new functions please?

src/spox/_fields.py Show resolved Hide resolved
src/spox/_node.py Outdated Show resolved Hide resolved
src/spox/_fields.py Show resolved Hide resolved
src/spox/_fields.py Outdated Show resolved Hide resolved
@neNasko1 neNasko1 requested a review from cbourjau December 9, 2024 02:47
Copy link
Collaborator

@cbourjau cbourjau left a comment

Choose a reason for hiding this comment

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

Very nice! I have one very tiny nitpick, and then this is ready! Thank you very much!

CHANGELOG.rst Outdated Show resolved Hide resolved
src/spox/_value_prop.py Outdated Show resolved Hide resolved
@neNasko1 neNasko1 changed the title Split value prop Introduce _VarInfo internally to reduce memory footprint in value propagation Dec 10, 2024
@neNasko1 neNasko1 merged commit 320d57f into main Dec 10, 2024
18 checks passed
@neNasko1 neNasko1 deleted the split-value-prop branch December 10, 2024 10:03
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Value propagation may produce a large memory footprint
3 participants