Julia 并行计算共享Darray
我试图在Julia中实现一个简单的并行算法,用于矩阵上的乘法加法运算。这更是为了理解如何在Julia中进行并行计算,而不是实用性 最终,这应该实现Julia 并行计算共享Darray,julia,Julia,我试图在Julia中实现一个简单的并行算法,用于矩阵上的乘法加法运算。这更是为了理解如何在Julia中进行并行计算,而不是实用性 最终,这应该实现C=C+A*B,其中A、B和C是矩阵。我使用的代码是: function MultiplyAdd!(C::SharedArray{Int64,2}, A::SharedArray{Int64,2}, B::SharedArray{Int64,2}) assert(size(A)[2]==size(B)[1]) const p = si
C=C+A*B
,其中A
、B
和C
是矩阵。我使用的代码是:
function MultiplyAdd!(C::SharedArray{Int64,2}, A::SharedArray{Int64,2}, B::SharedArray{Int64,2})
assert(size(A)[2]==size(B)[1])
const p = size(A)[1] #rows(A), rows(C)
const m = size(A)[2] #cols(A), rows(B)
const n = size(B)[2] #cols(C), cols(B)
# thresh is some threshold based on the number of operations required
# to compute C before we should switch to parallel computation.
const thresh = 190
M = 2*p*m*n
if ( M < thresh )
C += A*B # base case for recursion
elseif ( n >= max(p,m) )
# Partition C and B (Vertical Split)
if (iseven(p))
#even partition of C and B
#MultiplyAdd!( C0, A, B0 )
#MultiplyAdd!( C1, A, B1 )
a = @spawn MultiplyAdd!( C[:,1:convert(Int64,p/2)], A, B[:,1:convert(Int64,p/2)] )
b = @spawn MultiplyAdd!( C[:,1:convert(Int64,p-(p/2))], A, B[:,1:convert(Int64,p-(p/2))])
fetch(a), fetch(b)
else
#odd parition of C and B
a = @spawn MultiplyAdd!( C[:,1:convert(Int64,p/2+0.5)], A, B[:,1:convert(Int64,p/2+0.5)] )
b = @spawn MultiplyAdd!( C[:,1:convert(Int64,p-(p/2+0.5))], A, B[:,1:convert(Int64,p-(p/2+0.5))])
fetch(a), fetch(b)
end
elseif ( p >= m )
# Partition C and A (Horizontal Split)
if (iseven(n))
#even partition of C and A
#MultiplyAdd!( C0, A0, B )
#MultiplyAdd!( C1, A1, B )
a = @spawn MultiplyAdd!(C[1:convert(Int64,n/2),:],A[1:convert(Int64,n/2),:],B)
b = @spawn MultiplyAdd!(C1 = C[1:convert(Int64,n-(n/2)),:], A[1:convert(Int64,n-(n/2)),:], B)
fetch(a), fetch(b)
else
#odd parition of C and A
# MultiplAdd!( C0, A0, B )
# MultiplyAdd!( C1, A1, B )
a = @spawn MultiplyAdd!( C[1:convert(Int64,n/2 + 0.5),:], A[1:convert(Int64,n/2),:], B )
b = @spawn MultiplyAdd!( C[1:convert(Int64,n-(n/2 + 0.5)),:], A[1:convert(Int64,n-(n/2 + 0.5)),:], B )
fetch(a), fetch(b)
end
else
#Begin Serial Recursion
# A is Vertical Split, B is Horizontal Split
#MultiplyAdd!( C,A0,B0 )
#MultiplyAdd!( C,A1,B1 )
if (iseven(m))
MultiplyAdd!( C,A[:,1:convert(Int64,m/2)], B[1:convert(Int64,m/2),:] )
MultiplyAdd!( C,A[:,1:convert(Int64,m-(m/2))], B[1:convert(Int64,m-(m/2) ),:] )
else
MultiplyAdd!( C,A[:,1:convert(Int64,m/2 + 0.5)], B[1:convert(Int64,m/2 + 0.5), :])
MultiplyAdd!( C,A[:,1:convert(Int64,m-(m/2 + 0.5))], B[1:convert(Int64,m-(m/2 + 0.5)), :] )
end
end
end
其次,在我看来,我不应该运行两个@spawn
任务。我应该让第二个是一个多个add!(C、A、B)
在每种情况下调用。换句话说,只需分配a
和fetch(a)
第三,Julia通过引用将数组传递给函数,因此所有的操作不是自然地在相同的C
、A
和B
矩阵上运行吗?就目前情况而言,采取如下措施:
C0 = C[:, 1:p/2]
C1 = C[:, 1:p-p/2]
创建一个全新的对象,这解释了在上述代码中获取函数调用内部的切片。从本质上说,我是在避免在同一个对象上尝试和操作的任务。一定有比我所实施的更好的方法来做到这一点。最后,我想对内存中的相同数据进行操作,只需“在阵列上移动放大镜”就可以并行地对其子集进行操作。这里很难帮助您,因为您还没有真正提出问题。冒着听起来居高临下的风险,我建议你偷看一眼,问一个好问题 至于你的代码,你的方法有几个问题
MultiplyAdd代码>最多只能并行两个工作进程
MultiplyAdd
执行多个调用,如分配新数组的A[:,1:n]
A[:,1:n]
这样的调用将生成Array
对象,而不是SharedArray
对象,因此递归调用MultiplyAdd带有严格键入到SharedArray{Int,2}
的参数的code>将不起作用
MultiplyAdd
不遵守SharedArray
对象的索引方案A
和B
部分需要进行数据传输,这会扼杀并行化代码带来的性能提升。你可以通过跑步看到这一点
for i in procs(A)
@show i, localindexes(A)
end
在您的SharedArray
对象A
上。理想情况下,每个workeri
应该只在自己的本地索引上运行,尽管允许在本地索引边界上共享数据可以帮助您省去一些簿记方面的麻烦
如果您坚持对原型使用SharedArray
s,那么您仍然有选择。SharedArray
有一些好的建议。我发现这个构造
function f(g, S::SharedArray)
@sync begin
for p in procs(S)
@async begin
remotecall_fetch(g, p, S, p)
end
end
end
S
end
使用一些内核函数g
(例如MultiplyAdd!
)通常会在所有参与的工作人员之间很好地并行化操作。显然,您必须决定如何划分执行;平流\u共享文档中的代码>示例是一个很好的指南
你也可以考虑使用朱丽亚。这种并行框架与共享内存计算略有不同。但是,它允许您使用熟悉的迭代构造直接对数组
对象进行操作。将@everywhere
放在函数定义前面,以便在每个进程上定义函数。另外,您可能希望在基本情况下使用muladd
。我昨天问的问题似乎也与此相关@everywhere
修复了该错误。第二个错误随后出现,因为混合了数组和sharedarray。我在前面加了convert(SharedArray
调用递归函数中的每个切片。现在它运行了,但给出了错误的答案,尽管它至少完成了计算。我将检查切片的逻辑,看看为什么会出现这种情况。ooh@xave如果要并行计算,在混合SharedArray
和Array
操作时应该小心el.我认为一个数组
只能被主进程看到。如果你要求一个工作进程参与,那么它就看不到数组
。最终,我根本不是在寻找性能。我只是想在Julia中并行实现一个算法来理解这个进程。这纯粹是一个教育练习。这是alg算法非常简单,如果我不能用它,我将无法做任何不寻常的事情。我不需要使用SharedArray。我只需要设置代码,使其按预期工作,这是一个并行实现的乘法加载项Julia。如果需要,我们可以完全更改所有代码。
function f(g, S::SharedArray)
@sync begin
for p in procs(S)
@async begin
remotecall_fetch(g, p, S, p)
end
end
end
S
end