朱莉娅:构造恒定场以优化性能



foo是一个可调用的示例结构,稍后将有其他字段。由于其中一些字段包含值不断变化的数组,因此不能选择将实例设为const G。但是,布尔值b保持不变。有没有一种方法可以告诉编译器,为了启用优化,这个字段永远不会更改?在这个例子中,我希望FGH一样快。

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检查FG最终是否具有相同的本地代码:

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)
; └

相关内容

  • 没有找到相关文章

最新更新