在 python3 中的多进程之间共享 python 对象
share python object between multiprocess in python3
这里我创建了一个producer-customer程序,父进程(producer)创建了很多子进程(consumer),然后父进程读取文件并传递数据给子进程。
但是,性能问题来了,进程之间传递消息太费时间了(我认为)。
举个例子,一个 200MB 原始数据,父进程读取和预处理比只传递数据花费更少 8 秒通过 multiprocess.pipe 到子进程将花费另一个 8 秒,子进程完成剩余的工作只花费另一个 3 ~ 4 秒。
所以,一个完整的工作流耗时不到18秒,进程间的通信耗时超过40%,比我想象的要大得多,我试过多进程。队列和经理,他们更差。
我和 windows7 / Python3.4 一起工作。
我 google 好几天了,POSH 可能是一个很好的解决方案,但它不能用 python3.4
构建
我有3种方法:
1.is 有什么方法可以在 Python3.4 中的进程之间直接共享 python 对象?作为 POSH
或
2.is 是否可以将对象的 "pointer" 传递给子进程,子进程可以将 "pointer" 恢复为 python 对象?
或
3.multiprocess.Array 可能是一个有效的解决方案,但如果我想共享复杂的数据结构,例如列表,它是如何工作的?我应该基于它创建一个新的 class 并将接口作为列表提供吗?
编辑1:
第三种方法我试过了,效果更差
我定义了那些值:
p_pos = multiprocessing.Value('i') #producer write position
c_pos = multiprocessing.Value('i') #customer read position
databuff = multiprocess.Array('c',buff_len) # shared buffer
和两个函数:
send_data(msg)
get_data()
在send_data函数(父进程)中,将msg复制到databuff中,并通过管道将开始和结束位置(两个整数)发送给子进程。
比在 get_data 函数(子进程)中,它接收到两个位置并从数据缓冲区复制消息。
最终,它的成本是使用管道的两倍@_@
编辑 2:
是的,我尝试了 Cython,结果看起来不错。
我只是将我的 python 脚本的后缀更改为 .pyx 并编译它,程序速度提高了 15%。
毫无疑问,我遇到了“找不到vcvarsall.bat”和“系统找不到指定文件”的错误,我花了一整天的时间解决了第一个,并被第二个阻止了。
最后,我找到了Cyther,所有的烦恼都没有了^_^.
五个月前我在你家。我环顾四周但我的结论是 Python 的多重处理正是您描述的问题:
- 管道和队列很好,但根据我的经验不适用于大对象
- Manager() 代理对象很慢,除了数组,而且那些对象是有限的。如果您想共享一个复杂的数据结构,请使用命名空间,就像在此处完成的那样:multiprocessing in python - sharing large object (e.g. pandas dataframe) between multiple processes
- Manager() 有一个您要查找的共享列表:https://docs.python.org/3.6/library/multiprocessing.html
- Python 中没有指针或实际内存管理,因此您无法共享选定的内存单元
我通过学习C++解决了这类问题,但它可能不是你想读的...
要将数据(尤其是大的 numpy 数组)传递给子进程,我认为 mpi4py 会非常高效,因为我可以直接处理类似缓冲区的对象。
可以找到使用 mpi4py 生成进程和通信的示例(也使用 trio,但这是另一回事)here。
这里我创建了一个producer-customer程序,父进程(producer)创建了很多子进程(consumer),然后父进程读取文件并传递数据给子进程。
但是,性能问题来了,进程之间传递消息太费时间了(我认为)。
举个例子,一个 200MB 原始数据,父进程读取和预处理比只传递数据花费更少 8 秒通过 multiprocess.pipe 到子进程将花费另一个 8 秒,子进程完成剩余的工作只花费另一个 3 ~ 4 秒。
所以,一个完整的工作流耗时不到18秒,进程间的通信耗时超过40%,比我想象的要大得多,我试过多进程。队列和经理,他们更差。
我和 windows7 / Python3.4 一起工作。 我 google 好几天了,POSH 可能是一个很好的解决方案,但它不能用 python3.4
构建我有3种方法:
1.is 有什么方法可以在 Python3.4 中的进程之间直接共享 python 对象?作为 POSH
或
2.is 是否可以将对象的 "pointer" 传递给子进程,子进程可以将 "pointer" 恢复为 python 对象?
或
3.multiprocess.Array 可能是一个有效的解决方案,但如果我想共享复杂的数据结构,例如列表,它是如何工作的?我应该基于它创建一个新的 class 并将接口作为列表提供吗?
编辑1:
第三种方法我试过了,效果更差
我定义了那些值:
p_pos = multiprocessing.Value('i') #producer write position
c_pos = multiprocessing.Value('i') #customer read position
databuff = multiprocess.Array('c',buff_len) # shared buffer
和两个函数:
send_data(msg)
get_data()
在send_data函数(父进程)中,将msg复制到databuff中,并通过管道将开始和结束位置(两个整数)发送给子进程。
比在 get_data 函数(子进程)中,它接收到两个位置并从数据缓冲区复制消息。
最终,它的成本是使用管道的两倍@_@
编辑 2:
是的,我尝试了 Cython,结果看起来不错。
我只是将我的 python 脚本的后缀更改为 .pyx 并编译它,程序速度提高了 15%。
毫无疑问,我遇到了“找不到vcvarsall.bat”和“系统找不到指定文件”的错误,我花了一整天的时间解决了第一个,并被第二个阻止了。
最后,我找到了Cyther,所有的烦恼都没有了^_^.
五个月前我在你家。我环顾四周但我的结论是 Python 的多重处理正是您描述的问题:
- 管道和队列很好,但根据我的经验不适用于大对象
- Manager() 代理对象很慢,除了数组,而且那些对象是有限的。如果您想共享一个复杂的数据结构,请使用命名空间,就像在此处完成的那样:multiprocessing in python - sharing large object (e.g. pandas dataframe) between multiple processes
- Manager() 有一个您要查找的共享列表:https://docs.python.org/3.6/library/multiprocessing.html
- Python 中没有指针或实际内存管理,因此您无法共享选定的内存单元
我通过学习C++解决了这类问题,但它可能不是你想读的...
要将数据(尤其是大的 numpy 数组)传递给子进程,我认为 mpi4py 会非常高效,因为我可以直接处理类似缓冲区的对象。
可以找到使用 mpi4py 生成进程和通信的示例(也使用 trio,但这是另一回事)here。