There is fundamentally one (and a half) key question in my wall of text above:
- What (non-)local information (e.g.,
const-ness, type, specialization, etc) about the names in the benchmarked expression is stripped? Or retained?- How does
$change that? What’s the goal of a$flag?
- How does
Yes! This is exactly the answer I’m looking for! And then it sounds like the goal of a $ is to treat the value as an argument to a function (without any explicit specialization), trying to hide the fact that the value is a constant from the compiler. Does this mean that we shouldn’t need to manually use the $(Ref(x))[] pattern over a simple $x — and if it’s necessary, is it a bug?
These cases seem like odd ones out:
f() = (z=0.5; @b sin(z)); f() # No constant prop; Implicit argument which the compiler does not know is constant because it discards that information when forming a closure
h(::Type{T}) where {T} = (S = T; @b rand(S)); h(Float64)
In practice, sin(z) and rand(S) will constant-propagate or be type-stable in those respective contexts. I really don’t want to need to think about Julia’s closure-capture rules if I didn’t explicitly write the closure (and especially not if they’re at conflict with the overall goal above).
I really don’t understand what’s happening here:
julia> @b rand((1, 0.0, 1+5im, big(5), big(1.0))) sin
16.304 ns
julia> @b rand((1, 0.0, 1+5im, big(5), big(1.0))) sin
0 ns
It’s also worth noting that BenchmarkTools gives pretty different answers here and I don’t fully appreciate why, either:
julia> @b rand($Float64)
135.854 ns (1.02 allocs: 16.583 bytes)
julia> @btime rand($Float64);
79.287 ns (1 allocation: 16 bytes)