When I searched about the '$' prefix in Julia, all I could find is that it is for string or expression interpolation. For example, here https://docs.julialang.org/en/v1/base/punctuation/. However, I have seen people' code like
add_broadcast!($y_d, $x_d)
as in this tutorial https://cuda.juliagpu.org/stable/tutorials/introduction/. Here the "$" sign cannot be interpolation, can it? There is nothing about such usage in the functions doc either https://docs.julialang.org/en/v1/manual/functions/. So I am very confused. Any idea is appreciated. Thanks!
The $
sign expressions like you have shown is non-standard Julia code and it typically appears only in expressions passed to macros. This is exactly the case in your example, where the full line is:
@btime add_broadcast!($y_d, $x_d)
which uses @btime
macro from BenchmarkTools.jl. And if you go to Quick Start section there you can read:
If the expression you want to benchmark depends on external variables, you should use $ to "interpolate" them into the benchmark expression to avoid the problems of benchmarking with globals. Essentially, any interpolated variable $x or expression $(...) is "pre-computed" before benchmarking begins:
So in short with @btime
you use $
to "interpolate" them into the benchmarked expression in order to get a correct benchmark results.
The $
sign is used with macros to interpolate also in other packages, e.g. DataFrameMacros.jl.
EDIT:
An example how not using $
affects execution time when referencing to non-const global variable:
julia> using BenchmarkTools
julia> x = 1
1
julia> @btime (y = 0; for _ in 1:10^6 y += x end; y) # slow and a lot of allocations
22.102 ms (999489 allocations: 15.25 MiB)
1000000
julia> @btime (y = 0; for _ in 1:10^6 y += $x end; y) # loop is optimized out
5.600 ns (0 allocations: 0 bytes)
1000000
julia> const z = 1
1
julia> @btime (y = 0; for _ in 1:10^6 y += z end; y) # loop is optimized out
5.000 ns (0 allocations: 0 bytes)
You can think of it as follows. In the above example not using $
is as-if you have created and run the following function:
function temp1()
y = 0
for _ in 1:10^6
y += x
end
y
end
And you get:
julia> @btime temp1()
22.106 ms (999489 allocations: 15.25 MiB)
1000000
While using $
is as if defined x
inside the body of the function like this:
function temp2()
x = 1
y = 0
for _ in 1:10^6
y += x
end
y
end
and now you have:
julia> @btime temp2()
5.000 ns (0 allocations: 0 bytes)
1000000