【问题标题】:Pmap with Euclidean Distance Operations具有欧几里得距离运算的 Pmap
【发布时间】:2018-08-22 16:56:29
【问题描述】:

我对 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:@函数二的分布式版本

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

【问题讨论】:

  • 您希望看到什么以及您看到的哪些不符合这些期望?
  • @Engineero 我已经更新了问题以指定这一点。 F1:期望看到一个简单的欧几里得距离矩阵。 F2:期望看到最小距离而不是整个距离矩阵。 F3:期望看到最小距离和索引位置最小距离出现在第二个数据集中。
  • 我不是 pmap 方面的专家,但是关于您的例程的另外两个 cmets:1) Julia 使用列优先排序(与 C 不同),因此像您在最内层循环中一样遍历列比将问题改写为跨行迭代要慢得多。 2) Distances 包是一个真的写得很好的 Julia 包,所以你正在寻找最佳速度,你应该检查一下。
  • 第三条评论:Number 的子类型,例如浮点数和整数,在 Julia 中是不可变的,所以像 copy(1) 这样的操作是允许的,但不是特别有意义。你可以做x = 0 ; y = x ; y = 1,你会注意到x仍然是0copy 通常用于可变类型,例如数组。
  • @ColinTBowers 感谢您提供信息。我会查看 Distances 包,但乍一看它似乎没有提供计算整个距离矩阵的方法?

标签: julia pmap


【解决方案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 将其转换为矩阵。

【讨论】:

    猜你喜欢
    • 2013-03-02
    • 1970-01-01
    • 2020-11-29
    • 2018-02-14
    • 2013-04-07
    • 2021-01-31
    • 2015-09-23
    相关资源
    最近更新 更多