foo
是一个可调用的示例结构,稍后将有其他字段。由于其中一些字段包含值不断变化的数组,因此不能选择将实例设为const G
。但是,布尔值b
保持不变。有没有一种方法可以告诉编译器,为了启用优化,这个字段永远不会更改?在这个例子中,我希望F
与G
和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)
您没有正确地对F
进行基准测试。这里有一种方法:
julia> @btime $F(1)
0.026 ns (0 allocations: 0 bytes)
2
问题不在于F
是全局非常数变量,而G
是常数,因此当访问F
时,其值在@btime
内不稳定。
在调用前面添加$
会使F
在基准测试期间成为局部变量,然后您可以看到它同样快。
此外,在这种情况下,最好对一些较大的函数进行基准测试。这里有一个快速的例子:
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
此外,您可以使用@code_native
检查F
和G
最终是否具有相同的本地代码:
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)
; └