将多处理和并行性应用于 numpy 函数

Posted

技术标签:

【中文标题】将多处理和并行性应用于 numpy 函数【英文标题】:Applying multi processing and parallelism to numpy functions 【发布时间】:2021-04-18 01:51:07 【问题描述】:

我正在尝试并行化我的 numpy 代码以使其更快。原始的 numpy 数组 list_ 有超过 200 万个变量,所以很难计算这就是为什么我试图用 numpy 和多处理函数来计算我的计算。我如何利用下面的代码来处理多处理单元。我在下面有一个代码,我尝试过多处理,但我相信它不是很有效。函数 ym, xym ,std 是独立的,因此对这些函数进行多处理是可行的,但是 mk,bk 依赖于 ym, xym ,std 函数。

原版 Python 版

import numpy as np
number = 5
list_= np.array([457.334015,424.440002,394.795990,408.903992,398.821014,402.152008,435.790985,423.204987,411.574005,
404.424988,399.519989,377.181000,375.467010,386.944000,383.614990,375.071991,359.511993,328.865997,
320.510010,330.079010,336.187012,352.940002,365.026001,361.562012,362.299011,378.549011,390.414001,
400.869995,394.773010,382.556000])
ym = (np.convolve(list_, np.ones(shape=(number)), mode='valid')/number)[:-1]
xym = (np.convolve(list_, np.arange(number, 0, -1), mode='valid'))[:-1]
mk = (x_mean* ym- xym)/(np.power(x_mean,2)- x_squared_mean)
bk = ym - mk*x_mean
std = np.array([list_[i:i+number].std() for i in range(0, len(list_)-number)])

多处理版本

#x_mean and x_squared is used for the lin regressions and stand dev
x_mean = number/2*(1 + number)
x_squared_mean = number*(number+1)*(2*number+1)/6

def ym():   
    ym = (np.convolve(PC_list, np.ones(shape=(number)), mode='valid')/number)[:-1]
    print(ym)
def xym():
    xym = (np.convolve(PC_list, np.arange(number, 0, -1), mode='valid'))[:-1]
    print(xym)
def std():
    std = np.array([PC_list[i:i+number].std() for i in range(0, len(PC_list)-number)])
    print(std)
    
#setting up the multi processing vars     
p1 = multiprocessing.Process(target=ym)
p2 = multiprocessing.Process(target=xym)
p3 = multiprocessing.Process(target=std)

#running the multi processes 
p1.start()
p2.start()
p3.start()

p1.join()
p2.join()
p3.join()

xym()
ym()
std()

【问题讨论】:

【参考方案1】:

由于mkbk 确实依赖于ymxym,所以您无能为力,您必须先计算它们,然后才能在接下来的计算中使用它们。

我做了一个快速基准测试,看起来即使我有一个 2000 万个数组,卷积、mkbk 都运行在 0.3 秒以下。代码中真正的瓶颈是 std 函数。那是因为您使用的是 python for 循环,速度很慢。

Numba 救援

我的建议是调查numba。它可以将您的常规 python 函数编译为优化的机器代码,并使它们运行得非常快!它有一些限制,但对于你的情况,它会完美地工作。尝试将std 函数更改为:

from numba import njit

@njit 
def std_numba(x, n):
    std = np.array([x[i:i+n].std() for i in range(0, len(x)-n)])
    return std

即使没有任何类型的多处理,所有计算都在 200 万个浮点数的随机数组上在一秒钟内完成。

【讨论】:

感谢您的努力,目前我在 Windows 10 上安装 numba 库时遇到问题,但我会尽快安装它。

以上是关于将多处理和并行性应用于 numpy 函数的主要内容,如果未能解决你的问题,请参考以下文章

多处理的并行性几乎没有减少时间

将多处理函数的返回值放入矩阵

如何将多线程应用于方法

有效地将函数并行应用于分组的 pandas DataFrame

在本书的背景下,所谓的“细粒度并行”究竟意味着什么?

如何将多处理用于函数而不是循环?