在高性能环境中在分叉的工作进程之间共享状态

时间:2014-01-07 12:05:21

标签: python concurrency machine-learning nlp

这是我previous question的后续跟进。正如Tim Peters所建议的那样,使用Manager可能不一定是最好的方法。不幸的是,我有太多的脚手架代码来发布SSCCE。相反,我会尝试提供我的问题的详细解释。请随意浏览Github上的整个代码库,但现在有点混乱。

背景

我正在进行自然语言处理方面的研究,我想做(如类似的)基于字典的平滑文档分类。培养分类器以将单词和短语与正确答案相关联的想法。例如,包含单词socialist的文档可能与政治有关,而包含短语lava temperature的文档可能与地质有关。通过查看少数预先标记的示例来训练系统。因为语言是如此多样化,分类器永远不会“知道”它在生产中可能遇到的所有可能的短语。

这就是字典的用武之地。假设我们有a cheap and easy way获取几乎所有短语的同义词(我会引用自己,因为它的味道很差)。当穷人的分类器面对一个它不知道的短语时,我们可以在所说的字典中查找并告诉分类器“看,你不知道communism,但它有点像{{1} ,你知道的!“如果字典合理,分类器通常会表现得更好。

伪代码

socialist

问题

上面的循环是并行化的理想选择。我一直在使用Python 2.7 data = Load training and testing documents (300MB on disk) dictionary = Load dictionary (200MB - 2GB on disk) and place into a `dict` for fast look-ups Repeat 25 times: do_work(data, dictionary) def do_work(data, dictionary) X = Select a random sample of data Train a classifier on X Y = Select a random sample of data Using dictionary, classify all documents in Y Write results to disk (通过multiprocessing.Pool,因为它很容易,并且如果事情向南,则提供非常有用的回溯)。所有工作进程都需要对字典和文档集合的只读访问权限。工作人员不需要彼此沟通或与父流程进行通信 - 他们所做的就是产生,做一些魔术,写一个文件并死掉。

字典需要支持快速随机访问。我不知道样本joblib.Parallel将包含哪些文档,因此我无法轻松修剪字典并仅传递每个工作者所需的部分字典。字典将经常被查询 - 每次运行的典型命中数是数百万。 目前我的代码是内存绑定的(我相信)正在为每个工作进程创建文档集合和字典的副本。解析时Ydata通常会占用几GB的RAM。我尝试使用dictionary来避免复制大型对象,但这会减慢工作人员的速度。

问题

还有哪些其他选择可以加快速度?我想过的事情包括:

  • MongoDB / CouchDB / memcached应​​该能很好地处理并发访问,但我担心吞吐量。 zeromq也在对我之前的问题的评论中提出,没有机会研究它。
  • 内存中multiprocessing.managers.BaseManager数据库和数据库连接不能跨进程共享,因此每个工作程序都需要自己的连接到磁盘数据库。这意味着当每个工作者的缓存增长时,首先会有大量的I / O和高内存使用量。
  • 内存映射
  • 使用线程代替进程

This SO question还表示许多看似需要只读sqlite的实际问​​题可能会触发dict的写时复制,因此可能会不可能完全避免复制大型物体。

1 个答案:

答案 0 :(得分:2)

您描述的方案,在使用多线程时,由于GIL,您可能会遇到大的性能问题。可能要避免您选择使用多处理。另一方面,这使用了进程,因此可能会为每个子进程复制数据结构。

我不想这么说,但是使用非Python解决方案(例如在C ++中)可能会加快速度,因为你没有GIL问题。然后你可以使用多线程,不必复制东西等。从几个线程读取一个大字典并不是一个真正的问题,所以你不必同步任何东西(GIL总是会为你做什么没有真正的需要)。