-
Notifications
You must be signed in to change notification settings - Fork 5
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
Question on implementation and type stability #77
Comments
While it's not documented, it's used in many core packages (eg StatsBase, Distributions, ...), so breaking it would break other parts of the pipeline already. The main advantage of |
Interesting. Have you benchmarked this recently? function my_expected_loglikelihood(
gh::GPLikelihoods.GaussHermiteExpectation, lik, q_f::AbstractVector{<:Normal}, y::AbstractVector
)
return sum(expected_loglikelihood(gh, lik, q_fᵢ, yᵢ) for (q_fᵢ, yᵢ) in zip(q_f, y))
end
function my_expected_loglikelihood2(
gh::GPLikelihoods.GaussHermiteExpectation, lik, q_f::AbstractVector{<:Normal}, y::AbstractVector
)
return mapfoldl(qfy -> expected_loglikelihood(gh, lik, qfy[2], qfy[1]), +, zip(y, q_f))
end
function my_expected_loglikelihood3(
gh::GPLikelihoods.GaussHermiteExpectation, lik, q_f::AbstractVector{<:Normal}, y::AbstractVector
)
return mapreduce(qfy -> expected_loglikelihood(gh, lik, qfy[2], qfy[1]), +, zip(y, q_f))
end
So with EDIT: julia> versioninfo()
Julia Version 1.7.2
Commit bf53498635 (2022-02-06 15:21 UTC)
Platform Info:
OS: Linux (x86_64-pc-linux-gnu)
CPU: Intel(R) Core(TM) i7-9700K CPU @ 3.60GHz
WORD_SIZE: 64
LIBM: libopenlibm
LLVM: libLLVM-12.0.1 (ORCJIT, skylake) |
The main point is pairwise summation - while still being fast. |
An example that illustrates my point: julia> using BenchmarkTools, LinearAlgebra
julia> A = vcat(1f0, fill(1f-8, 10^8));
julia> w = ones(Float32, length(A));
julia> f_dot(A, w) = dot(A, w)
f_dot (generic function with 1 method)
julia> f_sum_zip(A, w) = sum(Ai * wi for (Ai, wi) in zip(A, w))
f_sum_zip (generic function with 1 method)
julia> f_sum_broadcasted(A, w) = sum(Broadcast.instantiate(Broadcast.broadcasted(*, A, w)))
f_sum_broadcasted (generic function with 1 method)
julia> f_sum_mapfoldl(A, w) = mapfoldl(+, zip(A, w)) do (Ai, wi)
Ai * wi
end
f_sum_mapfoldl (generic function with 1 method)
julia> f_sum_mapreduce(A, w) = mapreduce(+, zip(A, w)) do (Ai, wi)
Ai * wi
end
f_sum_mapreduce (generic function with 1 method)
julia> f_dot(A, w)
1.9625133f0
julia> f_sum_zip(A, w)
1.0f0
julia> f_sum_broadcasted(A, w)
1.9999989f0
julia> f_sum_mapfoldl(A, w)
1.0f0
julia> f_sum_mapreduce(A, w)
1.0f0
julia> @btime f_dot($A, $w);
42.887 ms (0 allocations: 0 bytes)
julia> @btime f_sum_zip($A, $w);
140.985 ms (0 allocations: 0 bytes)
julia> @btime f_sum_broadcasted($A, $w);
46.262 ms (0 allocations: 0 bytes)
julia> @btime f_sum_mapfoldl($A, $w);
141.182 ms (0 allocations: 0 bytes)
julia> @btime f_sum_mapreduce($A, $w);
141.659 ms (0 allocations: 0 bytes) |
Very nice, thanks. Strangely, |
Yes, |
I see. It seems that something that zips multiple vectors but still allows linear indexing would accomplish the same thing as |
I can't figure out the reason for |
I was studying the implementation of the expected likelihood and stumbled upon this:
GPLikelihoods.jl/src/expectations.jl
Lines 84 to 96 in 498af31
This uses
Broadcast.broadcasted
, which is not documented. If I'm not mistaken, this means that it is not part of Julia's public API, and could break at any point in time. Besides that, I wonder what is the advantage over this:This also seems to be type-stable, while the current implementation isn't.
The text was updated successfully, but these errors were encountered: