【发布时间】:2021-12-28 16:19:35
【问题描述】:
我正在使用 AllenNLP(2.6 版)语义角色标注模型来处理一大堆句子。我的 Python 版本是 3.7.9。我在 MacOS 11.6.1 上。我的目标是使用multiprocessing.Pool 来并行化工作,但是通过池进行的调用比在父进程中花费的时间要长,有时甚至相当长。
在父进程中,我已将模型显式放置在共享内存中,如下所示:
from allennlp.predictors import Predictor
from allennlp.models.archival import load_archive
import allennlp_models.structured_prediction.predictors.srl
PREDICTOR_PATH = "...<srl model path>..."
archive = load_archive(PREDICTOR_PATH)
archive.model.share_memory()
PREDICTOR = Predictor.from_archive(archive)
我知道模型只在父进程中加载一次。无论我是否要使用池,我都会将模型放在共享内存中。我正在使用torch.multiprocessing,正如许多人推荐的那样,我正在使用spawn 启动方法。
我正在使用Pool.apply_async 调用池中的预测器,并且我正在为子进程中的调用计时。我知道池正在使用可用的 CPU(我有六个内核),而且我的物理内存还远未耗尽,因此没有理由将子进程交换到磁盘。
对于一组 395 个句子,情况如下:
- 没有多重处理:638 总处理秒数(以及经过的时间)。
- 使用 4 进程池:经过时间 293 秒,总处理时间为 915 秒。
- 使用 12 个进程池:经过时间 263 秒,总处理时间为 2024 秒。
进程越多,AllenNLP 的总处理时间越差 - 即使模型显式位于共享内存中,并且在调用期间跨越进程边界的唯一内容是输入文本和输出 JSON。
我已经进行了一些分析,首先让我感到震惊的是函数torch._C._nn.linear 在多处理情况下花费的时间要长得多。这个函数接受两个张量作为参数——但是没有张量通过进程边界,我正在解码,而不是训练,所以模型应该是完全只读的。似乎它必须是共享模型资源的锁定或竞争问题,但我完全不明白为什么会这样。而且我不是torch 程序员,所以我对正在发生的事情的理解有限。
任何指针或建议将不胜感激。
【问题讨论】:
-
我还尝试使用
copy.deepcopy将预测器中的模型复制为池元素的初始化代码的一部分,但这只会增加创建池元素的时间,并且没有显着减少 AllenNLP 处理时间。
标签: pytorch multiprocessing allennlp