-
Notifications
You must be signed in to change notification settings - Fork 1
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
Rework cat
implementation
#18
Conversation
Codecov ReportAttention: Patch coverage is
Additional details and impacted files@@ Coverage Diff @@
## main #18 +/- ##
==========================================
+ Coverage 72.44% 72.72% +0.28%
==========================================
Files 9 10 +1
Lines 323 308 -15
==========================================
- Hits 234 224 -10
+ Misses 89 84 -5
Flags with carried forward coverage won't be shown. Click here to find out more. ☔ View full report in Codecov by Sentry. 🚀 New features to boost your workflow:
|
I think it is ok, I see that you tried to stick closer to the implementation of I think we can have some compromise between the two approaches, for example: function cat(dims, args...)
# `instantiate` reduces over the `args` and determines a common `CatStyle`,
# returning a new `Catted` with the `CatStyle` stored.
return copy(instantiate(Catted(dims, args...)))
end
function Base.copy(c::Catted)
dest = similar(c)
copyto!(dest, c)
return dest
end
function Base.copyto!(dest::AbstractArray, c::Catted)
cat!(dest, axes(c), c.dims, c.args...)
return dest
end
function cat!(dest, shape, catdims, args...)
# Implementation of `cat!`.
end |
I initially started with a design similar to I agree that sure, the Concretely, I would suggest we avoid the |
I'm a bit concerned about reusing |
It's possible, but then we can still specialize on the types. Also, since we currently don't have that many different sparse types in place, I would much rather have a simple solution that works for now, which we can fix later if need be, instead of a more complicated one that may account for future options, but may also still have to be fixed later because we cannot foresee all possibilities without actual examples. |
I still personally prefer a solution based around a |
I reworked the implementation to include a |
I like the new names, What do you have in mind for how to incorporate this into the rest of the package? I'm curious what you think of: #12 (comment). It seems like those broader questions around what this package should be and how opinionated it should be has implications for what we decide to do with these cat methods. If we go the route of having this package be very unopinionated and not really having any implementations, it might then make sense for this PR to be put in a separate package |
I think I would lean towards having defaults that aren't opinionated, while providing tools for customization. I'm not very enthusiastic about splitting this off into a separate package. This has the drawback that it would then require us to also add the logic of having interfaces and interface promotion rules there, or simply depend on this package anyways. I fear that if we need to have Another somewhat unfortunate factor is that these kinds of solutions don't follow the same format as the other functions, and it's a bit hard to try and fit it into the |
Yeah, I think that would be a bit too much (it would be unfortunate for someone to call
Right, for now I was picturing that if we moved it to a separate package we could depend on this package and the
As you say, I think that is just the nature of the fact that I'm ok keeping it in this package right now, but lets keep it in mind going forward. I would want to have some "philosophy" or guiding principle for what goes in this package vs. in a separate package. Maybe the principle is that if it implements functionality that is close to functionality in Base but provides better customization points based around |
@lkdvos this looks good to me, what are the next steps here? |
Since this one is breaking, I would suggest either merging but not yet tagging, or slightly holding off on merging, because maybe we can simultaneously alter the
|
Sure, that sounds reasonable to do all of those in a single breaking release. So, up to you if you want to merge this and then work on those next, or keep this unmerged and building off of it (I think I prefer not merging this yet since if there are non-breaking things we want to fix in the meantime it would make that easier). |
I'm okay with keeping this open, the other changes should not depend on this anyways |
If tests turn green, I think this should be ready to release.
|
Ready to go from my side. |
Can you tell what's going on with the downstream tests? I would have hoped bumping the version would mean the downstream packages fail during the installation step, while it seems like they are downgrading to some broken state. But maybe what's happening is that the downstream tests aren't all testing direct dependencies, so then they don't have compat entries for DerivableInterfaces. I'm guessing it is fine from the endpoint of a user unless they force DerivableInterfaces to use v0.4, I just want to double check if you see anything we should try to change. |
f = eltype(a) <: Number ? Returns(zero(eltype(a))) : zero! | ||
return @interface interface map!(f, a, a) | ||
end | ||
# TODO: should this be recursive? `map!(zero!, A, A)` might also work? |
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.
The case I can think of where we might want it to be recursive is for the blocks/storage of BlockSparseArray
, which as you know is a sparse array of arrays. Do you know how this definition affects that case? Maybe there we don't ever call zero!(blocks(a))
and we just define zero!(a)
, i.e. define it directly on the block sparse array?
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.
Also, just to clarify, is the idea now that if types want to overload ArrayLayouts.zero!
, they can do some "manually", for example by defining it as DerivableInterfaces.zero!
?
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.
To be fair, for BlockSparseArrays
I would expect a custom implementation anyways, since we probably want to dispatch that to zero!(blocks(a))
, and we would also need a custom implementation for SparsArrayDOK
anyways, since we don't actually want to fill anything at all, but rather delete?
And yes, I think the idea was to decouple this entirely from ArrayLayouts
? I don't have any special opinions about this really, I just want a function to overload when necessary
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.
To be fair, for
BlockSparseArrays
I would expect a custom implementation anyways, since we probably want to dispatch that tozero!(blocks(a))
, and we would also need a custom implementation forSparsArrayDOK
anyways, since we don't actually want to fill anything at all, but rather delete?
That sounds right, I just wanted to make sure I was following along with what the plan is there so I knew how to review this change, and also probe whether we want zero!
to be recursive. My guess is that we would want it to be, though probably we can hold off on that for now since as you say our use cases require custom implementations anyway.
And yes, I think the idea was to decouple this entirely from
ArrayLayouts
? I don't have any special opinions about this really, I just want a function to overload when necessary
That's what I had in mind and I think what we had discussed, I just wanted to make sure we had a plan there that we both agreed on. (I think more generally, we basically want to leave it up to types to overload other interfaces like the ArrayLayouts.jl interface, the broadcast interface, etc. and not have that logic in DerivableInterfaces.jl.)
Actually, I think Pkg is just being smarter than we are: NamedDimsArrays used to depend on |
Hmm ok, I guess that is a bit unfortunate since it would be nice to have the tests fail "properly" if we make breaking changes to DerivableInterfaces.jl, rather than force a downgrade to older package versions. Would it make sense to yank those older versions of those packages that depend on Derive.jl? I'd be ok going a bit "scorched earth" on the ITensorRegistry, we don't really need those older versions and packages to be installable at this point since so much has changed and improved since then. |
Yeah, I think removing these from the registry is more than fair, given that this is not production-ready anyways I don't see the need to be that backwards compatible |
I cooked up a minimal version of the parts of a small adaptation to the Base implementation of
cat
with more well-defined entry-points for customization, and which should be friendly on both inference and invalidations because the dispatching is happening in steps.Let me know how you feel about this and we can think about the most convenient way of integrating this into the rest of the framework.