Numba : "这个错误通常是由于传递了一个不被指定函数支持的类型的参数而引起的。"

问题描述 投票:0回答:1

当使用Numba的@jitclass装饰器调用对象上的类方法时,似乎不支持 "self "参数。不知道该怎么解释这些错误,一切都编译得很好,但尽管调用了其他numpy函数,但各个方法却不一致。

spec = [('raster',numba.float32[:,:]),('height', numba.int32),('width', numba.int32),('azis', numba.int64[:]),('grid',numba.int64),('rough',numba.float64[:,:]),('maxrange',numba.float64[:,:]),('aziratio',numba.float64[:,:]),('labels',numba.float64[:,:])]

@jitclass(spec)
class raster_class(object):
    def __init__(self,raster):
        self.raster = raster
        self.height =self.raster.shape[0]
        self.width = self.raster.shape[1]
        self.azis =  np.arange(0,170,10)
        self.grid = 500
        x = np.int(self.height/self.grid)
        y = np.int(self.width/self.grid)
        self.rough = np.zeros((x,y))
        self.maxrange = np.zeros((x,y)) 
        self.aziratio = np.zeros((x,y))
        self.labels = np.zeros((x,y))


    def detrend(self):
        raster -= ndimage.gaussian_filter(self.raster,sigma=40)
        return raster


    def SR(self,image):
        image = image[~np.isnan(image)] # remove nan's
        image = np.ndarray.flatten(image)
        mean = np.mean(image)

        return np.sqrt((1/(len(image)-1))*np.sum((image-mean)**2))
    def getRange(self,mat):
    # fits an anisotropic variogram model and returns the effective range for a given azimuth
        m,n = mat.shape
        vals = np.reshape(mat,(m*n,1))
        coords = []
        for i in range(m):
            for j in range(n):
                coords.append((i,j))
                coords = np.array(coords)
                response = np.hstack((coords,vals))
                response = response[~np.isnan(response[:,-1])]
                response = response[response[:,-1] != 0]
                response = response[~np.isnan(response[:,-1])]
                coords = response[:,:2]
                response = response[:,2]
                response += np.random.normal(0,scale=0.25,size=response.shape[0]) #add noise to prevent same values

         azi_r = []
         for azi in self.azis:
            DV =  DirectionalVariogram(coords,response,azimuth=azi,tolerance=15,maxlag=250,n_lags=20) 
            azi_r.append(DV.cof[0])

        major = np.argmax(azi_r)
        large_range = azi_r[major]
        major = azis[major]

        if major  >= 90:
            perp = major - 90
        else:
            perp = major + 90
        minor = azis.index(perp)
        minor_range = azi_r(minor)
        ratio = large_range/minor_range
        return ratio,large_range

    def iterate(self):
        for i in range(0,self.height-self.grid,self.grid):
            for j in range(0,self.width-self.grid,self.grid):
                image = self.raster[i:i+self.grid,j:j+self.grid]
                indi = int(i/self.grid)
                indj = int(j/self.grid)
                roughness = self.SR(image)
                ratio,range_ = self.getRange(image)
                self.azi_ratio[indi,indj] = ratio
                self.largest_range[indi,indj] = range_
                self.response_rough[indi,indj] = roughness

if __name__ == "__main__":
    brooks = np.load("brooks_dem.npy")
    brooks_class = raster_class(brooks)
    time = time.time()
    brooks_class.iterate()
    end_time = time.time() - time
    hours = end_time/3600
    print("Computation Took {} Hours".format(hours))

错误信息

This error is usually caused by passing an argument of a type that is unsupported by the 
named function.
[1] During: typing of intrinsic-call at /home/dunbar/DEM/processraster.py (35)

File "processraster.py", line 35:
    def SR(self,image):
        image = image[~np.isnan(image)] # remove nan's
        ^

[1] During: resolving callee type: BoundFunction((<class 
'numba.types.misc.ClassInstanceType'>, 'SR') for 
instance.jitclass.raster_class#55ac81be91b8<raster:array(float32, 2d, 
A),height:int32,width:int32,azis:array(int64, 1d, A),grid:int64,rough:array(float64, 2d, 
A),maxrange:array(float64, 2d, A),aziratio:array(float64, 2d, A),labels:array(float64, 2d, 
A)>)
[2] During: typing of call at /home/dunbar/DEM/processraster.py (81)


File "processrabster.py", line 81:
    def iterate(self):
        <source elided>
                indj = int(j/self.grid)
                roughness = self.SR(image)
                ^

[1] During: resolving callee type: BoundFunction((<class 
'numba.types.misc.ClassInstanceType'>, 'iterate') for 
instance.jitclass.raster_class#55ac81be91b8<raster:array(float32, 2d, 
A),height:int32,width:int32,azis:array(int64, 1d, A),grid:int64,rough:array(float64, 2d, 
A),maxrange:array(float64, 2d, A),aziratio:array(float64, 2d, A),labels:array(float64, 2d, 
A)>)
[2] During: typing of call at <string> (3)


File "<string>", line 3:
<source missing, REPL/exec in use?>
python numpy parallel-processing numba
1个回答
0
投票

问题似乎出在 SR 方法,不过不幸的是,除此之外,jitclass的错误信息并没有什么信息。由于这是一个静态方法,不过,一个非常简单的调试方法是将它作为一个独立的函数进行测试,即把 SR 出类拔萃,删除 self 参数,添加一个 @njit 装潢师,并运行 SR 在一个任意的二维数组上。

当我这样做的时候,我发现以下两个问题。

  1. image[~np.isnan(image)] 是一种 "花哨 "或 "高级 "的索引形式, 因为它使用布尔数组作为输入。Numba 只支持单一维度的高级索引image 是二维的。

  2. 你叫 flatten 像函数一样从其 ndarray 类,即 np.ndarray.flatten(image)但Numba只识别更标准的方法调用。image.flatten().

你可以通过改变两行的顺序来解决第1点,写上 image = image.flatten() 初次 image = image.ravel(),因为不需要复制),然后是 image = image[~np.isnan(image)] 第二。

幸运的是,对于您的特殊应用,有 徒劳无功因为它看起来像 SR 方法可以用调用 np.nanmeanNumba支持的。

更普遍的是,我赞同评论中提出的用Numba编译这样一个大类并不是真正的目的用途(至少目前是这样);最好是找出一些剖析的瓶颈,然后专门编译这些瓶颈。

© www.soinside.com 2019 - 2024. All rights reserved.