我正在尝试通过apply()
发送2GB的CPython只读对象(可以被腌制)给分布式工作人员。最终会消耗大量内存用于进程/线程(14+ GB)。
是否可以将对象仅一次加载到内存中,并让工作人员同时使用该对象?
我有2个Dask系列Source_list和Pattern_list,分别包含700万和300万个字符串。我正在尝试从Pattern_list(3M)的Source_list(7M)中找到所有子字符串匹配项。
为了加快子字符串搜索的速度,我使用pyahocorasick包从Pattern_list(该对象是可腌制的)创建一个Cpython数据结构(一个类对象)。
distributed.worker - WARNING - Memory use is high but worker has no data to
store to disk. Perhaps some other process is leaking memory? Process memory:
2.85 GB -- Worker memory limit: 3.00 GB
在运行dask的同时将内存限制增加到8GB / 16GB:
线程
distributed.worker - WARNING - Memory use is high but worker has no
data to store to disk. Perhaps some other process is leaking
memory?
Process memory: 14.5 GB -- Worker memory limit: 16.00 GB
distributed.nanny - WARNING - Worker exceeded 95% memory budget. Restarting
进程 处理需要花费超过2.5个小时的时间,但我从未见过它完成(取消之前,它运行了8个小时以上)。它还消耗了10+ GB的 记忆
Source_list.str.find_all(Pattern_list)
花费超过2.5个小时。# OS = Windows 10
# RAM = 16 GB
# CPU cores = 8
# dask version 1.1.1
import dask.dataframe as dd
import ahocorasick
from dask.distributed import Client, progress
def create_ahocorasick_trie(pattern_list):
A = ahocorasick.Automaton()
for index, item in pattern_list.iteritems():
A.add_word(item,item)
A.make_automaton()
return A
if __name__ == '__main__':
client = Client(memory_limit="12GB",processes=False)
# Using Threading, because, the large_object seems to get copied in memory
# for each process when processes = True
Source_list = dd.read_parquet("source_list.parquet")
Pattern_list = dd.read_parquet("pattern_list.parquet")
# Note: 'source_list.parquet' and 'pattern_list.parquet' are generated via dask
large_object = create_ahocorasick_trie(Pattern_list)
result = Source_list.apply(lambda source_text: {large_object.iter(source_text)}, meta=(None,'O'))
# iter() is an ahocorasick Cpython method
progress(result.head(10))
client.close()
答案 0 :(得分:0)
简短的答案是将其包装在dask.delayed呼叫中
big = dask.delayed(big)
df.apply(func, extra=big)
Dask将根据需要移动它,并将其视为自己的数据。话虽这么说,它必须存在于每个工作程序中,所以每个工作程序中的RAM应该远远超过占用的内存。 (至少4倍左右)。