我可以使用PyOpenCL与Scipy集成来与GPU并行执行差分进化吗



我得到了使用差分进化模拟多元回归模型的代码,甚至得到了多处理选项来帮助减少运行时间。然而,有7个自变量,每个自变量有10个值,对21个100多个元素的矩阵进行矩阵运算,对24个核心进行运算需要一些时间。我对PyOpenCL的多处理没有太多经验,所以我想问一下是否值得进入并尝试将两者集成到GPU上。我附上了3个变量和3个值的代码片段供参考:

import scipy.optimize as op
import numpy as np
def func(vars, *args):
res = []
x = []
for i in args[1:]:
if len(res) + 1 > len(args)//2:
x.append(i)
continue
res.append(np.array(i).T)

f1 = 0
for i in range(len(x[0])):
for j in range(len(x[1])):
diff = (vars[0]*x[0][i] + vars[1])*(vars[2]*x[1][j]*x[1][j] + vars[3]*x[1][j] + vars[4])*(vars[5]*50*50 + vars[6]*50 + vars[7])
f1 = f1 + abs(res[0][i][j] - diff) # ID-Pitch

f2 = 0
for i in range(len(x[0])):
for j in range(len(x[2])):
diff = (vars[0]*x[0][i] + vars[1])*(vars[5]*x[2][j]*x[2][j] + vars[6]*x[2][j] + vars[7])*(vars[2]*10*10 + vars[3]*10 + vars[4])
f2 = f2 + abs(res[1][i][j] - diff) # ID-Depth

f3 = 0
for i in range(len(x[1])):
for j in range(len(x[2])):
diff = (vars[2]*x[1][i]*x[1][i] + vars[3]*x[1][i] + vars[4])*(vars[5]*x[2][j]*x[2][j] + vars[6]*x[2][j] + vars[7])*(vars[0]*3.860424005 + vars[1])
f3 = f3 + abs(res[2][i][j] - diff) # Pitch-Depth
return f1 + f2 + f3

def main():
res1 = [[134.3213274,104.8030828,75.28483813],[151.3351445,118.07797,84.82079556],[135.8343927,105.9836392,76.1328857]]
res2 = [[131.0645086,109.1574174,91.1952225],[54.74920444,30.31300092,17.36537062],[51.8931954,26.45139822,17.28693162]]
res3 = [[131.0645086,141.2210331,133.3192429],[54.74920444,61.75898314,56.52756593],[51.8931954,52.8191817,52.66531712]]
x1 = np.array([3.860424005,7.72084801,11.58127201])
x2 = np.array([10,20,30])
x3 = np.array([50,300,500])
interval = (-20,20)
bds = [interval,interval,interval,interval,interval,interval,interval,interval]
res = op.differential_evolution(func, bounds=bds, workers=-1, maxiter=100000, tol=0.01, popsize=15, args=([1,2,2], res1, res2, res3, x1, x2, x3))
print(res)

if __name__ == '__main__':
main()

首先,是的,这是可能的,func可以是一个函数,它将数据发送到GPU,然后等待计算完成,然后将数据传输回RAM,并将其返回给scipy。

将计算从CPU更改为GPU并不总是有益的,因为从GPU来回传输数据需要时间,所以例如,使用中等大小的笔记本电脑GPU,你根本不会得到任何加速,而且你的代码可能会更慢。减少GPU和RAM之间的数据传输可以使GPU比普通CPU快2-4倍,但您的代码需要数据传输,因此这是不可能的。

对于具有高带宽的强大GPU(如RTX2070、RTX3070或APU(,您可以期待更快的计算,因此GPU上的计算将比CPU快几倍,即使有数据传输,但这取决于CPU和GPU代码的代码实现。

最后,你的代码可以在不使用GPU的情况下加速,这可能是你在进行GPU计算之前应该做的第一件事,主要是通过使用像cython和numba这样的代码编译器,它可以在不进行重大修改的情况下毫不费力地将代码加速近100倍,但你应该将代码转换为只使用固定大小的预分配numpy数组,而不是列表,因为代码会更快,你甚至可以禁用GIL,让你的代码多线程,而且其中有很好的多线程循环实现。

最新更新