Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/python/349.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
python管道的同步/异步行为_Python_Linux_Multiprocessing_Pipe - Fatal编程技术网

python管道的同步/异步行为

python管道的同步/异步行为,python,linux,multiprocessing,pipe,Python,Linux,Multiprocessing,Pipe,在我的应用程序中,我使用来自多处理模块的管道在python进程之间进行通信。 最近,我观察到一种奇怪的行为,这取决于我通过它们发送的数据的大小。 根据python文档,这些管道是基于连接的,应该以异步方式运行,但有时它们在发送时会卡住。如果我在每个连接中启用全双工,那么一切都可以正常工作,即使我没有将连接用于发送和侦听。 有人能解释这种行为吗 100个浮点数,全双工禁用 代码利用异步性工作 100个浮点数,全双工启用 该示例工作正常 10000个浮点,全双工禁用 执行将永远被阻止,即使对于较小的

在我的应用程序中,我使用来自多处理模块的管道在python进程之间进行通信。 最近,我观察到一种奇怪的行为,这取决于我通过它们发送的数据的大小。 根据python文档,这些管道是基于连接的,应该以异步方式运行,但有时它们在发送时会卡住。如果我在每个连接中启用全双工,那么一切都可以正常工作,即使我没有将连接用于发送和侦听。 有人能解释这种行为吗

  • 100个浮点数,全双工禁用
    代码利用异步性工作
  • 100个浮点数,全双工启用
    该示例工作正常
  • 10000个浮点,全双工禁用
    执行将永远被阻止,即使对于较小的数据执行情况良好
  • 10000个浮点数,全双工启用
    又好了
  • 代码(这不是我的生产代码,它只是说明了我的意思):


    首先,值得注意的是类的实现

    不同之处在于半双工“管道”使用a,而全双工“管道”实际上使用a,因为匿名管道本质上是单向的

    我不知道你在这里所说的“异步”是什么意思。如果您的意思是“非阻塞I/O”,那么值得注意的是,这两种实现在默认情况下都使用阻塞I/O


    其次,值得注意的是,您试图发送的数据的大小

    >>> from numpy.random import randn
    >>> from cPickle import dumps
    >>> len(dumps(randn(100)))
    2479
    >>> len(dumps(randn(10000)))
    237154
    

    第三,从
    管道(7)
    手册页

    管道容量

    管道的容量有限。如果管道已满,则写入(2)将被阻塞 或失败,取决于是否设置了O_非块标志(见下文)。不同的 实现对管道容量有不同的限制。申请应 不依赖于特定的容量:应用程序的设计应确保 读取过程在数据可用时立即消耗数据,因此写入过程 不会保持阻塞状态

    在2.6.11之前的Linux版本中,管道的容量与系统相同 页面大小(例如,i386上的4096字节)。自Linux 2.6.11以来,管道容量为 65536字节


    因此,实际上,您创建了一个死锁,其中所有子进程都阻塞了
    pipe_out.send()
    调用,并且它们都无法从其他进程接收任何数据,因为您在一次命中中发送了所有237154字节的数据,这已经填充了65536字节的缓冲区

    您可能只想使用Unix域套接字版本,但目前它工作的唯一原因是它的缓冲区大小比管道大,如果将
    数据点的数量增加到100000,您会发现该解决方案也将失败

    “quick n'dirty hack”解决方案是将数据分成更小的数据块进行发送,但依赖特定大小的缓冲区并不是一种好的做法

    更好的解决方案是在
    pipe\u out.send()
    调用上使用非阻塞I/O,尽管我对
    多处理
    模块不太熟悉,无法确定使用该模块实现它的最佳方法

    伪代码应该是

    while 1:
        if we have sent all data and received all data:
            break
        send as much data as we can without blocking
        receive as much data as we can without blocking
        if we didn't send or receive anything in this iteration:
            sleep for a bit so we don't waste CPU time
            continue
    
    …或者您可以使用Python模块来避免睡眠时间过长,但是,再次强调,将其与
    多处理.Pipe集成可能很棘手


    这门课可能会为你做所有这些,但我以前从未使用过,所以你必须做一些实验。

    谢谢你详尽的回答。现在我明白了。
    >>> from numpy.random import randn
    >>> from cPickle import dumps
    >>> len(dumps(randn(100)))
    2479
    >>> len(dumps(randn(10000)))
    237154
    
    while 1:
        if we have sent all data and received all data:
            break
        send as much data as we can without blocking
        receive as much data as we can without blocking
        if we didn't send or receive anything in this iteration:
            sleep for a bit so we don't waste CPU time
            continue