-
-
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
Define new dot method for abstract vectors #22392
Conversation
@eveydee Sorry for obstructing your PRs. It is great that you contribute. However, I think we should go for the complete separation of dot(x::AbstractVector, y::AbstractVector) = sum(xx'yy for (xx,yy) in zip(x,y) instead of having |
@andreasnoack I'm really glad to receive feedback and hope that I contribute more than cause trouble. I think yours is a much cleaner solution, but it looks like it comes with a performance cost which is quite significant for normal short vectors: julia> dott(x::AbstractVector, y::AbstractVector) = sum(xx'yy for (xx,yy) in zip(x,y))
julia> a = 1:4
julia> @benchmark dot(a, a)
BenchmarkTools.Trial:
memory estimate: 0 bytes
allocs estimate: 0
--------------
minimum time: 22.109 ns (0.00% GC)
median time: 22.961 ns (0.00% GC)
mean time: 23.265 ns (0.00% GC)
maximum time: 91.116 ns (0.00% GC)
--------------
samples: 10000
evals/sample: 997
julia> @benchmark dott(a, a)
BenchmarkTools.Trial:
memory estimate: 128 bytes
allocs estimate: 3
--------------
minimum time: 64.720 ns (0.00% GC)
median time: 68.734 ns (0.00% GC)
mean time: 84.562 ns (15.93% GC)
maximum time: 3.641 μs (97.08% GC)
--------------
samples: 10000
evals/sample: 980 I would imagine this is the reason |
Presumably @andreasnoack's suggestion was mainly for the semantics. We'd probably still want specialized methods for specific types (e.g. arrays of numbers, cases that would call BLAS, arrays of vectors, arrays of matrices, etcetera), and the fallback method should probably be implemented by explicit loops rather than summing a generator. |
Good to hear that. As @stevengj suggests, I'm mainly after the semantics here. It would be great if we had two argument dot(x::AbstractVector{<:Number}, y::AbstractVector{<:Number}) = vecdot(x, y)
function dot(x::AbstractVector, y::AbstractVector)
if length(x) != length(y)
throw(ArgumentError("something"))
end
return isa(first(x)'first(y)) ? vecdot(x,y) : sum(xx'yy for (xx,yy) in zip(x,y))
end and avoid the overhead in the most important cases. The second version would also be fairly fast in the |
I have tried to optimise the |
This is typical: BLAS calls have a fair amount of overhead, but are highly optimized, so the larger the input, the better they fare; the flip side is that they do less well for smaller inputs. |
* Define dot product between Number and AbstractArray * Define dot between abstract arrays * Added docs for dot between arrays * Revert "Define dot product between Number and AbstractArray" This reverts commit d46cdc7. * Define new dot method between AbstractVectors
#22374 undefines
dot
between matrices. The concerns raised in #22220 was thatdot(::Matrix, ::Matrix)
is presently the Euclidean product. This behaviour will be fixed/broken by #22374 and the Euclidean product between matrices will have to be computed by callingvecdot
.There are two main arguments for adding methods between matrices and numbers to
dot
as in this PR:(I don't know how to make #22220 point to this new branch, so I'm making a new PR. Sorry for the noise.)