为什么追加列表在多处理中比较慢

时间:2018-10-16 08:41:05

标签: python performance multiprocessing

在测试期间,我发现以下内容中MP方法的运行速度稍慢

def eat_time(j):
    result = []
    for j in range(10**4):
        a = 0
        for i in range(1000):
            a += 101
            result.append(a)
    return result

if __name__ == '__main__':
    #MP method
    t = time.time()
    pool = Pool()
    result = []
    data = pool.map(eat_time, [i for i in range(5)])
    for d in data:
        result += d
    print(time.time()-t) #11s for my computer

    #Normal method
    t = time.time()
    integers = []
    for i in range(5):
        integers += eat_time(i)
    print(time.time()-t) #8s for my computer

但是,如果我不要求将eat_time()更改为

来汇总数据
def eat_time(j):
    result = []
    for j in range(10**4):
        a = 0
        for i in range(1000):
            a += 101
            #result.append(a)
    return result

MP时间要快得多,现在我的计算机只需运行 3s ,而正常方法仍然需要 8s (符合预期)

result中分别声明了method,这对我来说很奇怪,我不希望追加会完全破坏MP。

我可以知道有正确的方法吗?为什么添加附件时MP会变慢?


已编辑评论

@torek和@akhavr​​o表示感谢。

是的,我知道创建过程需要花费时间,这就是引发问题的原因。

实际上,原始代码将for循环放到外面,并一次又一次地调用简单方法,在很多任务中(比我的情况多了10 ** 6次调用),它比普通方法要快一些。

因此,我更改为将代码放入其中并使该方法更加复杂。通过将for j in range(10**4):的这一行移至eat_time()

但是似乎使代码复杂化会由于较大的数据大小而导致通信滞后。

所以,答案可能无法解决。

1 个答案:

答案 0 :(得分:2)

不是由append引起的,但会导致返回带有附加元素的结果。您可以通过更改代码进行附加操作来进行测试,但仅返回结果的前几个元素。现在它应该可以再次更快地工作。

当您从Pool工作人员返回结果时,实际上这是作为来自多处理的队列来实现的。它可以工作,但是它并不是奇迹,它绝对比仅操纵内存结构慢得多。当您返回大量数据时,队列需要传输大量数据。

没有简单的解决方法。您可以尝试共享内存,但是由于增加了复杂性,我个人不喜欢它。更好的方法是重新设计您的应用程序,以便它不需要在进程之间传输大量数据。例如,是否有可能在您的工作程序中进一步处理数据,以便您不需要全部返回而仅返回已处理的子集?