-
-
Notifications
You must be signed in to change notification settings - Fork 5.5k
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
Make matrix multiplication work for more types #18218
Conversation
cc @mlubin, this may help with JuMP's internal matmul code. |
Couldn't this just be |
@joehuchette, yep |
Along the lines of @andreasnoack, you could define something like (probably with a better name) |
In fact, since 3ace05a and 6fd91b2 were merged, this change has become a lot more important. Indeed, before these commits, @andreasnoack @pabloferz yes we could also do something like that. The main difference is that in the solution of this pull request, if |
In the long run, I hope (specializations of) |
I don't think that the plan is to eventually keep overloading
Since I tried locally the alternative proposed solution and it works just fine. |
@pabloferz I might not understand inference correctly but what scares me a bit is that If you guarantee me that the inference will not use the fact that |
05e2791
to
c5e38fa
Compare
@@ -424,7 +426,7 @@ end | |||
function generic_matmatmul{T,S}(tA, tB, A::AbstractVecOrMat{T}, B::AbstractMatrix{S}) | |||
mA, nA = lapack_size(tA, A) | |||
mB, nB = lapack_size(tB, B) | |||
C = similar(B, promote_op(*, arithtype(T), arithtype(S)), mA, nB) | |||
C = similar(B, promote_op(matprod, arithtype(T), arithtype(S)), mA, nB) |
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 believe you missed two of these below (for matmul2x2
and matmul3x3
)
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.
Yes, you are right. Why aren't they using arithtype
by the way ?
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 guess they just were unintentionally forgot. But, now that you mention it, matprod
also solves (more generally) the problem they where supposed to tackle, so in fact we can remove them and their definitions.
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.
Probably by mistake. But IIUC, arithtype
is only needed to convert Bool
to Int
when doing matrix multiplication, which the promote_op(matprod, ...)
does even without the arithtype
, so no worries here, but maybe a chance for cleanup.
I have removed |
import Base.*, Base.+, Base.zero | ||
immutable TypeA | ||
x::Int | ||
end |
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.
Not that it matters too much, but you can save some space by changing, e.g. TypeA
by Int
, so you only need two new types for the test.
679d266
to
0157d0c
Compare
@tkelman Fixed :) |
Looks like it's being used in DistributedArrays.jl, so better to deprecate than to remove. |
@martinholters I have added a deprecation warning |
@@ -778,6 +778,18 @@ end | |||
@deprecate cholfact!(A::Base.LinAlg.HermOrSym, uplo::Symbol, ::Type{Val{false}}) cholfact!(A, Val{false}) | |||
@deprecate cholfact!(A::Base.LinAlg.HermOrSym, uplo::Symbol = :U) cholfact!(A) | |||
|
|||
# #18218 | |||
function arithtype(T) |
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.
Can't you use the @deprecate
macro like used above?
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.
Doesn't add @deprecate
automatically add an export? We probably don't want that here.
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 don't think I can because the macro is when a function should be used instead of another one. Here there is not replacement.
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.
Makes sense. Thanks.
ff59690
to
81fbf1f
Compare
# #18218 | ||
eval(Base.LinAlg, quote | ||
function arithtype(T) | ||
depwarn("arithtype is deprecated as it is no longer needed in Julia Base.", |
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.
what's the replacement?
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.
Instead of using arithtype
which replaces Bool
by Int
for matrix multiplications, we use an internal method matprod(x, y) = x*y + x*y
which should cover the roll of arithtype
while also being more general.
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.
are packages using this? if so, the deprecation should tell them what to use instead
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.
With this, I mean that there is no need now for arithtype
or anything like it, which used to operate on types. Now its functionality (but not the method itself) is replaced by the definition and use of matprod
.
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.
If packages are using this together with promote_op
then the new way of doing things would be promote_op(matprod, S, T)
instead of promote_op(*, arithtype(S), arithtype(T))
. If packages are using it some other way, they would have to define their own replacement, I guess.
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.
this is not a helpful warning
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.
Yeah, you're right. @blegat Can you specify something more useful? Maybe like
"arithtype is now deprecated. If you were using inside a promote_op call, use promote_op(LinAlg.matprod, Ts...)
instead. Otherwise, if you need its functionality, consider defining it locally."
Of course, it doesn't have to be that if you find a better way to express it.
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.
LinAlg.matprod
right?
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.
Yeah, that's the one (edited above).
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.
Thanks for your help :) I have updated the warning message with your suggestion.
# #18218 | ||
eval(Base.LinAlg, quote | ||
function arithtype(T) | ||
depwarn("arithtype is now deprecated. If you were using it inside a promote_op call, use promote_op(LinAlg.matprod, Ts...) instead. Otherwise, if you need its functionality, consider defining it locally.", |
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.
wrap this over multiple lines
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.
Sorry about that, this is now fixed :)
@blegat There seems to be a small conflict here. Can you please rebase. Then it should be ready to merge. |
Currently it is assumed that the type of a sum of x::T and y::T is T but this may not be the case
@andreasnoack Thanks, that is now rebased :) |
cc @ajkeller34 it appears this broke Unitful.jl http://pkg.julialang.org/logs/Unitful_0.6.log |
I just read that log quickly but it seems like all of those failures could be fixed by defining:
I guess that's not unreasonable: |
@tkelman Fixed. |
I'm not sure having to define addition on types is really the best solution here? |
Yes, ordinarily addition is only defined for quantities, not for units (not to be pedantic, but I've defined it for I had planned on putting more effort/thought into promotion in Unitful once 0.5.1 is out. When inference is working well, it's my understanding that I shouldn't need any of the several |
* Make matrix multiplication work for more types Currently it is assumed that the type of a sum of x::T and y::T is T but this may not be the case * Remove arithtype in matmul and deprecate it
Matrix multiplication does not work for arrays of elements types
T
andS
such that the typeTS = promote_op(*, T, S)
does not satisfyTS == promote_op(+, TS, TS)
.For example, in this package, I have the type
Term
which is one term of a polynomial and the typePolynomial
which is the sum of several terms.Suppose I am trying to compute
A * x
whereA
is a matrix ofInt64
andx
is a vector ofTerm
.Then
TS
will beTerm
so it will allocate a vector ofTerm
to store the result. However when doing the sum ofTerm
it will getPolynomial
so what should have been allocated is a vector ofPolynomial
.The fix is simple, allocate an array of type
promote_op(+, TS, TS)
.