我用一个隐式格式来求解PDE,它可以在每一时间步划分成两个矩阵,然后由一个边界条件连接起来(也是在每个时间步骤)。我试图通过使用多个处理来同时反演两个矩阵来加速这个过程。
下面是一个很小(非PDE解决方案)示例中的示例。
using Distributed
using LinearAlgebra
function backslash(N, T, b, exec)
A = zeros(N,N)
α = 0.1
for i in 1:N, j in 1:N
abs(i-j)<=1 && (A[i,j]+=-α)
i==j && (A[i,j]+=3*α+1)
end
A = Tridiagonal(A)
a = zeros(N, 4, T)
if exec == "parallel"
for i = 1:T
@distributed for j = 1:2
a[:, j, i] = A\b[:, i]
end
end
elseif exec == "single"
for i = 1:T
for j = 1:2
a[:, j, i] = A\b[:, i]
end
end
end
return a
end
b = rand(1000, 1000)
a_single = @time backslash(1000, 1000, b, "single");
a_parallel = @time backslash(1000, 1000, b, "parallel");
a_single == a_parallel问题来了:最后一行计算为真,速度提高了6倍,但只有2倍是可能的。我做错什么了?
发布于 2022-07-12 15:08:43
您正在测量的编译时间prematurely
@distributed循环退出
@distributed循环不收集结果
因此,很明显,你有:
julia> addprocs(2);
julia> sum(backslash(1000, 1000, b, "single")), sum(backslash(1000, 1000, b, "parallel"))
(999810.3418359067, 0.0)因此,为了使代码工作,您需要从分布式循环中收集数据,这些数据可以这样做:
function backslash2(N, T, b, exec)
A = zeros(N,N)
α = 0.1
for i in 1:N, j in 1:N
abs(i-j)<=1 && (A[i,j]+=-α)
i==j && (A[i,j]+=3*α+1)
end
A = Tridiagonal(A)
a = zeros(N, 4, T)
if exec == :parallel
for i = 1:T
aj = @distributed (append!) for j = 1:2
[A\b[:, i]]
end
# you could consider using SharedArrays instead
a[:, 1, i] .= aj[1]
a[:, 2, i] .= aj[2]
end
elseif exec == :single
for i = 1:T
for j = 1:2
a[:, j, i] = A\b[:, i]
end
end
end
return a
end现在你得到了同样的结果:
julia> sum(backslash2(1000, 1000, b, :single)) == sum(backslash2(1000, 1000, b, :parallel))
true但是,对于只需几毫秒就能执行的循环来说,分布式代码效率很低,因此在本例中,当您运行1000次@distributed代码时,执行它将花费很多倍的时间,而且每次分派分布式作业需要大约几毫秒的时间。
也许您的生产任务需要更长的时间,所以它比有意义。或者您可能会考虑使用Threads.@threads。
最后但并非最不重要的是,BLAS可能被配置为多线程,并且在这个场景中,在一台机器上并行化可能没有意义(取决于场景)。
https://stackoverflow.com/questions/72954273
复制相似问题