-
Notifications
You must be signed in to change notification settings - Fork 499
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 clone functionality for module and containers #1111
Conversation
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.
@benborder — this CRTP idea is a nice one. If I'm being honest, I think breaking the existing API is fine, and there's a way we could do this which would be pretty minimally invasive. tl;dr -- I think we can add a pure virtual clone()
one the base Module
/Container
and implement things that way. Module
already being pure means this is pretty simple as is.
Downstream users that use module but want its copy constructor can and should implement copy
if they want this functionality. If they don't, they can raise an exception when updating. FL is still in a stage where we're not as concerned about keeping the API perfect -- we're still iterating and have the luxury of making decisions (like this one!). Keeping this as a method on the class avoids some additional inheritance complexity which in my opinion significantly complexifies the interface and type hierarchy.
Enables users to easily add cloning for standard Modules and Containers
A few simple ways to deal with this being optional:
- users can make their types' copy constructors of they don't want to play by copy constructor rules
- users can throw exceptions in copy methods
Let me know what you think. I'll leave more specific code comments after we figure out direction.
@jacobkahn The intention with this approach was to avoid any breaking changes while minimising the amount of code added/changed. Given breaking changes are an option, the approach you suggest is definitely a better one. It would be good to get some clarification on the desired behaviour of This would mean simple modules like activation functions can continue to use the compiler generated copy constructor. Furthermore, if the copy constructor is assumed to perform a deep copy there would be no need for a |
Agree -- let's think about this. My thoughts:
A pure virtual |
adf4351
to
4c9cf15
Compare
I generally agree. I think requiring users to implement their own I've made changes to reflect this. ModuleTest builds and passes, but I'll wait until we agree on a direction before addressing the remaining build failures from |
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.
Looks like CI is failing because some classes are still missing clone()
implementations -- flashlight/fl/contrib
modules need this as well. Would be great if you could update flashlight/pkg
too while you're at it. CI baselines for those coming soon.
…and containers and their subclasses
45fb066
to
eb8685e
Compare
eb8685e
to
23de9a2
Compare
@jacobkahn I went though and fixed up all the compile issues. I added copy constructors and copy assignment operators where the implementation was simple enough or the module/container provided core functionality. For the remaining I added a runtime exception indicating cloning is not implemented. Something to note. Due to adding copy constructors to perform a deep copy of a modules variables etc, existing code may not function as expected. For example the There is one potential issue I foresee with the current implementation of cloning, which is the handling of shared modules between multiple modules/containers. For example, in the |
Prev behavior would be desired. Any existing user code which uses the weird behavior should be changed anyways, as there's inherent ambiguity in the old system. If you're sharing module state very explicitly, you should use pointers or references, else use the copy ctor. Tw other things as discussed offline:
|
After offline discussion with @jacobkahn about if Modules should fully deep copy their parameters circumventing COW semantics, or deep copy using COW semantics if implemented in the backend, identifying some potential edge case issues and resolving some misunderstandings on my part, we agreed:
The following changes were made:
|
@jacobkahn has imported this pull request. If you are a Meta employee, you can view this diff on Phabricator. |
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.
Leaving some preliminary comments first — will in parallel start reviewing everything else.
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 might make sense to add a small test fixture to test copying basic modules (make sure behavior is the same; this can also serve as a chance to test that parameters aren't shared) as well as a test for copying a basic compositional Container
. Would you be able to add those in this PR as well?
@benborder has updated the pull request. You must reimport the pull request before landing. |
@jacobkahn has imported this pull request. If you are a Meta employee, you can view this diff on Phabricator. |
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.
Final stretch! Just a few more comments. Thanks for bearing with me on this. I'll rebase this branch shortly.
@benborder has updated the pull request. You must reimport the pull request before landing. |
@jacobkahn has imported this pull request. If you are a Meta employee, you can view this diff on Phabricator. |
@benborder has updated the pull request. You must reimport the pull request before landing. |
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.
🎉 I think we're ready to merge this after
- rebasing
- CI still being green enough
- double checking any new non-class functions are explicitly exported via FL_API (I don't think there are any)
Cheers to sticking with this PR -- this makes so many semantics clearer and behaviorS more explicit. A huge step towards a less bug prone set of interfaces on modules, and sensible copy semantics throughout FL!
Awesome! Agreed, it's a solid set of improvements. Glad we can get it over the line! |
@benborder has updated the pull request. You must reimport the pull request before landing. |
@jacobkahn has imported this pull request. If you are a Meta employee, you can view this diff on Phabricator. |
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.
A few final lints
@benborder has updated the pull request. You must reimport the pull request before landing. |
@benborder has updated the pull request. You must reimport the pull request before landing. |
@jacobkahn has imported this pull request. If you are a Meta employee, you can view this diff on Phabricator. |
@benborder has updated the pull request. You must reimport the pull request before landing. |
@benborder has updated the pull request. You must reimport the pull request before landing. |
@jacobkahn has imported this pull request. If you are a Meta employee, you can view this diff on Phabricator. |
@jacobkahn merged this pull request in f354e7f. |
Original Issue: #1110
closes #1110
Summary
Adds cloning functionality to modules and containers by adding a pure virtual
clone()
method toModule
.clone()
performs a deep copy of parameters and modules, taking advantage of the underlying tensors copy on write semantics if implemented by the backend in order to minimise memory usage.clone()
. This has been done for the core library and some simpler modules in pkg, the remaining will throw a runtime error indicating clone is unimplmented.Variable
.FL_BASIC_CONTAINER_CLONING
where possible, which implementsclone()
as well as appropriate copy, assignment and move constructors.FL_BASIC_CONTAINER_CLONING
macro, but implement their ownclone()
override method as well as copy, assignment and move constructors to achieve their desired behaviour.Test Plan (required)
Added some tests and successfully ran locally. Also use CI.