Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/windows/16.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Julia 朱莉娅:成对距离的嵌套循环真的很慢_Julia - Fatal编程技术网

Julia 朱莉娅:成对距离的嵌套循环真的很慢

Julia 朱莉娅:成对距离的嵌套循环真的很慢,julia,Julia,我有一些代码可以加载2000个二维坐标的csv文件,然后一个名为collision\u count的函数计算彼此之间距离d较近的坐标对数: using BenchmarkTools using CSV using LinearAlgebra function load_csv()::Array{Float64,2} df = CSV.read("pos.csv", header=0) return Matrix(df)' end function collision_coun

我有一些代码可以加载2000个二维坐标的csv文件,然后一个名为
collision\u count
的函数计算彼此之间距离
d
较近的坐标对数:

using BenchmarkTools
using CSV
using LinearAlgebra

function load_csv()::Array{Float64,2}
    df = CSV.read("pos.csv", header=0)
    return Matrix(df)'
end

function collision_count(pos::Array{Float64,2}, d::Float64)::Int64
    count::Int64 = 0
    N::Int64 = size(pos, 2)
    for i in 1:N
        for j in (i+1):N
            @views dist = norm(pos[:,i] - pos[:,j])
            count += dist < d
        end
    end
    return count
end
这比Python代码慢30倍左右:

import numpy as np
import scipy.spatial.distance

pos = np.loadtxt('pos.csv',delimiter=',')

def collision_count(pos, d):
    pdist = scipy.spatial.distance.pdist(pos)
    return np.count_nonzero(pdist < d)

%timeit collision_count(pos, 2)

5.41 ms ± 63 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)
将numpy导入为np
导入scipy.spatial.distance
pos=np.loadtxt('pos.csv',分隔符=',')
def碰撞计数(位置d):
pdist=scipy.space.distance.pdist(位置)
返回np.count_非零(pdist

有没有办法让它更快?那么所有的拨款是怎么回事

我能得到的最快结果如下

using Distances
using StaticArrays
using LinearAlgebra

pos = [@SVector rand(2) for _ in 1:2000]
function collision_count(pos::Vector{<:AbstractVector}, d)
    count = 0
    @inbounds for i in axes(pos,2)
        for j in (i+1):lastindex(pos,2)
            dist = sqeuclidean(pos[i], pos[j])
            count += dist < d*d
        end
    end
    return count
end

请注意,有可能更快的
n log(n)
算法,但对于一个简单的实现来说,这应该是非常接近最优的。

这里有一个解决方案,它不依赖于关于点的维度的特定知识:

Edit:我更新了该函数,使其在索引方面更加健壮。一些
AbstractArray
s的索引不是从1开始的,因此现在我使用
lastindex
而不是
大小

速度实际上接近于
SVector
解决方案。在即将发布的Julia版本1.5中,与OP的代码相比,差异应该小得多,因为
view
s变得更加高效

顺便说一句:删除类型注释,如下所示

count::Int64 = 0
N::Int64 = size(pos, 2)

这只是增加了视觉噪音。

julia你试过使用吗?从内存来看,这个包有一些令人印象深刻的优化……想想看,对于欧几里德距离,可以使用BLAS进行计算,这几乎可以肯定是Python包所做的。因此,为了匹配这种速度,您需要构造Julia代码,使其使用BLAS函数,或者只使用AFAIK为您提供的Distances软件包。您应该使用function
pairwise
from Distances。jl BLAS仅对大型阵列更快。除非每列都很长,否则BLAS可能会非常慢。您对
d
参数的限制太多了。没有理由它不能是与数组eltype不同的类型,例如数组可以容纳浮点,而
d
可以是整数。
@benchmark collision_count($pos, .1)
BenchmarkTools.Trial: 
  memory estimate:  0 bytes
  allocs estimate:  0
  --------------
  minimum time:     1.182 ms (0.00% GC)
  median time:      1.214 ms (0.00% GC)
  mean time:        1.218 ms (0.00% GC)
  maximum time:     2.160 ms (0.00% GC)
  --------------
  samples:          4101
  evals/sample:     1
function collision_count2(pos::AbstractMatrix, d)
    count = 0
    @inbounds for i in axes(pos, 2)
        for j in (i+1):lastindex(pos, 2)
            dist2 = sum(abs2(pos[k, i] - pos[k, j]) for k in axes(pos, 1))
            count += dist2 < d^2
        end
    end
    return count
end
julia> using BenchmarkTools

julia> @btime collision_count(pos, 0.7) setup=(pos=rand(2, 2000));
  533.055 ms (13991005 allocations: 488.01 MiB)

julia> @btime collision_count2(pos, 0.7) setup=(pos=rand(2, 2000));
  4.700 ms (0 allocations: 0 bytes)
count::Int64 = 0
N::Int64 = size(pos, 2)