2017-03-08 76 views
-3

我是Numba的新手,并且正在努力加速一些已经证明对于numpy来说过于笨拙的计算。我在下面给出的例子比较了一个包含我的计算子集的函数,该函数使用向量化/ numpy和函数的numba版本,后者也通过评论@autojit装饰器测试为纯python。我的numba代码可以比numpy快吗

我发现numba和numpy版本相对于纯python提供了类似的加速,这两者都是大约10倍速度改进的因素。 numpy版本实际上比我的numba函数稍快,但由于这种计算的4D性质,当numpy函数中的数组的大小比这个玩具示例大得多时,我会很快耗尽内存。

这个加速是好的,但我经常看到从纯python移动到numba时,web上的加速度超过100x。

我想知道在nopython模式下移动到numba时是否会有普遍的预期速度增加。我还想知道是否有任何我的numba化功能的组件会限制进一步的速度增加。

import numpy as np                  
from timeit import default_timer as timer            
from numba import autojit                
import math                   


def vecRadCalcs(slope, skyz, solz, skya, sola):          

    nloc = len(slope)                 
    ntime = len(solz)                 
    [lenz, lena] = skyz.shape               
    asolz = np.tile(np.reshape(solz,[ntime,1,1,1]),[1,nloc,lenz,lena])     
    asola = np.tile(np.reshape(sola,[ntime,1,1,1]),[1,nloc,lenz,lena])     
    askyz = np.tile(np.reshape(skyz,[1,1,lenz,lena]),[ntime,nloc,1,1])     
    askya = np.tile(np.reshape(skya,[1,1,lenz,lena]),[ntime,nloc,1,1])     
    phi1 = np.cos(asolz)*np.cos(askyz)             
    phi2 = np.sin(asolz)*np.sin(askyz)*np.cos(askya- asola)       
    phi12 = phi1 + phi2                
    phi12[phi12> 1.0] = 1.0               
    phi = np.arccos(phi12)                

    return(phi)                  


@autojit                    
def RadCalcs(slope, skyz, solz, skya, sola, phi):          

    nloc = len(slope)                 
    ntime = len(solz)                 
    pop = 0.0                   
    [lenz, lena] = skyz.shape               
    for iiT in range(ntime):               
     asolz = solz[iiT]                
     asola = sola[iiT]                
     for iL in range(nloc):               
      for iz in range(lenz):              
       for ia in range(lena):             
        askyz = skyz[iz,ia]            
        askya = skya[iz,ia]            
        phi1 = math.cos(asolz)*math.cos(askyz)        
        phi2 = math.sin(asolz)*math.sin(askyz)*math.cos(askya- asola)  
        phi12 = phi1 + phi2            
        if phi12 > 1.0:             
         phi12 = 1.0             
        phi[iz,ia] = math.acos(phi12)          
        pop = pop + 1              

    return(pop)                  


zenith_cells = 90                  
azim_cells = 360                  
nloc = 10  # nominallly ~ 700             
ntim = 10  # nominallly ~ 200000             

slope = np.random.rand(nloc) * 10.0             
solz = np.random.rand(ntim) *np.pi/2.0             
sola = np.random.rand(ntim) * 1.0*np.pi            

base = np.ones([zenith_cells,azim_cells])            
skya = np.deg2rad(np.cumsum(base,axis=1))            
skyz = np.deg2rad(np.cumsum(base,axis=0)*90/zenith_cells)        

phi = np.zeros(skyz.shape)                

start = timer()                  
outcalc = RadCalcs(slope, skyz, solz, skya, sola, phi)        
stop = timer()                   
outcalc2 = vecRadCalcs(slope, skyz, solz, skya, sola)         
stopvec = timer()                  

print(outcalc)                   
print(stop-start)                  
print(stopvec-stop)                 

回答

0

在运行numba 0.31.0的机器上,Numba版本比矢量化解决方案快两倍。当对numba函数进行计时时,您需要多次运行该函数,因为您第一次看到写入代码的时间+运行时间。随后的运行将不包括自从Numba在内存中缓存jitted代码以来的时间开销。

另外,请注意你的函数并不计算同样的事情 - 你要小心,你使用类似np.allclose的结果比较相同的东西。

相关问题