在全局变量上行动比传递它们更快?[朱莉娅琅]

Geo*_*ris 1 performance global parameter-passing julia

我刚学完朱莉娅(最重要的是表演技巧!).我意识到使用全局变量会使代码变慢.对此的反措施是将尽可能多的变量传递给函数的参数.因此我做了以下测试:

x = 10.5  #these are globals
y = 10.5

function bench1()  #acts on global
  z = 0.0
  for i in 1:100
    z += x^y
  end
  return z
end

function bench2(x, y)
  z = 0.0
  for i in 1:100
    z += x^y
  end
  return z
end

function bench3(x::Float64, y::Float64) #acts on arguments
  z::Float64 = 0.0
  for i in 1:100
    z += x^y
  end
  return z
end

@time [bench1() for j in 1:100]
@time [bench2(x,y) for j in 1:100]
@time [bench3(x,y) for j in 1:100]
Run Code Online (Sandbox Code Playgroud)

我必须承认结果非常出乎意料,并且与我所读到的内容不一致.结果:

0.001623 seconds (20.00 k allocations: 313.375 KB)
0.003628 seconds (2.00 k allocations: 96.371 KB)
0.002633 seconds (252 allocations: 10.469 KB)
Run Code Online (Sandbox Code Playgroud)

平均结果是,直接作用于全局变量的第一个函数总是比具有所有适当声明的最后一个函数快约2倍,并且不直接作用于全局变量.有人能解释一下为什么吗?

Dav*_*ers 8

另一个问题是以下仍然在全球范围内:

@time [bench1() for j in 1:100]
@time [bench2(x,y) for j in 1:100]
@time [bench3(x,y) for j in 1:100]
Run Code Online (Sandbox Code Playgroud)

你可以从报告的大量分配中看到@time.

将所有这些包装在一个函数中:

function runbench(N)
    x = 3.0
    y = 4.0
    @time [bench1() for j in 1:N]
    @time [bench2(x,y) for j in 1:N]
    @time [bench3(x,y) for j in 1:N]
end
Run Code Online (Sandbox Code Playgroud)

热身runbench(1),然后runbench(10^5)我得到

1.425985 seconds (20.00 M allocations: 305.939 MB, 9.93% gc time)
0.061171 seconds (2 allocations: 781.313 KB)
0.062037 seconds (2 allocations: 781.313 KB)
Run Code Online (Sandbox Code Playgroud)

如预期的那样,在情况2和3中分配的总存储器是8 ^ 5乘以8字节.

道德是几乎忽略实际的时间,只看内存分配,这是有关类型稳定性的信息.

编辑:bench3是朱莉娅的一个"反模式"(即一种未使用的编码风格) - 你不应仅仅为了试图修复类型不稳定而注释类型; 这不是朱莉娅的注释类型.


roy*_*vib 6

我想这主要是因为编译时间.如果我将"主要"代码更改为

N = 10^2
println("N = $N") 

println("bench1")
@time [bench1() for j in 1:N]
@time [bench1() for j in 1:N]

println("bench2")
@time [bench2(x,y) for j in 1:N]
@time [bench2(x,y) for j in 1:N]
Run Code Online (Sandbox Code Playgroud)

它给

N = 100
bench1
  0.004219 seconds (21.46 k allocations: 376.536 KB)
  0.001792 seconds (20.30 k allocations: 322.781 KB)
bench2
  0.006218 seconds (2.29 k allocations: 105.840 KB)
  0.000914 seconds (402 allocations: 11.844 KB)
Run Code Online (Sandbox Code Playgroud)

所以在第二次测量中,bench1()慢于bench2()~2倍.(我省略了,bench3()因为它给出了与之相同的结果bench2().)如果我们增加到N10 ^ 5,编译时间与计算时间相比可以忽略不计,所以我们可以看到bench2()即使在第一次测量中的预期加速.

N = 100000
bench1
  1.767392 seconds (20.70 M allocations: 321.219 MB, 8.25% gc time)
  1.720564 seconds (20.70 M allocations: 321.166 MB, 6.26% gc time)
bench2
  0.923315 seconds (799.85 k allocations: 17.608 MB, 0.96% gc time)
  0.922132 seconds (797.96 k allocations: 17.517 MB, 1.08% gc time)
Run Code Online (Sandbox Code Playgroud)