python - 如何使用 numba 加速积分,使用数组中的值重新定义积分
问题描述
我试图使用 python numba 更快地计算积分。即使使用 numba 进行单次计算的时间几乎快 10 倍,但当我循环重新定义积分的过程时,它变得非常慢。我尝试过使用其他装饰器,例如@vectorize
or@jit
但没有成功。关于如何做到这一点的任何提示?
import numpy as np
import datetime as dd
from scipy.integrate import quad
from numba import cfunc, types, carray
tempText = 'Time Elapsed: {0:.6f} sec'
arr = np.arange(0.01,1.01,0.01)
out = np.zeros_like(arr)
def tryThis(): # beginner's solution
for i in range(len(arr)):
def integrand(t):
return np.exp(-arr[i]*t)/t**2
def do_integrate(func):
return quad(func,1,np.inf)[0]
out[i] = do_integrate(integrand)
# print (out)
init = dd.datetime.now()
tryThis()
print (tempText.format((dd.datetime.now()-init).total_seconds()))
经过时间:0.047950 秒
def try2VectorizeThat(): # using numpy
def do_integrate(arr):
def integrand(t):
return np.exp(-arr*t)/t**2
return quad(integrand,1,np.inf)[0]
do_integrate = np.vectorize(do_integrate)
out = do_integrate(arr)
# print (out)
init = dd.datetime.now()
try2VectorizeThat()
print (tempText.format((dd.datetime.now()-init).total_seconds()))
经过时间:0.026424 秒
def tryThisFaster(): # attempting to use numba
for i in range(len(arr)):
def get_integrand(*args):
a = args[0]
def integrand(t):
return np.exp(-a*t)/t**2
return integrand
nb_integrand = cfunc("float64(float64)")(get_integrand(arr[i]))
def do_integrate(func):
return quad(func,1,np.inf)[0]
out[i] = do_integrate(nb_integrand.ctypes)
# print (out)
init = dd.datetime.now()
tryThisFaster()
print (tempText.format((dd.datetime.now()-init).total_seconds()))
经过时间:1.905140 秒
解决方案
请注意,您正在测量分配变量和定义包含的功能的时间。
此外,numba
当作业太小时,可能会变得(或看起来)更慢,因为它需要时间来编译自己然后应用。
放置integrand
在循环之外并进行装饰@njit
可以为您带来一些性能提升。让我们看一些比较:
from numba import njit
@njit
def integrand(t, i):
return np.exp(-arr[i]*t)/t**2
def tryFaster():
for i in range(len(arr)):
out[i] = quad(integrand, 1, np.inf, args=(i))[0]
时间len(arr) = 100
:
arr = np.arange(0.01,1.01,0.01)
%timeit tryThis()
# 29.9 ms ± 4.59 ms per loop (mean ± std. dev. of 7 runs, 10 loops each)
%timeit tryFaster()
# 4.99 ms ± 11.5 µs per loop (mean ± std. dev. of 7 runs, 1 loop each)
时间len(arr) = 10,000
:
arr = np.arange(0.01,100.01,0.01)
%timeit tryThis()
# 1.43 s ± 208 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)
%timeit tryFaster()
# 142 ms ± 17.7 ms per loop (mean ± std. dev. of 7 runs, 10 loops each)
推荐阅读
- r - 在“R”中向字符向量添加秒数
- macos - 终端消息:.zshrc:1:没有这样的文件或目录:
- java - 在 Java 中从浮点变量的输出中删除小数
- laravel - Gmail 没有收到我的 Laravel 用户验证电子邮件
- python-3.x - 未能在 Scrapy 中将类作为参数传递
- ada - 通过强类型和运算符重载进行简单的单元检查
- node.js - 如何让我的 API 函数将“字符串”返回给 Redis SETEX 值
- reactjs - 如何从 React 中的 Map() 对象返回反应标签树?
- encryption - 使用带有公钥的 OpenPGP.js 加密字符串
- python - Pandas DataFrame - 从 .txt 文件创建多个列