Julia:不相似矩阵计算的有效并行化

时间:2014-07-21 20:35:06

标签: parallel-processing julia

Julia语言通过pmat()和@parallel等方法支持并行化。

我正在尝试为一组数据计算相异度矩阵:

n = length(dataset)
mat = zeros(n,n)
for i = 1 : n
    for j = i+1 : n
        mat[i,j] = mat[j,i] = f_dist(dataset[i], dataset[j])
    end
end

由于计算是独立的,我认为这应该是并行计算的一个很好的选择。

我尝试使用pmat()和@parallel都变慢了。

mat = @parallel (+) for comb in collect(combinations([1:n],2))
    submat = zeros(n,n)
    i = comb[1]
    j = comb[2]
    dist = f_dist(dataset[i],dataset[j])
    submat[i,j] = dist
    submat[j,i] = dist
    submat
end

我知道@parallel是一个糟糕的方式,因为我基本上创建了一堆稀疏矩阵并将它们加在一起。非常低效。

有没有一种有效的方法让它发挥作用?我尝试过SharedArrays和DistributedArrays,但还没有想出如何做我想做的事。

谢谢。

1 个答案:

答案 0 :(得分:4)

使用SharedArrays它应该是相当简单的:这个代码是我的头脑而未经过测试,但是类似

mat = SharedArray(Float64, n, n)
combs = collect(combinations([1:n],2))
chunkbreaks = linspace(0, length(combs), nworkers()+1)
@sync begin
    for (i,wpid) in enumerate(workers())
        @async begin
            remotecall_wait(wpid, myfunc, mat, combs[chunkbreaks[i]+1:chunkbreaks[i+1]])
        end
    end
end

其中myfuncmat的指定索引执行计算。

但是,我应该补充一点,除非你的相似度计算很慢,否则序列化combs可能会比单线程版本慢。你可以通过提出一个更快的策略来解决分配给每个进程的索引(可以只用UnitRange{Int}进行编码并使用divrem来计算出i,j索引来解决这个问题。 )。