当通过管道传递大型数组时,Python多处理陷入困境
我在python中使用多处理,并尝试通过管道将一个大的numpy数组传递给子进程。它适用于小数组,但对于较大的数组挂起而不返回错误 我相信管道堵塞了,已经读了一些关于它的文章,但无法找到解决问题的方法当通过管道传递大型数组时,Python多处理陷入困境,python,multiprocessing,pipe,Python,Multiprocessing,Pipe,我在python中使用多处理,并尝试通过管道将一个大的numpy数组传递给子进程。它适用于小数组,但对于较大的数组挂起而不返回错误 我相信管道堵塞了,已经读了一些关于它的文章,但无法找到解决问题的方法 def f2(conn, x): conn.start() data = conn.recv() conn.join() print(data) do_something(x) conn.close() if __name__ == '__ma
def f2(conn, x):
conn.start()
data = conn.recv()
conn.join()
print(data)
do_something(x)
conn.close()
if __name__ == '__main__':
data_input = read_data() # large numpy array
parent_conn, child_conn = Pipe()
p = multiprocessing.Pool(processes=8)
func = partial(f2, child_conn)
parent_conn.send(data_input)
parent_conn.close()
result = p.map(func, processes)
p.close()
p.join()
忽略此代码中的所有其他问题(您没有要传递到
map
的x
,您没有使用x
f2
接收,混合池。map
和管道通常是错误的做法),您的最终问题是在工作进程可以读取之前执行阻塞send
调用
假设您确实希望将映射
与管道
混合使用,解决方案是在开始发送
之前异步启动映射
,因此在父级尝试写入时,另一侧有一些东西可以从管道
读取:
if __name__ == '__main__':
data_input = read_data() # large numpy array
parent_conn, child_conn = Pipe()
# Use with to avoid needing to explicitly close/join
with multiprocessing.Pool(processes=8) as p:
func = partial(f2, child_conn)
# Launch async map to ensure workers are running
future = p.map_async(func, x)
# Can perform blocking send as workers will consume as you send
parent_conn.send(data_input)
parent_conn.close()
# Now you can wait on the map to complete
result = future.get()
如前所述,由于x
的问题,此代码将不会运行,Pipe
文档明确警告不应同时从管道读取两个不同的进程
如果您想在单个辅助进程中批量处理数据,只需使用process
和Pipe
,类似于:
def f2(conn):
data = conn.recv()
conn.close()
print(data)
if __name__ == '__main__':
parent_conn, child_conn = Pipe()
proc = multiprocessing.Process(target=f2, args=(child_conn,))
proc.start()
data_input = read_data() # large numpy array
parent_conn.send(data_input)
parent_conn.close()
proc.join()
如果您想在多个工作区中分别处理每个元素,只需使用Pool
和map
:
def f2(x):
print(x)
if __name__ == '__main__':
data_input = read_data() # large numpy array
with multiprocessing.Pool(processes=8) as p:
result = p.map(f2, data_input)
忽略此代码中的所有其他问题(您没有要传递到map
的x
,您没有使用x
f2
接收,混合池。map
和管道通常是错误的做法),您的最终问题是在工作进程可以读取之前执行阻塞send
调用
假设您确实希望将映射
与管道
混合使用,解决方案是在开始发送
之前异步启动映射
,因此在父级尝试写入时,另一侧有一些东西可以从管道
读取:
if __name__ == '__main__':
data_input = read_data() # large numpy array
parent_conn, child_conn = Pipe()
# Use with to avoid needing to explicitly close/join
with multiprocessing.Pool(processes=8) as p:
func = partial(f2, child_conn)
# Launch async map to ensure workers are running
future = p.map_async(func, x)
# Can perform blocking send as workers will consume as you send
parent_conn.send(data_input)
parent_conn.close()
# Now you can wait on the map to complete
result = future.get()
如前所述,由于x
的问题,此代码将不会运行,Pipe
文档明确警告不应同时从管道读取两个不同的进程
如果您想在单个辅助进程中批量处理数据,只需使用process
和Pipe
,类似于:
def f2(conn):
data = conn.recv()
conn.close()
print(data)
if __name__ == '__main__':
parent_conn, child_conn = Pipe()
proc = multiprocessing.Process(target=f2, args=(child_conn,))
proc.start()
data_input = read_data() # large numpy array
parent_conn.send(data_input)
parent_conn.close()
proc.join()
如果您想在多个工作区中分别处理每个元素,只需使用Pool
和map
:
def f2(x):
print(x)
if __name__ == '__main__':
data_input = read_data() # large numpy array
with multiprocessing.Pool(processes=8) as p:
result = p.map(f2, data_input)
你为什么要在这里把管道
和地图
混在一起?您的工作人员不使用它接收的x
,正在传递的x
不存在,等等。您通常希望将管道
与一个或多个手动启动的进程
es或池上的映射
一起使用,不是两者都有。@ShadowRanger:原始程序计算一个子进程池,其中x作为单个输入(我将编辑我的帖子)。你的意思是我可以把我的numpy数组作为f2()的参数传递吗?实际上,假设你在一个可以fork
(读:不是Windows)的系统上,你最好不要传递numpy
数组。只要data\u input
在工作线程分叉之前被初始化,它就会被映射到每个子线程的写时拷贝内存中,这样他们就可以访问f2
中的data\u input
,它将是调用进程
或池
时父线程中内容的完美副本。使用Pool.map
将其作为参数传递给f2
,需要对数据进行酸洗、传输和取消勾选,其中fork
s“free”copy效率更高。为什么在这里尝试将Pipe
与map
混合使用?您的工作人员不使用它接收的x
,正在传递的x
不存在,等等。您通常希望将管道
与一个或多个手动启动的进程
es或池上的映射
一起使用,不是两者都有。@ShadowRanger:原始程序计算一个子进程池,其中x作为单个输入(我将编辑我的帖子)。你的意思是我可以把我的numpy数组作为f2()的参数传递吗?实际上,假设你在一个可以fork
(读:不是Windows)的系统上,你最好不要传递numpy
数组。只要data\u input
在工作线程分叉之前被初始化,它就会被映射到每个子线程的写时拷贝内存中,这样他们就可以访问f2
中的data\u input
,它将是调用进程
或池
时父线程中内容的完美副本。使用Pool.map
将其作为参数传递给f2
,需要对数据进行酸洗、传输和取消酸洗,其中fork
s“free”copy效率更高。