具有欧氏距离运算的Pmap

时间:2018-08-22 03:16:49

标签: julia pmap

我对Julia编程语言非常陌生,我正在测试一些通常用其他语言执行的欧几里得距离运算。如果串行调用该函数,则该函数起作用,但是pmap调用未返回期望的结果。有人可以看看吗,让我知道我是否正在以正确的方式进行操作? pmap甚至是解决此问题的最佳方法吗?

using Distributed

#Example data
d1 = randn(50000,3) 
d2 = randn(50000,3) 

第一个函数:欧氏距离矩阵

function EDM(m1, m2)
    n1 = size(m1, 1)
    n2 = size(m2,1)
    k = size(m1, 2)
    Dist = zeros(n1,n2)
    for i in 1:n1
        for j in 1:n2
            dtemp = 0
            for a in 1:k
                dtemp += (m1[i,a] - m2[j,a]) ^ 2
            end
            Dist[i,j] = sqrt(dtemp)
        end
    end
    return Dist
end

#pmap call
function pmap_EDM(m1,m2)
    return pmap(EDM, m1, m2)
end

第二个功能:单向最小欧几里得距离

function MED(m1, m2)
    n1 = size(m1, 1)
    n2 = size(m2,1)
    k = size(m1, 2)
    Dist = zeros(n1,1)
    for i in 1:n1
        dsum = Inf
        for j in 1:n2
            dtemp = 0
            for a in 1:k
                dtemp += (m1[i,a] - m2[j,a]) ^ 2
            end
            dtemp = sqrt(dtemp)
            if dtemp < dsum
                dsum = copy(dtemp)
            end
        end
        Dist[i,1] = dsum
    end
    return Dist
end

#pmap call
function pmap_MED(m1,m2)
    return pmap(MED, m1, m2)
end

第三功能:最小欧几里得距离和相应的指数单向

function MEDI(m1, m2)
    n1 = size(m1, 1)
    n2 = size(m2,1)
    k = size(m1, 2)
    Dist = zeros(n1,2)
    for i in 1:n1
        dsum = Inf
        dsum_ind = 0
        for j in 1:n2
            dtemp = 0
            for a in 1:k
                dtemp += (m1[i,a] - m2[j,a]) ^ 2
            end
            dtemp = sqrt(dtemp)
            if dtemp < dsum
                dsum = copy(dtemp)
                dsum_ind = copy(j)
            end
        end
        Dist[i,1] = dsum
        Dist[i,2] = dsum_ind
    end
    return Dist
end

#pmap call
function pmap_MEDI(m1,m2)
    return pmap(MEDI, m1, m2)
end

调用函数

r1 = EDM(d1,d2) #serial
r2 = pmap_EDM(d1,d2)

r3 = MED(d1,d2) #serial
r4 = pmap_MED(d1,d2)

r5 = MEDI(d1,d2) #serial
r6 = pmap_MEDI(d1,d2)

已编辑:

第一个函数应该返回一个简单的欧几里得距离矩阵,其中一个数组中的每一行到第二个数组中的每一行之间的距离。第二个函数和第三个函数是此函数的偏差,以基于一个数组中每一行到另一个数组中每隔一行的最小距离返回这些距离的子集(第三函数返回最小距离的索引位置)。距离似乎无法正确计算,并且使用pmap的后两个函数正在返回nx3矩阵,而不是分别返回nx1和nx2。

编辑2:使用较小数据集显示结果的示例

d1 = randn(5,3) 
d2 = randn(5,3) 

julia> EDM(d1,d2)
5×5 Array{Float64,2}:
 2.60637  3.18867  1.0745    2.60328  1.58608 
 1.2763   2.31037  3.04379   2.74113  2.00452 
 1.70024  2.07731  3.12397   2.60893  2.05932 
 2.44581  1.57345  0.910323  1.08718  0.407675
 3.42936  1.13001  2.18345   1.08764  1.70883 

julia> pmap_EDM(d1,d2)
5×3 Array{Array{Float64,2},2}:
 [0.397928]  [2.39283]   [0.953501]
 [1.06776]   [0.815057]  [1.87973] 
 [0.151963]  [3.05161]   [0.650967]
 [0.571021]  [0.275554]  [0.883151]
 [0.109293]  [0.635398]  [1.58254] 

julia> MED(d1,d2)
5×1 Array{Float64,2}:
 1.0744953977891307 
 1.2762979313081781 
 1.7002448697495505 
 0.40767454400155695
 1.0876399289364607 

julia> pmap_MED(d1,d2)
5×3 Array{Array{Float64,2},2}:
 [0.397928]  [2.39283]   [0.953501]
 [1.06776]   [0.815057]  [1.87973] 
 [0.151963]  [3.05161]   [0.650967]
 [0.571021]  [0.275554]  [0.883151]
 [0.109293]  [0.635398]  [1.58254] 

julia> MEDI(d1,d2)
5×2 Array{Float64,2}:
 1.0745    3.0
 1.2763    1.0
 1.70024   1.0
 0.407675  5.0
 1.08764   4.0

julia> pmap_MEDI(d1,d2)
5×3 Array{Array{Float64,2},2}:
 [0.397928 1.0]  [2.39283 1.0]   [0.953501 1.0]
 [1.06776 1.0]   [0.815057 1.0]  [1.87973 1.0] 
 [0.151963 1.0]  [3.05161 1.0]   [0.650967 1.0]
 [0.571021 1.0]  [0.275554 1.0]  [0.883151 1.0]
 [0.109293 1.0]  [0.635398 1.0]  [1.58254 1.0] 

编辑3:@功能2的分布式版本

using Distributed
using SharedArrays

#Minimum Euclidean Distances Unidirectional
@everywhere function MD(v1, m2)
    n = size(m2, 1)
    dsum = Inf
    for j in 1:n
        dtemp = sqrt((v1[1] - m2[j,1]) ^ 2 + (v1[2] - m2[j,2]) ^ 2 + (v1[3] - m2[j,3]) ^ 2)
        if dtemp < dsum
            dsum = dtemp
        end
    end
    return dsum
end

function MED(m1, m2)
    n1 = size(m1,1)
    Dist = SharedArray{Float64}(n1)
    m3 = SharedArray{Float64}(m2)
    @sync @distributed for k in 1:n1
        Dist[k] = MD(m1[k,:], m3)
    end
    return Dist
end

1 个答案:

答案 0 :(得分:1)

我没有详细介绍您的代码,但是可能是您在错误的代码级别应用了pmap吗? 例如,如果您具有以下序列号

for i = 1:imax
    # do some work
end

您可以这样写:

function function_for_single_iteration(i)
     # do some work
end

pmap(function_for_single_iteration,1:imax)

基本上,pmap会替换(外部)for循环。 在使用pmap之前,我通常首先使用串行map函数来检查是否具有相同的结果。

请注意,pmapmap将返回一个向量。在您的情况下,可能是距离向量的向量。您将需要使用cat将其转换为矩阵。