并行 for 循环遍历数组的条目,而不与所有工作线程共享它



我正在使用大数据数组,大约是 10^10 个元素。我通过调用某个函数来填充这些数组的条目。所有条目都是独立的,所以我想利用这一点,并通过一个并行的 for 循环同时填充数组,该循环运行一组索引并调用函数。我知道 SharedArrays 以及我通常如何实现这样的事情,但由于我使用的是巨大的数组,我不想在所有工作线程之间共享它们。我想只将我的数组保留在主工作线程上,然后执行并行 for 循环并将每个循环的结果传输到要存储在数组中的主工作线程。

例如,这就是我通常对小数组所做的。

H = SharedArray{ComplexF64}(n,n) #creates a shared array of size n*n
@sync @distributed for i in 1:q 
H[i] = f(i) #f is a function defined on every worker
end

这种构造的问题在于,如果数组 n 的大小太大,则与所有工作线程共享它的效率不是很高。有没有办法解决这个问题?我意识到我的问题可能很幼稚,我为此道歉。

>SharedArray不会在工人中复制!它只是允许所有进程访问相同的内存区域。这确实非常快,因为工人之间没有通信开销。主进程可以简单地查看由工作线程填充的内存区域,仅此而已。

SharedArrays的唯一缺点是所有工作线程都在同一主机上。如果使用DistributedArrays则只会由于进程间通信而添加不必要的分配,因为每个工作线程仅保留其自己的数组部分。

让我们看一下(这是共享和分布式阵列的两个等效代码(:


using Distributed
using BenchmarkTools
addprocs(4)
using SharedArrays
function f1()
h = SharedArray{Float64}(10_000) #creates a shared array of size n*n
@sync @distributed for i in 1:10_000
h[i] = sum(rand(1_000))
end
h
end
using DistributedArrays
@everywhere using DistributedArrays
function f2()
d = dzeros(10_000) #creates a shared array of size n*n
@sync @distributed for i in 1:10_000
p = localpart(d)
p[((i-1) % 2500)+1] = sum(rand(1_000))
end
d
end

现在,板岳

julia> @btime f1();
7.151 ms (1032 allocations: 42.97 KiB)
julia> @btime(sum(f1()));
7.168 ms (1022 allocations: 42.81 KiB)

julia> @btime f2();
7.110 ms (1057 allocations: 42.14 KiB)
julia> @btime sum(f2());
7.405 ms (1407 allocations: 55.95 KiB)

结论:

在单台机器上,执行时间大致相等,但是当使用DistributedArrays时,主节点收集数据会增加大量的内存分配。因此,在一台机器上,您总是希望使用SharedArrays(此外,API 也更简单(。

最新更新