Julia中跨进程的SharedArray和数据移动

时间:2018-12-13 01:30:21

标签: memory-management parallel-processing julia pmap

我试图了解SharedArray类型的数据是否在进程间移动,从而导致开销。

在我的Main模块(过程1)中定义了变量之后,我在数据的Array( im1 )和SharedArray( im1_shared )版本上调用了pmap。

pmap(someFunction(im1, im2, x), iterations)
pmap(someFunction(im1_shared, im2_shared, x), iterations) 

因此 im1 im2 im1_shared im2_shared 是默认参数,并且分片使用迭代器x,由工作人员处理。

使用

@fetchfrom 2 varinfo()

我得到:

  

im1 122.070 MiB 4000×4000阵列{Float64,2}

     

im2 122.070 MiB 4000×4000阵列{Float64,2}

     

im1_shared 122.071 MiB 4000×4000 SharedArray {Float64,2}

     

im2_shared 122.071 MiB 4000×4000 SharedArray {Float64,2}

所以我对此的想法和困惑:

  1. 在对Array类型进行pmap函数调用期间,将im1和im2复制到所有其他3个辅助线程中。最后,我的记忆中有4个 im1 im2 副本。
  2. 工作程序(此处为工作程序2)也列出了SharedArrays。因此,我认为其中任何一个都可能部分正确:

    2.1。 varinfo()列出了工作程序的本地工作区中的所有变量,但SharedArrays未存储在这些变量的本地内存中。列出它们只是暗示一个工人可以访问它们。

    在这种情况下,如果SharedArrays仅存储一次并且所有工作人员都可以访问它们,那么为什么这些类型在Julia中没有默认设置-首先将开销降至最低?

    2.2 SharedArray也被复制到每个工作线程,因此每个SharedArray的122 MiB。因此,SharedArrays优于Arrays的唯一优势是每个工作人员的访问权限。存储的数据必须以任何一种方式复制。

    在这种情况下,避免开销的唯一方法是使用分布式数组之类的方法,让工作人员仅对已经可以访问/已存储在内存中的块进行操作,对吧? < / p>

请您帮我整理一下这两种情况(2.1和2.2)。

更新1:这是一个有效的示例:

@everywhere using InteractiveUtils # to call varinfo() on all workers

### FUNCTIONS
@everywhere function foo(x::Array{Float64, 2}, y::Array{Float64, 2}, t::Int64)
    #just take a slice of both arrays at dfined steps and sum the values
    x_slice = x[t:t+5, t:t+5]
    y_slice = y[t:t+5, t:t+5]
    return x_slice + y_slice   
end

@everywhere function fooShared(x::SharedArray{Float64, 2}, y::SharedArray{Float64, 2}, t::Int64)
    #just take a slice of both arrays at dfined steps and sum the values
    x_slice = x[t:t+5, t:t+5]
    y_slice = y[t:t+5, t:t+5]
    return x_slice + y_slice   
end

### DATA
n = 1000
#the two Arrays
im1 = rand(1.0:2.0, n, n)
im2 = copy(im1);

#The two shared arrays
im1_shared = SharedArray(im1)
im2_shared = SharedArray(im2);

@fetchfrom 2 varinfo() # im1_shared and im2_shared are not yet listed, of course not...

pmap(x -> foo(im1, im2, x), [1, 2, 3, 4, 5, 6, 7, 8, 9, 10])
pmap(x -> fooShared(im1_shared, im2_shared, x), [1, 2, 3, 4, 5, 6, 7, 8, 9, 10])

@fetchfrom 2 varinfo() # im1_shared and im2_shared are now listed

1 个答案:

答案 0 :(得分:1)

SharedArray通过内存映射(https://docs.julialang.org/en/v1/stdlib/Mmap/index.html)在许多Julia进程之间共享。数据可以通过以下方式初始化:

using Distributed
Distributed.addprocs(2);
@everywhere using SharedArrays
@everywhere function ff(ss::SharedArray)
   println(myid()," ",localindices(ss))
   for ind in localindices(ss)
       ss[ind] = rand(1.0:2.0)    
   end   
end

现在让我们执行实际的初始化:

julia> s = SharedArray{Float64}((1000,1000),init=ff)
      From worker 2:    2 1:500000
      From worker 3:    3 500001:1000000
1000×1000 SharedArray{Float64,2}:
 2.0  1.0  1.0  1.0  1.0  2.0  …  2.0  1.0  2.0  2.0  1.0
 2.0  2.0  2.0  2.0  2.0  2.0     2.0  1.0  2.0  1.0  2.0
 2.0  1.0  1.0  2.0  1.0  2.0     1.0  1.0  1.0  1.0  2.0
 ⋮                        ⋮    ⋱  ⋮
 1.0  1.0  1.0  1.0  1.0  2.0     2.0  2.0  1.0  1.0  1.0
 1.0  2.0  1.0  2.0  2.0  1.0     2.0  2.0  1.0  1.0  1.0
 2.0  2.0  1.0  2.0  1.0  2.0     2.0  1.0  1.0  2.0  2.0

您可以看到,每个工作程序都初始化了其处理的数组的单独部分。