为什么 mmap 标志减少了单个 Word2Vec 实例的内存消耗

Why mmap flag reduces memory consumption for single Word2Vec instance

根据文档和维基百科:

mmap 允许进程共享相同的内存块

word_vectors = KeyedVectors.load(config.get(wv_file))

像这样加载的模型需要 ~2.2 GB 内存

word_vectors = KeyedVectors.load(config.get(wv_file), mmap='r')

像这样加载的这个模型需要大约 1.2 GB 的内存

为什么我观察到内存消耗如此急剧下降?

同时加载多个模型,按预期工作,模型共享 ~1 GM 内存。

Memory-mapping re-uses 操作系统的 virtual-memory 功能使用现有文件作为可寻址内存范围的 backing-source。

对于单个进程,不一定节省任何内存。相反,它只是:

  • 延迟 将任何 range-of-the-addresses 加载到 RAM 中,将其保留在磁盘上直到请求。如果它从未被请求过,那么 RAM 就永远不会被使用,所以在这种特殊情况下它可能 "save" 内存。

  • 允许那些已加载的范围在一段时间内未被访问时被廉价丢弃,并且其他分配需要 RAM——因为这些范围如果再次需要,可以按需从磁盘重新加载。因此,在这种情况下,与耗尽 RAM 或激活其他不知道 1:1 与现有磁盘文件关系的通用 virtual-memory 相比,它可能 "save" 内存。 (如果没有内存映射,RAM 中 material 的 seldom-used 范围可能会 written-out 到一个单独的交换文件,以释放 space 用于其他分配——这是一种浪费操作和冗余数据,当数据已经存在于磁盘某处时。)

不幸的是,在 single-process 的 common-case 中,以及像 most_similar() 这样必须对每个向量进行计算的典型操作,整个结构将被放入内存中most_similar()。那里没有净 RAM "savings"(尽管如果其他内存压力会迫使 paging-out 加载范围,可能会有轻微的 CPU/IO 好处)。 (无论您使用哪种方法,“~2.2 GB”和“~1.2 GB”used-RAM 值可能无法正确衡量。)

主要好处是在使用多个进程时,每个进程都需要查阅同一文件的数据。如果天真地加载到 RAM 中,每个进程都会有自己的相同数据的冗余副本。如果使用 memory-mapping,您已经让 OS 知道:这些多个 arrays-in-address-space,在多个单独的处理中,定义上具有相同的数据(如文件中所反映的)。无论有多少进程需要数据,每个 file-range 的副本只会消耗 RAM。在那里,可以实现大量节省。