python - 优化列表推导的并行实现
问题描述
我有一个数据框,其中每一行都包含一个整数列表。我还有一个参考列表,用于检查数据框中的哪些整数出现在此列表中。
我对此做了两种实现,一种是单线程的,一种是多线程的。单线程实现非常快(在我的机器上大约需要 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)
解决方案
首先,当主进程与其他进程之间的数据通信成本与函数的时间成本相比时,多处理很有用。
另一件事是您在代码中犯了错误:
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)
推荐阅读
- android - react native基于类别重构现有JSON
- android - Android Studio 代码样式方案每次启动都会自动重置为默认值
- f# - 枚举一个有区别的联合
- ruby-on-rails - 为什么 group 或 group_by 不能在这个版本的 rails table 上工作?
- c - C - 步行一和零测试,通过进位旋转
- java - 将两个 CSV 文件导入 Java,然后解析它们。第一个有效第二个无效
- javascript - 如何检查特定地点或地点是否包含在谷歌地图 api 的当前视口中?
- angular - Angular4提供的参数与空行上调用目标的任何签名都不匹配
- google-tag-manager - Google 跟踪代码管理器和页面加载性能:它会降低 PageSpeed Insights 的性能吗?
- c# - DataGrid中的WPF双重排序