Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/python-3.x/18.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python 3.x 如何正确使用Numba加速?_Python 3.x_Numba - Fatal编程技术网

Python 3.x 如何正确使用Numba加速?

Python 3.x 如何正确使用Numba加速?,python-3.x,numba,Python 3.x,Numba,我目前正在努力提高python函数的速度 def d_lat(dlat,R=6.371*1e6): return 2 * R * np.sqrt(np.sin(np.deg2rad(dlat)/2)**2) def d_lon(lat1,lat2,dlon,R=6.371*1e6): return 2 * R * np.sqrt(np.cos(np.deg2rad(lat1)) * np.cos(np.deg2rad(l

我目前正在努力提高python函数的速度

def d_lat(dlat,R=6.371*1e6):
    return 2 * R * np.sqrt(np.sin(np.deg2rad(dlat)/2)**2)


def d_lon(lat1,lat2,dlon,R=6.371*1e6):
    return 2 * R * np.sqrt(np.cos(np.deg2rad(lat1)) * 
                           np.cos(np.deg2rad(lat2)) *
                           np.sin(np.deg2rad(dlon)/2)**2)

def distance(u,v,lon1,lat1):
    lat2, lon2 = lat1.copy(), lon1.copy()
    lat2[v>0], lat2[v<0], = lat1[v>0]+1, lat1[v<0]-1,
    lon2[u>0], lon2[u<0], = lon1[u>0]+1, lon1[u<0]-1,
    dlon = lon2 - lon1
    dlat = lat2 - lat1
    return dlon, dlat
def d_lat(dlat,R=6.371*1e6):
    return 2 * R * np.sqrt(np.sin(np.deg2rad(dlat)/2)**2)

def d_lon(lat1,lat2,dlon,R=6.371*1e6):
    return 2 * R * np.sqrt(np.cos(np.deg2rad(lat1)) * 
                           np.cos(np.deg2rad(lat2)) *
                           np.sin(np.deg2rad(dlon)/2)**2)

def distance(u,v,lon1,lat1):
    lat2, lon2 = lat1.copy(), lon1.copy()
    lat2[v>0], lat2[v<0], = lat1[v>0]+1, lat1[v<0]-1,
    lon2[u>0], lon2[u<0], = lon1[u>0]+1, lon1[u<0]-1,
    dlon = lon2 - lon1
    dlat = lat2 - lat1
    return dlon, dlat
每个回路5.61 s±58.7 ms(7次运行的平均值±标准偏差,每个回路1次)

添加一个装饰器 每个回路7.76 s±64.9 ms(7次运行的平均值±标准偏差,每个回路1次)

正如您在上面看到的,我的Numba案例的计算速度比我的纯python案例慢。谁能帮我解决这个问题

ps:numba的版本
llvmlite 0.32.0rc1
numba 0.49.0rc2

------关于宏观经济学家答案的计算测试------ 根据他的回答,即使Numba现在已经足够聪明了,如果我们想要代码被Numba修饰,最好使用普通的“Fortran”/“C”类型的样式。下面是我正在思考的不同方法之间的计算时间比较

每个回路54 s±485 ms(7次运行的平均值±标准偏差,每个回路1次) 每个回路1min 21s±815ms(7次运行的平均值±标准偏差,每个回路1次) 每个回路1分钟2秒±239毫秒(7次运行的平均值±标准偏差,每个回路1次)
每个循环35.9 s±537 ms(7次运行的平均值±标准偏差,每个循环1次)有几个问题会跳出来

首先,您在
distance
函数中的计算不必要地复杂,并且以一种可能不适合Numba编译器的风格编写(带有许多花哨的索引,例如
lat2[v>0]
)。尽管Numba变得越来越聪明,但我发现以简单、面向循环的方式编写代码仍然有很高的回报

第二,可以通过可选参数稍微降低Numba的速度。我发现这主要适用于
distance
函数中的可选
R

解决了这两个问题——特别是用简化的循环来替换矢量化代码,从而最小化操作——我们得到了如下形式的代码

@numba.njit() 
def d_lat(dlat,R=6.371*1e6): 
    return 2 * R * np.sqrt(np.sin(np.deg2rad(dlat)/2)**2) 

@numba.njit() 
def d_lon(lat1,lat2,dlon,R=6.371*1e6): 
    return 2 * R * np.sqrt(np.cos(np.deg2rad(lat1)) *  
                           np.cos(np.deg2rad(lat2)) * 
                           np.sin(np.deg2rad(dlon)/2)**2) 

@numba.njit() 
def distance(u, v, lon1, lat1): 
    lon2 = np.empty_like(lon1) 
    lat2 = np.empty_like(lat1) 
    dlon = np.empty_like(lon1) 
    dlat = np.empty_like(lat1) 

    for i in range(len(v)): 
        vi = v[i] 
        if vi > 0: 
            lat2[i] = lat1[i]+1 
            dlat[i] = 1 
        elif vi < 0: 
            lat2[i] = lat1[i]-1 
            dlat[i] = -1 
        else: 
            lat2[i] = lat1[i] 
            dlat[i] = 0 

    for i in range(len(u)): 
        ui = u[i] 
        if ui > 0:  
            lon2[i] = lon1[i]+1 
            dlon[i] = 1 
        elif ui < 0: 
            lon2[i] = lon1[i]-1 
            dlon[i] = -1 
        else: 
            lon2[i] = lon1[i] 
            dlon[i] = 0 

    return d_lon(lat1,lat2,dlon), d_lat(dlat) 
@numba.njit()
def d_lat(dlat,R=6.371*1e6):
返回2*R*np.sqrt(np.sin(np.deg2rad(dlat)/2)**2)
@numba.njit()
定义长度(lat1、lat2、dlon,R=6.371*1e6):
返回2*R*np.sqrt(np.cos(np.deg2rad(lat1))*
np.cos(np.deg2rad(lat2))*
np.sin(np.deg2rad(dlon)/2)**2)
@numba.njit()
def距离(u、v、lon1、lat1):
lon2=np.空_样(lon1)
lat2=np.空\u类(lat1)
dlon=np.empty_like(lon1)
dlat=np.空_-like(lat1)
对于范围内的i(len(v)):
vi=v[i]
如果vi>0:
lat2[i]=lat1[i]+1
dlat[i]=1
elif vi<0:
lat2[i]=lat1[i]-1
dlat[i]=-1
其他:
lat2[i]=lat1[i]
dlat[i]=0
对于范围内的i(len(u)):
ui=u[i]
如果用户界面>0:
lon2[i]=lon1[i]+1
dlon[i]=1
elif ui<0:
lon2[i]=lon1[i]-1
dlon[i]=-1
其他:
lon2[i]=lon1[i]
dlon[i]=0
返回d_-lon(lat1、lat2、dlon)、d_-lat(dlat)

在我(速度较慢)的系统上,这将编译初始成本后的时间从大约7秒减少到大约4秒。在这一点上,我认为成本是由所有函数的原始成本支配的:代码> NP,SN < /代码>,<代码> NP.COS,<代码> NP.EXP>代码>等。

您可能想单独和不使用JIT单独考虑每个函数的时间,以查看NUBA是否得到改进。文档确实指出,Jit并不总是能够提高性能,而且由于变量的强类型化,Jit实际上可能会变得更慢。有时Jit确实会在规模上产生收益,但在小数据集上速度较慢。最后,您可能希望尝试在@numba.jit中使用签名,因为它可以让numba知道它将接收哪些数据类型,从而提高性能。签名?像@numba.njit(float32,float32,float32,float32)这样的函数距离?你认为如果我添加nogil=True或parallel=True,这两个参数会提高代码的速度吗?
@numba.njit()
def d_lat(dlat,R=6.371*1e6):
    return 2 * R * np.sqrt(np.sin(np.deg2rad(dlat)/2)**2)

@numba.njit()
def d_lon(lat1,lat2,dlon,R=6.371*1e6):
    return 2 * R * np.sqrt(np.cos(np.deg2rad(lat1)) * 
                           np.cos(np.deg2rad(lat2)) *
                           np.sin(np.deg2rad(dlon)/2)**2)

@numba.njit()
def distance(u, v, lon1, lat1, R=6.371*1e6):
    lat2, lon2 = lat1.copy(), lon1.copy()
    lat2[v>0], lat2[v<0], = lat1[v>0]+1, lat1[v<0]-1,
    lon2[u>0], lon2[u<0], = lon1[u>0]+1, lon1[u<0]-1,
    dlat = lat2 - lat1
    dlon = lon2 - lon1
    return d_lon(lat1,lat2,dlon), d_lat(dlat)
%%timeit
for i in range(10000):
    a,b = distance(u,v,lon1,lat1)
def d_lat(dlat,R=6.371*1e6):
    return 2 * R * np.sqrt(np.sin(np.deg2rad(dlat)/2)**2)

def d_lon(lat1,lat2,dlon,R=6.371*1e6):
    return 2 * R * np.sqrt(np.cos(np.deg2rad(lat1)) * 
                           np.cos(np.deg2rad(lat2)) *
                           np.sin(np.deg2rad(dlon)/2)**2)

def distance(u,v,lon1,lat1):
    lat2, lon2 = lat1.copy(), lon1.copy()
    lat2[v>0], lat2[v<0], = lat1[v>0]+1, lat1[v<0]-1,
    lon2[u>0], lon2[u<0], = lon1[u>0]+1, lon1[u<0]-1,
    dlon = lon2 - lon1
    dlat = lat2 - lat1
    return dlon, dlat
%%timeit
for i in range(10000):
    distance(u,v,lon1,lat1)
@numba.jit(nogil=True)
def d_lat(dlat,R=6.371*1e6):
    return 2 * R * np.sqrt(np.sin(np.deg2rad(dlat)/2)**2)

@numba.jit(nogil=True)
def d_lon(lat1,lat2,dlon,R=6.371*1e6):
    return 2 * R * np.sqrt(np.cos(np.deg2rad(lat1)) * 
                           np.cos(np.deg2rad(lat2)) *
                           np.sin(np.deg2rad(dlon)/2)**2)

def distance(u, v, lon1, lat1, R=6.371*1e6):
    lat2, lon2 = lat1.copy(), lon1.copy()
    lat2[v>0], lat2[v<0], = lat1[v>0]+1, lat1[v<0]-1,
    lon2[u>0], lon2[u<0], = lon1[u>0]+1, lon1[u<0]-1,
    dlat = lat2 - lat1
    dlon = lon2 - lon1
    return d_lon(lat1,lat2,dlon), d_lat(dlat)
%%timeit
for i in range(10000):
    a,b = distance(u,v,lon1,lat1)
def d_lat(dlat,R=6.371*1e6):
    return 2 * R * np.sqrt(np.sin(np.deg2rad(dlat)/2)**2)

def d_lon(lat1,lat2,dlon,R=6.371*1e6):
    return 2 * R * np.sqrt(np.cos(np.deg2rad(lat1)) * 
                           np.cos(np.deg2rad(lat2)) *
                           np.sin(np.deg2rad(dlon)/2)**2)

@numba.njit(nogil=True)
def distance(u, v, lon1, lat1, R=6.371*1e6):
    def d_lat(dlat,R=6.371*1e6):
        return 2 * R * np.sqrt(np.sin(np.deg2rad(dlat)/2)**2)             
    def d_lon(lat1,lat2,dlon,R=6.371*1e6):
        return 2 * R * np.sqrt(np.cos(np.deg2rad(lat1)) * 
                               np.cos(np.deg2rad(lat2)) *
                               np.sin(np.deg2rad(dlon)/2)**2)
    lat2, lon2 = lat1.copy(), lon1.copy()
    lat2[v>0], lat2[v<0], = lat1[v>0]+1, lat1[v<0]-1,
    lon2[u>0], lon2[u<0], = lon1[u>0]+1, lon1[u<0]-1,
    dlat = d_lat(lat2 - lat1)
    dlon = d_lon(lat1,lat2,lon2 - lon1)
    return dlon, dlat
%%timeit
for i in range(10000):
    a,b = distance(u,v,lon1,lat1)
@numba.njit() 
def d_lat(dlat,R=6.371*1e6): 
    return 2 * R * np.sqrt(np.sin(np.deg2rad(dlat)/2)**2) 

@numba.njit() 
def d_lon(lat1,lat2,dlon,R=6.371*1e6): 
    return 2 * R * np.sqrt(np.cos(np.deg2rad(lat1)) *  
                           np.cos(np.deg2rad(lat2)) * 
                           np.sin(np.deg2rad(dlon)/2)**2) 

@numba.njit() 
def distance(u, v, lon1, lat1): 
    lon2 = np.empty_like(lon1) 
    lat2 = np.empty_like(lat1) 
    dlon = np.empty_like(lon1) 
    dlat = np.empty_like(lat1) 

    for i in range(len(v)): 
        vi = v[i] 
        if vi > 0: 
            lat2[i] = lat1[i]+1 
            dlat[i] = 1 
        elif vi < 0: 
            lat2[i] = lat1[i]-1 
            dlat[i] = -1 
        else: 
            lat2[i] = lat1[i] 
            dlat[i] = 0 

    for i in range(len(u)): 
        ui = u[i] 
        if ui > 0:  
            lon2[i] = lon1[i]+1 
            dlon[i] = 1 
        elif ui < 0: 
            lon2[i] = lon1[i]-1 
            dlon[i] = -1 
        else: 
            lon2[i] = lon1[i] 
            dlon[i] = 0 

    return d_lon(lat1,lat2,dlon), d_lat(dlat) 
%%timeit
for i in range(10000):
    distance(u,v,lon1,lat1)
@numba.njit() 
def d_lat(dlat,R=6.371*1e6): 
    return 2 * R * np.sqrt(np.sin(np.deg2rad(dlat)/2)**2) 

@numba.njit() 
def d_lon(lat1,lat2,dlon,R=6.371*1e6): 
    return 2 * R * np.sqrt(np.cos(np.deg2rad(lat1)) *  
                           np.cos(np.deg2rad(lat2)) * 
                           np.sin(np.deg2rad(dlon)/2)**2) 

@numba.njit() 
def distance(u, v, lon1, lat1): 
    lon2 = np.empty_like(lon1) 
    lat2 = np.empty_like(lat1) 
    dlon = np.empty_like(lon1) 
    dlat = np.empty_like(lat1) 

    for i in range(len(v)): 
        vi = v[i] 
        if vi > 0: 
            lat2[i] = lat1[i]+1 
            dlat[i] = 1 
        elif vi < 0: 
            lat2[i] = lat1[i]-1 
            dlat[i] = -1 
        else: 
            lat2[i] = lat1[i] 
            dlat[i] = 0 

    for i in range(len(u)): 
        ui = u[i] 
        if ui > 0:  
            lon2[i] = lon1[i]+1 
            dlon[i] = 1 
        elif ui < 0: 
            lon2[i] = lon1[i]-1 
            dlon[i] = -1 
        else: 
            lon2[i] = lon1[i] 
            dlon[i] = 0 

    return d_lon(lat1,lat2,dlon), d_lat(dlat)