Python:如何加快这个函数的速度,使它更具可扩展性?

ua4mk5z4  于 2022-12-28  发布在  Python
关注(0)|答案(1)|浏览(110)

bounty将在7天后过期。回答此问题可获得+100的声誉奖励。user1769197正在寻找来自声誉良好的来源的答案

我有下面的函数,它接受一个形状为(20,000 x 20,000)。我必须运行函数20,000 x 20,000 = 400,000,000次。注意,indicator_Matrix必须以Pandas Dataframe 的形式作为参数传递到函数中,因为我实际问题的 Dataframe 有timeIndex和integer列,但是为了理解问题,我稍微简化了一下。

Pandas实现

indicator_Matrix = pd.DataFrame(np.random.randint(0,2,[20000,20000]))
def operations(indicator_Matrix):
   s = indicator_Matrix.sum(axis=1)
   d = indicator_Matrix.div(s,axis=0)
   res = d[d>0].mean(axis=0)
   return res.iloc[-1]

我试着用numpy来改进它,但它仍然需要很长时间才能运行。我也试过concurrent.future.ThreadPoolExecutor,但它仍然需要很长时间才能运行,而且从列表理解方面没有太大的改进。

Numpy实现

indicator_Matrix = pd.DataFrame(np.random.randint(0,2,[20000,20000]))
def operations(indicator_Matrix):
   s = indicator_Matrix.to_numpy().sum(axis=1)
   d = (indicator_Matrix.to_numpy().T / s).T
   d = pd.DataFrame(d, index = indicator_Matrix.index, columns = indicator_Matrix.columns)
   res = d[d>0].mean(axis=0)
   return res.iloc[-1]

output = [operations(indicator_Matrix) for i in range(0,20000**2)]

请注意,我再次将d转换为 Dataframe 的原因是,我需要获得列均值,并使用.iloc[-1]仅保留最后一列均值。d[d>0].mean(axis=0)返回列均值,即

2478    1.0
0       1.0

**更新:**我仍然卡在这个问题上,我想知道在我的本地桌面上使用cudfCuPy这样的gpu包是否会有什么不同。

5lhxktic

5lhxktic1#

你在做一些你不需要做的额外的数学运算。简单地英语,你在做的是:
1.对每列求和
1.“横向”旋转总和列表并在数组中进行划分
1.取每列的平均值,忽略零
1.仅返回最右边的均值
在第一步之后,除了最右边的列之外,您不再需要任何东西;你可以忽略剩下的。相应地修改你的代码:

def operations_simpler(indicator_matrix):
    sums = indicator_matrix.sum(axis=1)
    last_column = indicator_matrix.iloc[:, -1]
    divided = last_column / sums
    return divided[divided != 0].mean()

......产生相同的结果,并且花费大约百分之一的时间。从较短的测试运行推断,这将在我的机器上运行4亿次的时间从大约114年减少到......大约324天。仍然不是很好。到目前为止,我还没有设法通过转换为NumPy、使用Numba编译或使用多处理来使它运行得更快,但我还是先把这个贴出来吧,万一有用的话
注意:您不太可能看到线程对像这样的计算密集型工作有任何改进;如果有的话,您会希望使用多处理。concurrent.futures为这两种类型都提供了执行器。线程在避免等待I/O方面非常有用。

相关问题