更简单的python多进程编码。持久性工作线程,内存映射以获得最小的开销。
multicore的Python项目详细描述
Python Multicore
一个易于并行化Python代码的模块。
内容
Installation
- 在python路径中安装或添加multicore。
Overview
python支持多线程,但是全局解释器锁(gil)阻止 我们不再使用所有的CPU核心来完成CPU繁重的任务。建议的方法 是使用python的多处理库来处理gil,但这有自己的一系列挑战,特别是 在子进程之间共享数据的能力是有限的
多核库的目标是使代码尽可能简单地并行化。 同时产生least的开销。
Features
- 启用持久数据库连接的永久工作线程池。
- 进程间通信的内存映射。比多进程自己的IPC甚至管道快得多
- 可以考虑系统负载平均来决定是否并行化 在任何时候都是值得的
Architecture
python multicore实际上是一个内存队列,由 一群工人。它使用内存映射来避免使用 如芹菜等调酒系统。
Usage
让我们呈现100个用户总是把一个大任务分成几个小任务,但不是 太小了!如果范围太小,那么任务就不值得 因为开销太大。
import time from multicore import initialize, shutdown, Task from multicore.utils import ranges # Note the scoping of the "items" variable and the functions items = range(100) def as_string(item): return str(item) def expensive_as_string(item): time.sleep(0.01) return str(item) def multi_expensive_as_string(start, end): return ",".join([expensive_as_string(item) for item in items[start:end]]) if __name__ == "__main__": # Needs to be called only once for lifetime of process initialize() # Example 1: trivial (and slightly pointless) usage task = Task() for i in range(20): task.run(as_string, i) print(", ".join(task.get())) # Example 2: divide job optimally using ranges function task = Task() for start, end in ranges(items): # Note we don't pass items because pickling is expensive and defeats # the purpose of the exercize. task.run(multi_expensive_as_string, start, end) print(", ".join(task.get())) # Stop the multicore workers shutdown()
Task构造函数接受可选参数max_load_average如果 最后一分钟的平均负载大于定义的阈值 None返回,您的代码必须符合顺序代码路径。 注意,阈值是为单核机器指定的,因此通常 不到一个
run方法接受具有值的可选参数serialization_format。 pickle(默认)、json或string。泡菜又慢又安全。如果你 知道你有什么类型的数据(你应该!)根据需要设置。
run方法还默认接受可选参数use_dill。 值False。dill是一个图书馆,它可以经常腌制那些不能 用标准腌菜器腌制,但速度稍慢
FAQ’s
Will it try to execute hundreds of pieces of code in parallel?
不。工作池大小固定,只能执行核心数 并行任务。您还可以设置max_load_average作为进一步的保护。
Why didn’t you use multiprocessing.Pool?
当涉及到范围界定时,它和Django有太多的问题均匀的管道 而且套接字会带来太多的开销,所以使用内存映射。
The memory map is too small for my data structures
未来的版本将通过动态内存映射缩放来解决这个问题。