【问题标题】:Simultaneously using multiple views in the iPython Notebook在 iPython Notebook 中同时使用多个视图
【发布时间】:2014-11-30 16:05:53
【问题描述】:

我有一个问题,希望有人能帮我弄清楚。我正在尝试在 iPython 笔记本中构建两个不同的并行视图。第一个视图包含 ID 为 0 的处理器,第二个视图包含所有其余的处理器。我为每个视图关联了一个前缀,这样我就可以轻松地在不同的处理器上运行不同的东西。

我启动了一个后台线程,该线程使用第二个视图中的处理器进行长时间计算。当它在后台运行时,我尝试使用第一个视图运行命令,但它不起作用。我收到此错误:ValueError:''不在列表中。

所以我想知道是否有办法做我在这里尝试做的事情,或者这是否是不受支持的行为。简而言之,我想使用不同的处理器创建两个不同的视图。视图之间不会共享处理器。然后我希望能够运行使用一个视图的后台任务,同时将另一个视图用于不相关的任务。

这是一个导致错误的小示例脚本。我不知道如何直接发布笔记本,所以我只是复制并粘贴了从中生成的 python 脚本。

# <codecell>

from IPython import parallel
cli = parallel.Client()

# <codecell>

view1 = cli[0]
view1.block = True
view1.activate("_one")

# <codecell>

view2 = cli[1:]
view2.block = True
view2.activate("_two")

# <codecell>

%px_two import time
def backFunc():
    for i in range(10):
        %px_two time.sleep(5)
        %px_two print "In bg thread"

# <codecell>

from IPython.lib import backgroundjobs as bg
bgJob = bg.BackgroundJobManager()
bgJob.new('backFunc()')

# <codecell>

%px_one import time
def foreFunc():
    for i in range(10):
        %px_one time.sleep(1)
        %px_one print "In fg thread"


# <codecell>

foreFunc()

一旦运行 foreFunc(),就会报错:

ValueError: '<IDS|MSG>' is not in list

有什么想法吗?如果有人提出任何想法,我将不胜感激。

【问题讨论】:

    标签: ipython ipython-notebook ipython-parallel


    【解决方案1】:

    简答

    客户端使用的套接字不是线程安全的,因此您不能在多个线程中同时使用它们。您可以同时使用 cluster,但需要为后台任务创建一个单独的 Client,它会有自己的一组套接字:

    rc = parallel.Client()
    rc2 = parallel.Client()
    
    view1 = rc[0]
    view2 = rc2[1:]
    

    其余的应该按预期工作。

    PS:发生了什么事

    客户端对象主要是围绕一组套接字的 API。每个客户端都有自己的一组套接字,一个客户端上的所有视图都使用相同的套接字。当您在线程之间共享这些套接字时,一个线程可能会获得要发送给另一个线程的消息的一部分,从而导致消息乱码。

    每条消息实际上是一个多部分消息zeromq消息,用zmq.Socket.send/recv_multipart发送或接收,相当于:

    multipart = []
    for i in range(nparts):
        multipart.append(socket.send/recv())
    

    如果两个线程同时在同一个套接字上执行此操作,则消息可能会交错,因此不会收到两条消息:

    ['a1', 'a2', 'a3'], ['b1', 'b2', 'b3']
    

    我们得到

    ['a1', 'a2', 'b1', 'b2', 'b3'], ['a3']
    

    导致您看到的问题。最简单的解决方法是在不同的线程中使用不同的套接字。另一种解决方法是使用locking 来确保自动接收多部分消息。为每个线程分离套接字可以避免锁定的需要,但它确实会增加您需要使用的套接字数量与并发线程的数量成正比。

    PPS ...但 IPython.parallel 是异步的

    最后我会问你为什么要使用后台作业。您不需要使用线程来完成您描述的任务,因为客户端通常不会等待引擎的结果。 IPython.parallel 本质上是异步的,因此您无需等待作业完成即可提交新作业,或在交互式会话中本地工作。我一般不建议将block=True 用于除调试以外的任何事情。

    【讨论】:

    • 感谢您的详细解答。我这样做的原因是因为后台进程的参数可能需要在完成之前更改,所以不是发送一个可能会长时间占用引擎的大作业,而是将其分成块并检查如果有什么需要改变的话,在每个块之后。但这一切都需要在后台进行,而我将笔记本用于其他事情。我将其用于科学可视化,它本质上是可能被查看的帧的预缓存例程。我想不出没有线程怎么做。
    • 明白了,这是有道理的。
    猜你喜欢
    • 2013-04-29
    • 2014-02-17
    • 2015-08-24
    • 2013-10-28
    • 2013-10-09
    • 1970-01-01
    • 2013-01-01
    • 2015-09-02
    • 2018-10-25
    相关资源
    最近更新 更多