我有一个python应用程序,它抓取数据集合,并为该集合中的每个数据片段执行任务。由于涉及延迟,该任务需要一些时间才能完成。由于这种延迟,我不希望每个数据随后执行任务,我希望它们全部并行发生。我应该使用多进程吗?或操作线程?
我尝试使用线程但遇到了一些麻烦,通常一些任务实际上永远不会触发。
答案 0 :(得分:30)
如果你是真正的计算限制,使用multiprocessing module可能是最轻的权重解决方案(就内存消耗和实现难度而言。)
如果您受I / O约束,使用threading module通常会给您带来良好的效果。确保使用线程安全存储(如队列)将数据传递给线程。或者,当它们产生时,将它们交给他们独有的单个数据。
PyPy专注于表现。它具有许多可以帮助进行计算绑定处理的功能。他们也支持软件事务内存,尽管这还不是生产质量。承诺是您可以使用比多处理更简单的并行或并发机制(这有一些尴尬的要求。)
Stackless Python也是一个好主意。如上所述,Stackless具有可移植性问题。 Unladen Swallow很有希望,但现在已经不复存在了。 Pyston是另一个(未完成的)Python实现,专注于速度。它采用的方法与PyPy不同,可能会产生更好(或者只是不同)的加速。
答案 1 :(得分:9)
任务按顺序运行但你有并行运行的错觉。当您使用文件或连接I / O并且因为轻量级时,任务很好。
Multiprocess with Pool可能是适合您的解决方案,因为进程并行运行,因此非常适合密集型计算,因为每个进程都在一个CPU(或核心)中运行。
设置多进程可能非常简单:
from multiprocessing import Pool
def worker(input_item):
output = do_some_work()
return output
pool = Pool() # it make one process for each CPU (or core) of your PC. Use "Pool(4)" to force to use 4 processes, for example.
list_of_results = pool.map(worker, input_list) # Launch all automatically
答案 2 :(得分:7)
对于小型数据集合,只需使用subprocess.Popen创建子流程。
每个子进程只需从stdin或命令行参数中获取数据,进行处理,然后将结果写入输出文件。
当子进程全部完成(或超时)时,您只需合并输出文件。
很简单。
答案 3 :(得分:7)
您可以考虑查看Stackless Python。如果你可以控制需要很长时间的函数,你可以在那里抛出一些stackless.schedule()
(说到下一个协程的产量),否则你可以set Stackless to preemptive multitasking。
在Stackless中,你没有线程,但 tasklets 或 greenlets 本质上是非常轻量级的线程。它的效果非常好,因为它有一个非常好的框架,只需很少的设置即可实现多任务处理。
然而,Stackless阻碍了可移植性,因为你必须替换一些标准的Python库 - Stackless消除了对C栈的依赖。如果下一个用户也安装了Stackless,那么它非常便携,但很少会出现这种情况。
答案 4 :(得分:0)
使用CPython的线程模型不会给你任何性能提升,因为线程实际上不是并行执行的,因为处理垃圾收集的方式。多进程允许并行执行。显然,在这种情况下,您必须有多个核心可用于将并行作业分配到。
this related question中提供了更多信息。
答案 5 :(得分:0)
如果您可以轻松地对所拥有的数据进行分区和分离,那么您应该在外部进行分区,并将它们提供给程序的多个进程。 (即几个进程而不是线程)
答案 6 :(得分:0)
IronPython具有真正的多线程,与CPython不同,它是GIL。所以根据你正在做的事情,这可能值得一看。但听起来您的用例更适合多处理模块。
对于推荐无堆栈python的人来说,我不是它的专家,但在我看来他说的是软件“多线程”,实际上根本不是并行的(仍然在一个物理线程中运行,所以无法扩展到多个核心。)它只是构建异步(但仍然是单线程,非并行)应用程序的另一种方法。
答案 7 :(得分:0)
您可能需要查看Twisted。它专为异步网络任务而设计。