我有一个程序需要编译数千个大型正则表达式,所有这些都将被多次使用。问题是,它们花费的时间太长(根据cProfiler
113 秒)re.compile()
。(顺便说一句,编译后实际上使用所有这些正则表达式进行搜索 < 1.3 秒。)
如果我不预编译,它只是将问题推迟到我实际搜索时,因为re.search(expr, text)
隐式编译expr
. 实际上,情况更糟,因为re
每次我使用它们时都会重新编译整个正则表达式列表。
我尝试使用multiprocessing
,但这实际上减慢了速度。这是一个小测试来演示:
## rgxparallel.py ##
import re
import multiprocessing as mp
def serial_compile(strings):
return [re.compile(s) for s in strings]
def parallel_compile(strings):
print("Using {} processors.".format(mp.cpu_count()))
pool = mp.Pool()
result = pool.map(re.compile, strings)
pool.close()
return result
l = map(str, xrange(100000))
还有我的测试脚本:
#!/bin/sh
python -m timeit -n 1 -s "import rgxparallel as r" "r.serial_compile(r.l)"
python -m timeit -n 1 -s "import rgxparallel as r" "r.parallel_compile(r.l)"
# Output:
# 1 loops, best of 3: 6.49 sec per loop
# Using 4 processors.
# Using 4 processors.
# Using 4 processors.
# 1 loops, best of 3: 9.81 sec per loop
我猜并行版本是:
- 同时,编译和酸洗正则表达式,约 2 秒
- 在串行中,取消酸洗,因此重新编译它们,~6.5 秒
加上启动和停止进程的开销,在 4 个处理器上比串行慢multiprocessing
25%以上。
我还尝试将正则表达式列表划分为 4 个子列表,并对子列表进行pool.map
-ing,而不是单个表达式。这给性能带来了小幅提升,但我仍然无法比串行慢 25% 以上。
有没有比串行编译更快的方法?
编辑: 更正了正则表达式编译的运行时间。
我也尝试过使用threading
,但由于 GIL,只使用了一个处理器。它略好于multiprocessing
(130 秒对 136 秒),但仍比串行(113 秒)慢。
编辑 2: 我意识到一些正则表达式可能会被复制,所以我添加了一个 dict 来缓存它们。这缩短了约 30 秒。不过,我仍然对并行化感兴趣。目标机器有 8 个处理器,这会将编译时间减少到约 15 秒。