我正在尝试并行化我为顺序程序编写的函数。下面是输入和输出
输入 1,字符串列表:["foo bar los Angles", "foo bar new york", ...]
输入2,字符串列表作为字典:["los Angles", "new york"..]
我想从输入 1 中删除输入 2 中的所有字符串。因此输出将如下所示:
["foo bar", "foo bar"].
我可以使用双 for 循环来做到这一点。
res = []
for s1 in input1:
for s2 in input2:
if s2 in s1:
res.append(s1.replace(s2, ""))
但是在 200 万大小的列表输入 1(输入 2 是几千)上运行有点慢(在我的 MacBook Pro 上超过 10 分钟)。
我找到了一种使用 python 的 multithreading.dummy.Pool
的方法。并使用 pool.map 和全局变量来并行化它。但我担心全局变量的使用。这样做安全吗?有没有更好的方法让Python多线程共享变量(可能像apache Spark的mapPartions
)?
我现在使用Python 2.7。所以我更喜欢使用 python2 来回答。
最佳答案
通常建议在需要性能时避免多线程,因为 GIL 。幸运的是我们有multiprocessing !
#!/usr/bin/python
import itertools
import multiprocessing
in1 = ["foo bar los angles", "foo bar new york",]
in2 = ["los angles", "new york",]
results = []
def sub(arg):
s1, s2 = arg
if s2 in s1:
return s1.replace(s2, "")
pool = multiprocessing.Pool(4)
for result in pool.imap(sub, itertools.product(in1, in2)):
if result is not None:
results.append(result)
print results
听起来您的 200 万个商品列表已在内存中,因此您需要使用 imap
而不是 map
,以免将产品变成数以千计的项目列表。我还使用 itertools.product 来计算输入的笛卡尔积——这就是嵌套循环所做的事情。
您的要求在唯一性方面有点模糊 - 如果您找到匹配项,您只会添加到结果中。
由于我们只在主体中添加results
,因此无需担心全局results
变量。如果您使用多线程
,由于 GIL 的保护,您的 map
函数可以直接写入结果变量......但是您的并发性也会受到 GIL 的影响.
请注意,您可以通过传递较大的chunksize
来调整imap
。您可以通过使用 imap_unordered
放宽有序要求来进一步优化。请参阅multiprocessing了解更多信息。
关于python - 如何使用多线程在python中共享变量(不可修改)?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/37823289/