代码之家  ›  专栏  ›  技术社区  ›  HiroIshida

使用数组访问的循环速度慢

  •  0
  • HiroIshida  · 技术社区  · 6 年前

    我对一个有数组访问和没有数组访问的循环进行了比较,结果发现两者之间的性能差别很大:1.463677秒对0.086808秒。

    @inline dist2(p, q) = sqrt((p[1]-q[1])^2+(p[2]-q[2])^2)
    function rand_gen()
        r2set = Array[]
        for i=1:10000
            r2_add = rand(2, 1)
            push!(r2set, r2_add)
        end
        return r2set
    end
    
    function test()
        N = 10000
        r2set = rand_gen()
        a = [1 1]
        b = [2 2]
    
        @time for i=1:N, j=1:N
            dist2(r2set[i], r2set[j])
        end
    
        @time for i=1:N, j=1:N
            dist2(a, b)
        end
    end
    test()
    
    1 回复  |  直到 6 年前
        1
  •  5
  •   Bogumił Kamiński    6 年前

    制造 r2set https://docs.julialang.org/en/latest/manual/performance-tips/#Avoid-containers-with-abstract-type-parameters-1 ):

    @inline dist2(p, q) = sqrt((p[1]-q[1])^2+(p[2]-q[2])^2)
    function rand_gen()
        r2set = Matrix{Float64}[]
        for i=1:10000
            r2_add = rand(2, 1)
            push!(r2set, r2_add)
        end
        return r2set
    end
    
    function test()
        N = 10000
        r2set = rand_gen()
        a = [1 1]
        b = [2 2]
    
        @time for i=1:N, j=1:N
            dist2(r2set[i], r2set[j])
        end
    
        @time for i=1:N, j=1:N
            dist2(a, b)
        end
    end
    test()
    

    现在的测试是:

    julia> test()
      0.347000 seconds
      0.147696 seconds
    

    现在如果你真的想要速度,使用不可变类型,例如。 Tuple 不是这样的数组:

    @inline dist2(p, q) = sqrt((p[1]-q[1])^2+(p[2]-q[2])^2)
    function rand_gen()
        r2set = Tuple{Float64,Float64}[]
        for i=1:10000
            r2_add = (rand(), rand())
            push!(r2set, r2_add)
        end
        return r2set
    end
    
    function test()
        N = 10000
        r2set = rand_gen()
        a = (1,1)
        b = (2,2)
    
        s = 0.0
        @time for i=1:N, j=1:N
            @inbounds s += dist2(r2set[i], r2set[j])
        end
    
        @time for i=1:N, j=1:N
            s += dist2(a, b)
        end
    end
    test()
    

    你会发现两者的速度相当:

    julia> test()
      0.038901 seconds
      0.039666 seconds
    
    julia> test()
      0.041379 seconds
      0.039910 seconds
    

    注意,我添加了 s

    关键是,如果将数组存储在数组中,那么外部数组将保存指向内部数组的指针,而对于不可变类型,则直接存储数据。