【问题标题】:ipython parallel and non-copying sends of numpy arraysnumpy数组的ipython并行和非复制发送
【发布时间】:2015-02-19 21:28:51
【问题描述】:

我试图了解 IPython 并行的 numpy 数组的非复制发送/接收会发生什么。我知道消息的非复制接收是只读的,但这让我期望我收到的 numpy 数组就像一个视图,指向原始数组(至少在共享内存机器上)。然后我希望如果修改 numpy 数组 其中一个计算节点,我在笔记本中对该数组的视图将被更新, 但是,情况似乎并非如此。为了演示让我感到困惑的地方,代码

from IPython.parallel import Client
dv = Client()[:]

with dv.sync_imports():
    import numpy 

dv.execute('a = numpy.zeros(2)')
print dv['a']
mya = dv['a'][1] # my copy of the array in the notebook
# mya[0] = -1 # can't assign to mya because it is read-only
dv.execute('a[1] = 1') # update the arrays on the compute nodes
print mya # value of mya is not updated
print dv['a'] # even though the arrays are updated on the compute nodes

有输出

importing numpy on engine(s)
[array([ 0.,  0.]), array([ 0.,  0.]), array([ 0.,  0.]), array([ 0.,  0.])]
[ 0.  0.]
[array([ 0.,  1.]), array([ 0.,  1.]), array([ 0.,  1.]), array([ 0.,  1.])]

我认为非复制发送的目的是通过让数组的每个视图都指向同一块内存来节省内存,但事实并非如此 似乎是这里的情况。幕后发生了什么,我对非复制发送的使用有何误解?

我上面的主要问题的上下文是共享内存环境(我的笔记本电脑), 但我有一个可能相关的问题是 numpy 数组的非复制发送如何工作以及它们在分布式内存情况下的用途是什么,其中计算节点 是不同的物理机器,您必须(我假设)通过网络发送 numpy 数组(有效地在接收机器上制作副本),因此查看原始内存位置是没有意义的。

【问题讨论】:

    标签: python numpy ipython ipython-parallel


    【解决方案1】:

    在 IPython.parallel(或底层 zeromq)上下文中的非复制发送并不意味着与目标共享内存。 IPython.parallel 不是基于共享内存系统,而是基于显式消息传递。

    这意味着网络接口直接从您提供的数组中检索其数据,而不是将数据复制到网络堆栈中自己的缓冲区中。 到目标进程或线程的传输仍然是一个副本,即使它在同一台机器上。

    所以数据的接收方可以修改数据而不改变发送方的数据。 但是发送者必须注意在将数据复制到目的地之前不要修改它提供给网络接口的缓冲区。使用 pyzmq,这可以通过 track 关键字参数来完成,该参数为您提供一个对象,您可以轮询该对象以完成传输,并且缓冲区再次可供修改。

    非复制发送是一种危险的优化,因为您必须非常小心哪些缓冲区可用于写入,哪些不可用。只有在明确指出网络堆栈的附加副本存在性能问题时,才应使用它们。

    【讨论】:

    • 我不确定我是否完全理解。如果“传输到目标进程或线程仍然是一个副本”和“数据的接收者可以修改数据而不更改发送者端的数据”,为什么 IPython 并行默认接收消息是只读的?如果一直在制作副本,我不明白 IPython 并行文档中的“非复制接收”是什么意思。
    猜你喜欢
    • 2016-03-22
    • 1970-01-01
    • 2022-11-15
    • 1970-01-01
    • 1970-01-01
    • 2016-10-06
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多