首页 > 解决方案 > 优化列表推导的并行实现

问题描述

我有一个数据框,其中每一行都包含一个整数列表。我还有一个参考列表,用于检查数据框中的哪些整数出现在此列表中。

我对此做了两种实现,一种是单线程的,一种是多线程的。单线程实现非常快(在我的机器上大约需要 0.1 秒),而多线程大约需要 5 秒。

我的问题是:这是因为我的实现很差,还是这仅仅是多线程导致的开销太大以至于使用多个线程没有意义的情况?

示例如下:

import time
from random import randint
import pandas as pd
import multiprocessing
from functools import partial

class A:
    def __init__(self, N):
        self.ls = [[randint(0, 99) for i in range(20)] for j in range(N)]
        self.ls = pd.DataFrame({'col': self.ls})

        self.lst_nums = [randint(0, 99) for i in range(999)]

    @classmethod
    def helper(cls, lst_nums, col):
        return any([s in lst_nums for s in col])

    def get_idx_method1(self):
        method1 = self.ls['col'].apply(lambda nums: any(x in self.lst_nums for x in nums))
        return method1

    def get_idx_method2(self):
        pool = multiprocessing.Pool(processes=1)
        method2 = pool.map(partial(A.helper, self.lst_nums), self.ls['col'])
        pool.close()
        return method2

if __name__ == "__main__":

    a = A(50000)

    start = time.time()
    m1 = a.get_idx_method1()
    end = time.time()
    print(end-start)

    start = time.time()
    m2 = a.get_idx_method2()
    end = time.time()
    print(end - start)

标签: pythonmultithreadingpandas

解决方案


首先,当主进程与其他进程之间的数据通信成本与函数的时间成本相比时,多处理很有用。

另一件事是您在代码中犯了错误:

def helper(cls, lst_nums, col):
    return any([s in lst_nums for s in col])

VS

any(x in self.lst_nums for x in nums)

您在 helper 方法中有那个列表 [],这将使 any() 方法等待整个数组被计算,而第二个 any() 将停止在第一个 True 值处。

总之,如果您从辅助方法中删除列表括号并可能增加 lst_nums 初始化程序的 randint 范围,您会注意到使用多个进程时速度有所提高。

self.lst_nums = [randint(0, 10000) for i in range(999)]

def helper(cls, lst_nums, col):
    return any(s in lst_nums for s in col)

推荐阅读