1

我试图了解 SharedArray 类型的数据是否正在跨进程移动并因此导致开销。

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

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

所以im1im2im1_sharedim2_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 个im1im2副本。
  2. 工作人员(这里是工作人员 2)也列出了 SharedArrays。所以我认为其中任何一个都可能是部分正确的:

    2.1。varinfo()列出工作人员本地工作空间中的所有变量,但 SharedArrays 不存储在这些工作人员的本地内存中。它们只是被列出来暗示工作人员可以访问它们。

    在这种情况下,如果 SharedArrays 只存储一次并且所有工作人员都可以访问它们,为什么这些类型在 Julia 中不是默认的——首先是为了最小化开销?

    2.2 SharedArray 也被复制到每个工作人员,因此每个 SharedArray 有 122 MiB。因此,SharedArrays 相对于 Arrays 的唯一优势是每个工作人员都可以访问。必须将存储的数据复制到每一种方式。

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

您能否帮我对这两种情况(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
4

1 回答 1

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

您可以看到每个工作人员都初始化了它所处理的数组的一个单独部分。

于 2018-12-14T03:07:08.410 回答