在Julia中使用变量后,for循环的速度明显变慢

在Julia中使用变量后,for循环的速度明显变慢,julia,Julia,我对以下代码的性能感到非常困惑,在用变量“z=2”替换“2”后,for循环的运行速度要慢得多: 有没有关于原因和如何防止这种延误的想法?谢谢 这是因为z是在全局范围内定义的,并且不是常数,这意味着它可以随时更改值。更重要的是,它也可以改变类型。这会阻止Julia编译器进行大量优化 TLDR:始终尝试并避免在性能关键型操作的全局范围内使用非常量变量 但是,如果将值定义为常量(下面的w示例)或在局部范围内定义变量(下面的y示例),则循环编译为代码的效率与使用文字的效率相同: julia> @e

我对以下代码的性能感到非常困惑,在用变量“z=2”替换“2”后,for循环的运行速度要慢得多:


有没有关于原因和如何防止这种延误的想法?谢谢

这是因为
z
是在全局范围内定义的,并且不是常数,这意味着它可以随时更改值。更重要的是,它也可以改变类型。这会阻止Julia编译器进行大量优化

TLDR:始终尝试并避免在性能关键型操作的全局范围内使用非常量变量

但是,如果将值定义为常量(下面的
w
示例)或在局部范围内定义变量(下面的
y
示例),则循环编译为代码的效率与使用文字的效率相同:

julia> @elapsed for a=1:2:24996
         for b=1:2:24996
         end
       end
1.16e-7

还请注意,您的基准测试存在一些问题

首先,您的基准不计算任何内容。这是一个问题,因为一旦编译器可以自由地进行任何优化,它就会优化所有内容

您在这里测量的运行时更多地与编译相关,而不是与问题的大小相关。例如,请参见以下问题规模增大时发生的情况:

julia> @elapsed for a=1:2:2*24996
         for b=1:2:2*24996
         end
       end
1.21e-7

julia> @elapsed for a=1:2:4*24996
         for b=1:2:4*24996
         end
       end
1.31e-7
其次,建议对封装在函数中的代码执行此类微基准测试,并使用提供的宏(例如
BenchmarkTools.@belapsed
应优先于
@appead
),以便执行更精确的测量,并省略编译时间

解决所有这些问题后,我们以一种更令人信服的方式看到,函数中包含局部变量的代码与包含常量文本的代码一样快:


julia> function foo(n)
           s = 0.
           for a=1:2:n
               for b=1:2:n
                   s += a+b
               end
           end
           s
       end
foo (generic function with 1 method)

julia> @btime foo(24996)
  224.787 ms (0 allocations: 0 bytes)
3.904375299984e12

julia> function foo(n, z)
           s = 0.
           for a=1:z:n
               for b=1:z:n
                   s += a+b
               end
           end
           s
       end
foo (generic function with 2 methods)

julia> @btime foo(24996, 2)
  224.762 ms (0 allocations: 0 bytes)
3.904375299984e12
julia> const w = 2
2

julia> @elapsed for a=1:w:24996
         for b=1:w:24996
         end
       end
1.58e-7
julia> @elapsed let y=2
           for a=1:y:24996
               for b=1:y:24996
               end
           end
       end
1.05e-7
julia> @elapsed for a=1:2:2*24996
         for b=1:2:2*24996
         end
       end
1.21e-7

julia> @elapsed for a=1:2:4*24996
         for b=1:2:4*24996
         end
       end
1.31e-7

julia> function foo(n)
           s = 0.
           for a=1:2:n
               for b=1:2:n
                   s += a+b
               end
           end
           s
       end
foo (generic function with 1 method)

julia> @btime foo(24996)
  224.787 ms (0 allocations: 0 bytes)
3.904375299984e12

julia> function foo(n, z)
           s = 0.
           for a=1:z:n
               for b=1:z:n
                   s += a+b
               end
           end
           s
       end
foo (generic function with 2 methods)

julia> @btime foo(24996, 2)
  224.762 ms (0 allocations: 0 bytes)
3.904375299984e12