- android - 多次调用 OnPrimaryClipChangedListener
- android - 无法更新 RecyclerView 中的 TextView 字段
- android.database.CursorIndexOutOfBoundsException : Index 0 requested, 光标大小为 0
- android - 使用 AppCompat 时,我们是否需要明确指定其 UI 组件(Spinner、EditText)颜色
我正在尝试使用多重处理来生成 4 个进程,这些进程会强制进行一些计算,并且每个进程在每次迭代中操作我想要在它们之间共享的单个列表对象的机会非常小。不是best practice在指南中,但我需要“很多人”。
对于相对较少的迭代次数,代码可以正常工作,但是当迭代次数增加到一定阈值时,所有四个进程都将进入僵尸状态。他们默默地失败了。
我尝试使用 multiprocessing.Queue()
跟踪对共享列表的修改。它出现于this SO post , this closed Python issue – "not a bug" ,以及一些提到这些的帖子,底层管道可能会过载并且进程会挂起。 SO 帖子中接受的答案非常难以破译,因为有太多多余的代码。
为清楚起见进行了编辑:
文档中的示例执行非常轻量级的操作,几乎总是单个函数调用。因此,我不知道我是否误解和滥用了功能。
指南说:
It is probably best to stick to using queues or pipes for communication between processes rather than using the lower level synchronization primitives from the threading module.
这里的“沟通”是否意味着我在示例中实际所做的事情之外的其他事情?
或者
这是否意味着我应该在队列中共享 my_list
而不是与经理共享?这不是意味着每个进程的每次迭代都会使用 queue.get
和 queue.put
吗?
If maxsize is less than or equal to zero, the queue size is infinite.
这样做并不能修复我的失败示例中的错误。在我执行 queue.put()
之前,所有数据都存储在普通的 Python 列表中:my_return_list
那么这实际上是由于我提供的链接而失败吗?
与我当前的解决方法相比,是否有更好的方法?我似乎找不到其他人采取类似的方法,我觉得我错过了一些东西。我需要它同时适用于 Windows 和 Linux。
失败示例(取决于 __main__
下的迭代):
import multiprocessing as mp
import random
import sys
def mutate_list(my_list, proc_num, iterations, queue, lock):
my_return_list = []
if iterations < 1001:
# Works fine
for x in xrange(iterations):
if random.random() < 0.01:
lock.acquire()
print "Process {} changed list from:".format(proc_num)
print my_list
print "to"
random.shuffle(my_list)
print my_list
print "........"
sys.stdout.flush()
lock.release()
my_return_list.append([x, list(my_list)])
else:
for x in xrange(iterations):
# Enters zombie state
if random.random() < 0.01:
lock.acquire()
random.shuffle(my_list)
my_return_list.append([x, list(my_list)])
lock.release()
if x % 1000 == 0:
print "Completed iterations:", x
sys.stdout.flush()
queue.put(my_return_list)
def multi_proc_handler(iterations):
manager = mp.Manager()
ns = manager.list()
ns.extend([x for x in range(10)])
queue = mp.Queue()
lock = manager.Lock()
print "Starting list to share", ns
print ns
sys.stdout.flush()
p = [mp.Process(target=mutate_list, args=(ns,x,iterations,queue,lock)) for x in range(4)]
for process in p: process.start()
for process in p: process.join()
output = [queue.get() for process in p]
return output
if __name__ == '__main__':
# 1000 iterations is fine, 100000 iterations will create zombies
multi_caller = multi_proc_handler(100000)
使用multiprocessing.Manager.list()
的解决方法:
import multiprocessing as mp
import random
import sys
def mutate_list(my_list, proc_num, iterations, my_final_list, lock):
for x in xrange(iterations):
if random.random() < 0.01:
lock.acquire()
random.shuffle(my_list)
my_final_list.append([x, list(my_list)])
lock.release()
if x % 10000 == 0:
print "Completed iterations:", x
sys.stdout.flush()
def multi_proc_handler(iterations):
manager = mp.Manager()
ns = manager.list([x for x in range(10)])
lock = manager.Lock()
my_final_list = manager.list() # My Queue substitute
print "Starting list to share", ns
print ns
sys.stdout.flush()
p = [mp.Process(target=mutate_list, args=(ns,x,iterations,my_final_list,
lock)) for x in range(4)]
for process in p: process.start()
for process in p: process.join()
return list(my_final_list)
if __name__ == '__main__':
multi_caller = multi_proc_handler(100000)
最佳答案
队列与列表
在底层,multiprocessing.Queue
和 manager.list()
都在向缓冲区写入和读取。
队列
shared_queue = multiprocessing.Queue()
当您使用 N 或更多字节(其中 N 取决于许多变量)调用 put
时,它超出了缓冲区可以处理的范围,并且 put
会阻塞。您也许可以通过在另一个进程中调用 get
来取消阻止 put
。这是一个使用代码的第一个版本应该很容易执行的实验。我强烈建议您尝试这个实验。
列表
manager = multiprocessing.Manager()
shared_list = manager.list()
当您调用append
时,您传递的字节数远少于N个字节,并且写入缓冲区成功。 还有另一个进程从缓冲区读取数据并将其附加到实际的列表
。该流程由经理
创建。即使您使用 N 或更多字节调用 append
,一切都应该继续工作,因为还有另一个进程正在从缓冲区读取。您可以通过这种方式将任意数量的字节传递给另一个进程。
摘要
希望这能澄清为什么您的“解决方法”有效。您将对缓冲区的写入分解为更小的片段,并且有一个辅助进程从缓冲区读取数据,将这些片段放入托管列表中。
关于python - 当增加迭代次数时,多进程会变成僵尸进程。 mp.Queue() 与 Manager.list() 相比有何优势?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/38961584/
我试图弄清楚以下模块正在做什么。 import Queue import multiprocessing import threading class BufferedReadQueue(Queue.
如果我使用 Queue.Queue,那么我的 read() 函数不起作用,为什么?但是,如果我使用 multiprocessing.Queue,它运行良好: from multiprocessing
我正在寻找比我在文档中找到的更多关于 Python 队列实现的见解。 根据我的理解,如果我在这方面有误,请原谅我的无知: queue.Queue():通过内存中的基本数组实现,因此不能在多个进程之间共
当我使用多处理模块(Windows 上的 Python 2.7)中的队列代替 Queue.Queue 时,我的程序没有完全关闭。 最终,我想使用 multiprocessing.Process 处理
阅读了大量的 JavaScript 事件循环教程,我看到了不同的术语来标识队列存储消息,当调用堆栈为空时,事件循环准备好获取消息: 队列 消息队列 事件队列 我找不到规范的术语来识别它。 甚至 MDN
我收到错误消息“类型队列不接受参数”。当我将更改队列行替换为 PriorityQueue 时,此错误消失并且编译正常。有什么区别以及如何将其更改为编译队列和常规队列? import java.util
如何将项目返回到 queue.Queue?如果任务失败,这在线程或多处理中很有用,这样任务就不会丢失。 docs for queue.Queue.get()说函数可以“从队列中删除并返回一个项目”,但
如何在多个 queue.Queue 上进行“选择”同时? Golang 有 desired feature及其 channel : select { case i1 = 声明。 线程:queue 模
http://docs.python.org/2/library/queue.html#Queue.Queue.put 这似乎是一个幼稚的问题,但我在文档和谷歌搜索中都没有找到答案,那么这些方法是线程
这可能是个愚蠢的问题,但我对与 .dequeue() 和 $.queue() 一起使用的 .queue() 感到困惑> 或 jquery.queue()。 它们是否相同,如果是,为什么 jquery
我正在尝试创建一个线程化的 tcp 流处理程序类线程和主线程对话,但是 Queue.Queue 也没有做我需要的,服务器从另一个程序接收数据,我只想传递它进入主线程进行处理这里是我到目前为止的代码:
The principal challenge of multi-threaded applications is coordinating threads that share data or ot
在Queue模块的queue类中,有几个方法,分别是qsize、empty 和 full,其文档声称它们“不可靠”。 他们到底有什么不可靠的地方? 我确实注意到 on the Python docs网
我需要一个队列,多个线程可以将内容放入其中,并且多个线程可以从中读取。 Python 至少有两个队列类,Queue.Queue 和 collections.deque,前者似乎在内部使用后者。两者都在
明天我将介绍我选择进程内消息队列实现的基本原理,但我无法阐明我的推理。我的合作设计者提议我们实现一个简单的异步队列,只使用基本的作业列表和互斥锁来控制访问,我建议在嵌入式模式下使用 ActiveMQ。
在 scala 中定义了一个特征: trait Queue[T] Queue 是一种类型吗?或其他东西,例如类型构造函数? 来自 http://artima.com/pins1ed/type-para
我看到 SML/NJ 包含一个队列结构。我不知道如何使用它。如何使用 SML/NJ 提供的附加库? 最佳答案 Queue structure SML '97 未指定,但它存在于 SML/NJ 的顶级环
我是 D3 和 JavaScript 的新手。 我试图理解其中的 queue.js。 我已经完成了 this关联。但是仍然无法清楚地了解 queue.await() 和 queue.awaitAll(
所以我试图在我的 main.cpp 文件中调用一个函数,但我得到“错误:没有匹配函数来调用‘Queue::Queue()。” 队列.h #ifndef QUEUE_H #define QUEUE_H
假设我有一个 10 行的二维 numpy 数组 例如 array([[ 23425. , 521331.40625], [ 23465. , 521246.03125],
我是一名优秀的程序员,十分优秀!