Python Numba优化功能无速度增益

Python Numba优化功能无速度增益,python,performance,numpy,optimization,numba,Python,Performance,Numpy,Optimization,Numba,我已经编写了一些代码来计算不同卡车对300英尺长桥梁施加的弯矩。卡车数据包含在两个列表中:ax_列表和sp_列表,分别是轴重和轴间距 代码没什么大不了的,但是,这需要对数百万种不同的卡车类型重复,我正在尝试优化我的代码,当涉及实际数据大小集时,这需要很长时间 我尝试使用Numba来查看是否可以获得任何速度提升,但它没有改变执行时间,无论我是否为每个函数添加Numba@jit装饰器。我做错了什么?欢迎任何帮助!我还包括为下面1000条记录生成代表性伪数据的代码: import random fro

我已经编写了一些代码来计算不同卡车对300英尺长桥梁施加的弯矩。卡车数据包含在两个列表中:
ax_列表
sp_列表
,分别是轴重和轴间距

代码没什么大不了的,但是,这需要对数百万种不同的卡车类型重复,我正在尝试优化我的代码,当涉及实际数据大小集时,这需要很长时间

我尝试使用Numba来查看是否可以获得任何速度提升,但它没有改变执行时间,无论我是否为每个函数添加Numba
@jit
装饰器。我做错了什么?欢迎任何帮助!我还包括为下面1000条记录生成代表性伪数据的代码:

import random
from numba import jit
import numpy as np
from __future__ import division

#Generate Random Data Set

ax_list=[]
sp_list=[]

for i in xrange(1000):
    n = random.randint(3,10)
    ax = []
    sp = [0]
    for i in xrange(n):
        a = round(random.uniform(8,32),1)
        ax.append(a)
    for i in xrange(n-1):
        s = round(random.uniform(4,30), 1)
        sp.append(s)
    ax_list.append(ax)
    sp_list.append(sp)

#Input Parameters
L=300
step_size=4
cstep_size=4
moment_list=[]

@jit
#Simple moment function
def Moment(x):
    if x<L/2.0:
        return 0.5*x
    else:
        return 0.5*(L-x)

#Attempt to vectorize the Moment function, hoping for speed gains
vectMoment = np.vectorize(Moment,otypes=[np.float],cache=False)

@jit
#Truck movement function that uses the vectorized Moment function above
def SimpleSpanMoment(axles, spacings, step_size):
    travel = L + sum(spacings)
    spacings=list(spacings)
    maxmoment = 0
    axle_coords =(0-np.cumsum(spacings))
    while np.min(axle_coords) < L:
        axle_coords = axle_coords + step_size
        moment_inf = np.where((axle_coords >= 0) & (axle_coords <=L), vectMoment(axle_coords), 0)
        moment = sum(moment_inf * axles)
        if maxmoment < moment:
            maxmoment = moment
    return maxmoment
收益率:

1 loop, best of 3: 2 s per loop
我还尝试在jit装饰器中声明类型,但结果仍然没有变化


@jit('f8(f8)
@jit('f8(f8[:],f8[:],f8)])
分别用于这两个函数。

基本问题是,当您使用
nb.jit时,它遇到无法编译为本机代码的问题,它使用
对象模式,这可能会很慢。如果将
nopython=True
指定为大多数numba装饰器/函数的参数,则可以看到这一点。如果numba不能显式地键入变量,或者不知道如何转换函数,那么就会出现错误。这是一个版本,我相信它会产生与原始函数相同的结果。在我的机器上,你的代码运行大约需要2.7秒。下面的优化版本完全在
nopython
模式下运行,大约需要50毫秒(加速约50倍):

查看文档,了解Numba在
nopython
模式下支持什么:


注意,您可以在
nopython
模式下的numba函数内部使用
np.where
,但第三个参数必须是数组(例如
np.zeros_like(矩inf)
)而不是整数。我发现它比我在上面显式循环数组时编写函数的方式慢大约2倍。

基本问题是,当使用
nb.jit
时,它遇到无法编译为本机代码的问题,它使用
对象模式,这可能会很慢。如果将
nopython=True
指定为大多数numba装饰器/函数的参数,则可以看到这一点。如果numba不能显式地键入变量,或者不知道如何转换函数,那么就会出现错误。这是一个版本,我相信它会产生与原始函数相同的结果。在我的机器上,你的代码运行大约需要2.7秒。下面的优化版本完全在
nopython
模式下运行,大约需要50毫秒(加速约50倍):

查看文档,了解Numba在
nopython
模式下支持什么:


注意,您可以在
nopython
模式下的numba函数内部使用
np.where
,但第三个参数必须是数组(例如
np.zeros_like(矩inf)
)而不是整数。我发现它比我在上面显式循环数组时编写函数的方式慢了大约2倍。

似乎你在这个问题上抛开了所有工具。我建议采取更系统的方法;尝试分析。Python评测非常简单。它将向您展示瓶颈,因此您可以战略性地利用您知道的工具。当然,这更好的原因是时间。我意识到没有办法学习世界上所有的优化工具。因此,您可以找到代码中最慢的部分,并了解一点有关解决此特定问题的新优化器的信息!我发现Numba在第二个函数中将所有Veriable作为python对象保存,而不是键入它们。不知道为什么。看起来你在这个问题上抛开了所有的工具。我建议采取更系统的方法;尝试分析。Python评测非常简单。它将向您展示瓶颈,因此您可以战略性地利用您知道的工具。当然,这更好的原因是时间。我意识到没有办法学习世界上所有的优化工具。因此,您可以找到代码中最慢的部分,并了解一点有关解决此特定问题的新优化器的信息!我发现Numba在第二个函数中将所有Veriable作为python对象保存,而不是键入它们。不知道为什么。非常感谢。这确实是我一直在寻找的解决方案。我的整个代码有20个左右的函数,如上面的例子。我将整个代码移到了Numba,并获得了x40~x50的加速。非常感谢。这确实是我一直在寻找的解决方案。我的整个代码有20个左右的函数,如上面的例子。我将整个代码移到了Numba,并获得了x40~x50的加速比。
1 loop, best of 3: 2 s per loop
@nb.vectorize(nopython=True)
#Simple moment function
def vectMoment2(x):
    if x<L/2.0:
        return 0.5*x
    else:
        return 0.5*(L-x)

@nb.jit(nopython=True)
#Truck movement function that uses the vectorized Moment function above
def SimpleSpanMoment2(axles, spacings, step_size):
    travel = L + np.sum(spacings)
    maxmoment = 0
    axle_coords = -np.cumsum(spacings)

    moment_inf = np.empty_like(axles)
    while np.min(axle_coords) < L:
        axle_coords = axle_coords + step_size
        y = vectMoment2(axle_coords)

        for k in range(y.shape[0]):
            if axle_coords[k] >=0 and axle_coords[k] <= L:
                moment_inf[k] = y[k]
            else:
                moment_inf[k] = 0.0

        moment = np.sum(moment_inf * axles)
        if maxmoment < moment:
            maxmoment = moment
    return maxmoment
%%timeit
for i in xrange(len(ax_list)):
    moment_list2.append(np.around(SimpleSpanMoment2(np.array(ax_list[i]), np.array(sp_list[i]), step_size),1))