python - 如何使用多线程在python中共享变量(不可修改)?

标签 python multithreading

我正在尝试并行化我为顺序程序编写的函数。下面是输入和输出

输入 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/

相关文章:

python - 如何使用python用0填充列表

c - C 中的多线程

python - 如何使用 Python 多处理库在进程完成时请求新任务?

java - 在 Java 中识别和处理锁定线程的最佳方法

python - 使用 scikit-learn 在 Python 中使用稀疏矩阵进行 kNN 估计?

python - 操作 numpy 数组

multithreading - 什么是调用线程?

python - 为什么 `gevent.spawn` 与 monkeypatched `threading.Thread()` 不同?

python - 正则表达式 - 如何识别一个模式,直到找到第二个模式

python - 使用 astype() 将字符串转换为数字