interpolation - 如何在工作进程中的 SharedArray 上使用插值,而无需每个进程创建自己的数据副本?

标签 interpolation julia shared-memory

我目前在 64 位 Debian Stretch(“测试”)中使用 Julia 0.4.6。我目前在 4 核 4GB VM 中使用它。

我基本上想做的是让主进程设置一个 3D SharedArray,然后在工作进程上并行生成从该 3D 数组派生的 2D 数组。问题是,如果我希望工作人员通过插值访问该卷(所有卷,因为我无法预测他们实际需要哪些位),我似乎遇到了内存使用率过高的问题。

这是一些演示我正在尝试做的事情的最小代码...

首先是插值免费版本:

# Initialize 1GByte of SharedArray
volume=SharedArray(Float32,(512,512,1024))  # 1 GByte of shared data
volume[:,:,:]=rand(Float32,(512,512,1024))

# Function to compute directly from array
function test0()
  image=SharedArray(Float32,(512,512))
  @sync @parallel for y=1:512
    for x=1:512
      image[x,y]=volume[x,y,512]
    end
  end
  sdata(image)
end

println(mean(test0()))

无论我是在没有 worker 的情况下运行它还是在 -p 2、-p 4、-p 8 或 -p 16 的情况下运行它都很好(没有太多的性能改进,但请记住这只是一个模型在每次迭代中做更多的计算)。

但是这个版本:

using Interpolations

# Function to compute via interpolator
function test1()
  sampler=interpolate(volume,BSpline(Linear()),OnGrid())

  image=SharedArray(Float32,(512,512))

  @sync @parallel for i=1:512*512
    x,y=ind2sub((512,512),i)
    image[x,y]=sampler[x,y,512]
  end
  sdata(image)
end

println(mean(test1()))

使用 -p 2 启动系统交换,-p 4 使工作程序以 OutOfMemoryError 终止。

猜测是插值器到工作进程的序列化忽略了它位于 SharedArray 上的事实,只是将数据批量复制到非共享副本中每个 worker 。

我的问题是:我可以做些什么来改进它?对于我在这里尝试做的事情,有没有更好的模式,或者巧妙地使用 @<something>这会导致每个 worker 插入共享数组而不是它自己的副本?

更新:

这种方法似乎可以有效地将插值对象的创建推送到每个工作进程中:

function test(volume)

  image=SharedArray(Float32,(512,512))

  sampler=Nullable()

  @sync @parallel for i=1:512*512
    x,y=ind2sub((512,512),i)
    if isnull(sampler)
      warn(STDERR,"Allocating sampler...")
      sampler=Nullable(Interpolations.interpolate(sdata(volume),Interpolations.BSpline(Interpolations.Linear()),Interpolations.OnGrid()))
      warn(STDERR,"...allocated sampler")
    end
    image[x,y]=get(sampler)[x,y,512]
  end
  sdata(image)
end

...但是它仍然遇到完全相同的问题,并且有多个工作进程将开始交换或由于内存耗尽而无法创建采样器。

仔细检查 Interpolations.jl代码表明它通常希望填充和/或预过滤给定的数组(这显然意味着它需要一个副本)......但是我还不能很好地阅读 Julia 以了解是否 BSpline(Linear())有机会绕过正在制作的那些副本并避免每个进程的大量内存开销。我看到二次插值提供了一个有趣的选项,可以“就地”完成预过滤,但我还没有进一步探讨这个问题(一个重要的问题似乎是避免所有试图预过滤共享数据的工作人员).

最佳答案

Apparently解决方案是使用 interpolate! 版本的插值。这适用于我投入的尽可能多的工作进程:

using Interpolations

# Function to compute via interpolator
function test(volume)

  image=SharedArray(Float32,(512,512))

  sampler=interpolate!(
    volume,
    Interpolations.BSpline(Interpolations.Linear()),
    Interpolations.OnGrid()
  )

  @sync @parallel for i=1:512*512
    x,y=ind2sub((512,512),i)
    image[x,y]=sampler[x,y,512]
  end
  sdata(image)
end

# Initialize 1GByte of SharedArray
volume=SharedArray(Float32,(512,512,1024))  # 1 GByte of shared data
volume[:,:,:]=rand(Float32,(512,512,1024))

println(mean(test(volume)))

还有一个 prefilter!,它暗示也可以类似地使用高阶插值方法,但线性插值足以满足我的目的。

关于interpolation - 如何在工作进程中的 SharedArray 上使用插值,而无需每个进程创建自己的数据副本?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/38663113/

相关文章:

powershell - FFMPEG 插值视频 |第一帧卡住,没有对第二帧进行任何插值

julia - 在 Julia 中,创建一个向量集,并指定该集的类型

linux - Julia Gtk Windows 不显示在 REPL 之外

c# - 定义精确大小的内存结构

java - 从java中的c++/c#程序读取共享内存

java - 为什么 Kotlin 的字符串插值在 Java 中连接字符串?

Ruby 方法名称插值

python - 如何最好地对 2D 点数据执行曲面积分?

python - 我无法从 Python 调用 Julia

从消息队列接收后无法使用shm_open