多处理在python中写入数组的函数的循环
我正在尝试为这个循环实现多处理。它无法修改数组或,并且似乎无法正确排序作业(返回上一个函数完成之前的数组)多处理在python中写入数组的函数的循环,python,arrays,loops,multiprocessing,Python,Arrays,Loops,Multiprocessing,我正在尝试为这个循环实现多处理。它无法修改数组或,并且似乎无法正确排序作业(返回上一个函数完成之前的数组) 我以前没有使用过多处理,所以我对这一点也不熟悉,但在做了一些研究(主要是从帖子中),我想我已经部分地解决了您使用此代码的问题: import multiprocessing import numpy def func(i, array, connection): squared_value = i ** 2 array[i] = squared_value pr
我以前没有使用过
多处理
,所以我对这一点也不熟悉,但在做了一些研究(主要是从帖子中),我想我已经部分地解决了您使用此代码的问题:
import multiprocessing
import numpy
def func(i, array, connection):
squared_value = i ** 2
array[i] = squared_value
print(squared_value)
connection.send(array)
def main(n):
array = numpy.zeros(n)
for i in range(0, n):
recv_end, send_end = multiprocessing.Pipe(False)
p = multiprocessing.Process(target=func, args=(i, array, send_end))
p.start()
p.join()
array = recv_end.recv()
return array
if __name__ == '__main__':
print(main(10))
输出
0
1.
4.
9
16
25
36
49
64
81
[ 0. 1. 4. 9. 16. 25. 36. 49. 64. 81.]
此方法修改阵列而您的方法不修改阵列的原因解释如下:
问题是,当对象被传递到工作进程时,它们会被打包成pickle,然后被运送到另一个进程,在那里它们会被解包并处理。您的对象与其说是传递给另一个进程,不如说是克隆。您不返回对象,因此克隆的对象被愉快地修改,然后丢弃
关于我的(部分)解决方案,我应该指出以下几点:
- 此实现的运行速度比仅以常规方式(通过单个线程)生成此列表要慢得多。这很可能是由于创建新进程和在它们之间编组数据所增加的开销
- 由于问题的性质(每个作业都修改一个数组),每个作业都必须将上一个作业的输出作为输入。由于这个限制,我认为不可能让作业同时运行,这有点违背了多处理的观点
至于这两点中的后一点,我尝试了一个变体,其中
func
返回一个接受数组并返回其修改版本的函数。这将允许作业同时运行,但不幸的是,函数似乎不能被pickle。进程不共享内存,您的程序最初将创建一个满是零的数组,然后启动10个进程,这些进程将在首次创建数组时对数组的副本调用func函数,但决不是原始数组
看起来你真正想要实现的是:
from multiprocessing import Process, Lock
from multiprocessing.sharedctypes import Array
def modify_array(index, sharedarray):
sharedarray[index] = index ** 2
print([x for x in sharedarray])
def main(n):
lock = Lock()
array = Array('i', 10, lock=lock)
if __name__ == '__main__':
for i in range(0, n):
p = Process(target=modify_array, args=(i, array))
p.start()
p.join()
return list(array)
main(10)
输出:
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
[0, 1, 0, 0, 0, 0, 0, 0, 0, 0]
[0, 1, 4, 0, 0, 0, 0, 0, 0, 0]
[0, 1, 4, 9, 0, 0, 0, 0, 0, 0]
[0, 1, 4, 9, 16, 0, 0, 0, 0, 0]
[0, 1, 4, 9, 16, 25, 0, 0, 0, 0]
[0, 1, 4, 9, 16, 25, 36, 0, 0, 0]
[0, 1, 4, 9, 16, 25, 36, 49, 0, 0]
[0, 1, 4, 9, 16, 25, 36, 49, 64, 0]
[0, 1, 4, 9, 16, 25, 36, 49, 64, 81]
但问题是,使用多处理是错误的。与新线程相比,生成一个额外的进程,甚至只是保持单线程状态并利用事件循环触发操作,都会有很大的开销
在Python的单线程单进程中使用并发的示例如下所示:
import numpy as np
from asyncio import get_event_loop, wait, ensure_future
def modify_array(index, array):
array[index] = index ** 2
print([x for x in array])
async def task(loop, function, index, array):
await loop.run_in_executor(None, function, index, array)
def main(n):
loop = get_event_loop()
jobs = list()
array = np.zeros(10)
for i in range(0, n):
jobs.append(
ensure_future(
task(loop, modify_array, i, array)
)
)
loop.run_until_complete(wait(jobs))
loop.close()
main(10)
这是目前流行的一种模式,即使用异步IO事件循环并行完成任务。但是,由于您使用的是Numpy之类的库,我怀疑此模式对您的价值有多大。From:“问题是,当对象被传递到工作进程时,它们会用pickle打包,然后运送到另一个进程,在那里它们会被解包并处理。您的对象与其说是传递给另一个进程,不如说是克隆。“这是我的回答之外的另一个选择。比我快。“我对速度也做了同样的观察。”瓦西里西拉基斯,谢谢。知道
多处理
定义了可以在进程之间共享的类型是很酷的+谢谢你的回复。我正在测试您的响应,在函数中添加一个循环以增加处理时间。(对于范围(010000)中的j,sum=0///sum=sum+j)。它仍然在单核上连续执行功能-我是否需要做一些额外的事情,使它在每个CPU核上运行一个进程?感谢您的回复。我可以访问一台30核的机器,我的实际函数包含一个积分,大约需要2秒(完成数千次)。在这种情况下,开销是否值得,或者还有更好的方法吗?如果任务在开始时生成长时间运行的进程,那么开销可能不是问题,但是如果您经常生成进程,我会说这不值得。您的程序还会给出错误消息raise RUNTIMERROR('Event loop is closed')运行时错误:事件循环已关闭
import numpy as np
from asyncio import get_event_loop, wait, ensure_future
def modify_array(index, array):
array[index] = index ** 2
print([x for x in array])
async def task(loop, function, index, array):
await loop.run_in_executor(None, function, index, array)
def main(n):
loop = get_event_loop()
jobs = list()
array = np.zeros(10)
for i in range(0, n):
jobs.append(
ensure_future(
task(loop, modify_array, i, array)
)
)
loop.run_until_complete(wait(jobs))
loop.close()
main(10)