我正在尝试并行化我为顺序程序编写的函数。下面是输入输出
输入 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变量。如果您使用多线程,您的map 函数可以直接写入结果变量,因为有 GIL 的保护....但是您的并发性也会受到 GIL 的影响.
请注意,您可以通过传递较大的 chunksize 来调整 imap。您可以通过使用 imap_unordered 放宽有序要求来进一步优化。参见 multiprocessing获取更多信息。
