Reputation: 51
foo
is a callable example struct that will have additional fields later. Since some of these fields hold arrays with changing values it's not an option to make the instance a const G
. However, the boolean value b
stays constant. Is there a way to tell the compiler that this field will never change in order to enable optimizations? In this example I would like F
to be as fast as G
and H
.
using BenchmarkTools
struct foo
b::Bool
end
function (f::foo)(x)
if f.b
x+1
end
end
F = foo(true)
const G = foo(true)
H(x) = x+1
@btime F(1) # 12.078 ns (0 allocations: 0 bytes)
@btime G(1) # 0.023 ns (0 allocations: 0 bytes)
@btime H(1) # 0.024 ns (0 allocations: 0 bytes)
Upvotes: 2
Views: 403
Reputation: 69949
You are not benchmarking the F
correctly. Here is a way to do it:
julia> @btime $F(1)
0.026 ns (0 allocations: 0 bytes)
2
The problem is not that F
is a global non-constant variable while G
is a constant, so when accessing F
its value is not stable within @btime
.
Adding a $
in front of the call makes F
a local variable during a benchmark and you can then see that it is equally fast.
Also it is probably better to benchmark some larger functions in such cases. Here is a quick example:
julia> function test(x)
s = 0
for i in 1:10^6
s += x(1)
end
s
end
test (generic function with 1 method)
julia> @btime test($F)
35.830 μs (0 allocations: 0 bytes)
2000000
julia> @btime test($G)
35.839 μs (0 allocations: 0 bytes)
2000000
Also you can check with @code_native
that F
and G
end up with identical native code:
julia> @code_native F(1)
.text
; ┌ @ REPL[10]:2 within `foo'
cmpb $0, (%rsi)
je L17
; │ @ REPL[10]:3 within `foo'
; │┌ @ int.jl:53 within `+'
addq $1, %rdx
; │└
movq %rdx, (%rdi)
movb $2, %dl
xorl %eax, %eax
retq
L17:
movb $1, %dl
xorl %eax, %eax
; │ @ REPL[10]:3 within `foo'
retq
nopw %cs:(%rax,%rax)
; └
julia> @code_native G(1)
.text
; ┌ @ REPL[10]:2 within `foo'
cmpb $0, (%rsi)
je L17
; │ @ REPL[10]:3 within `foo'
; │┌ @ int.jl:53 within `+'
addq $1, %rdx
; │└
movq %rdx, (%rdi)
movb $2, %dl
xorl %eax, %eax
retq
L17:
movb $1, %dl
xorl %eax, %eax
; │ @ REPL[10]:3 within `foo'
retq
nopw %cs:(%rax,%rax)
; └
Upvotes: 2