持久化服务内存管理与NumPy 2.0兼容性解析

本文详细介绍了spaCy v3.8版本中新增的持久化服务内存管理功能,通过内存区域上下文管理器实现词汇表缓存清理,同时全面支持NumPy 2.0兼容性,并改进了模型包依赖管理机制。

持久化服务的内存管理

支持新的上下文管理器方法 Language.memory_zone(),允许长时间运行的服务避免因词汇表或字符串存储中的缓存条目导致内存使用增长。内存区域块结束后,spaCy将驱逐在该块期间添加的词汇表和字符串存储条目,释放内存。在内存区域块内创建的文档对象不应在块外访问。

当前实现会禁用内存区域内的分词器缓存填充,导致一定的性能影响。如果运行完整管道,性能差异可能可忽略不计,但若仅运行分词器,速度会显著变慢。若存在此问题,可通过预先预热缓存来缓解:在不创建内存区域的情况下处理前几批文本。分词器的内存区域支持将在未来更新中添加。

Language.memory_zone() 上下文管理器还会检查管道组件上的 memory_zone() 方法,以便组件在必要时执行类似的内存管理。目前所有内置组件均无需此功能。

如果组件需要向字符串存储或词汇表添加非临时性条目,可向 Vocab.add()StringStore.add() 组件传递 allow_transient=False 标志。

示例用法:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
import spacy
import json
from pathlib import Path
from typing import Iterator
from collections import Counter
import typer
from spacy.util import minibatch

def texts(path: Path) -> Iterator[str]:
    with path.open("r", encoding="utf8") as file_:
        for line in file_:
            yield json.loads(line)["text"]

def main(jsonl_path: Path) -> None:
    nlp = spacy.load("en_core_web_sm")
    counts = Counter()
    batches = minibatch(texts(jsonl_path), 1000)
    for i, batch in enumerate(batches):
        print("Batch", i)
        with nlp.memory_zone():
            for doc in nlp.pipe(batch):
                for token in doc:
                    counts[token.text] += 1
    for word, count in counts.most_common(100):
        print(count, word)

if __name__ == "__main__":
    typer.run(main)

NumPy v2 兼容性

NumPy 2.0 与 NumPy v1 不具二进制兼容性,因此需要选择其一进行构建。此版本隔离了依赖变更且无其他修改,以便在依赖变更引发问题时更易处理。

此依赖变更曾尝试在 3.7.6 版本中实施,但 v3.7 系列模型内的依赖关系导致了一些冲突,且部分依赖 NumPy v1 的包与 v3.7.6 不兼容。因此已移除 3.7.6 版本并替换为本版本,该版本增加了次要版本号。

模型包不再将 spaCy 列为必需依赖

对模型打包方式进行了更改以加速发布流程。此前 spaCy 模型会指定对 spaCy 本身的版本化要求,这意味着无法在增加 spaCy 版本的同时使其与现有模型兼容,因为模型会指定仅兼容 spacy>=3.7.0,<3.8.0。虽然存在兼容性表格供 spaCy 查看哪些模型兼容,但模型自身无法预知未来哪些 spaCy 版本可正常工作。

因此向 spaCy 包 CLI 添加了标志 --require-parent/--no-require-parent,用于控制是否将父包(如 spaCy)列为模型的必需依赖。在 v3.8 中默认使用 --require-parent,但在 v4 中将默认改为 --no-require-parent。针对 v3.8 模型已设置 --no-require-parent,以便发布不影响模型的后续变更,而无需重新训练模型或强制用户重新下载。

comments powered by Disqus
使用 Hugo 构建
主题 StackJimmy 设计