Numba:类方法

时间:2016-07-10 16:47:03

标签: numba

我有以下类和方法,应该将数组与内核进行卷积。

import numpy as np
from numpy.fft import fft2 as FFT, ifft2 as IFFT
from PIL import Image
from tqdm import trange, tqdm
from numba import jit

from time import sleep

import _kernel

class convolve(object):
    """ contains methods to convolve two images """
    def __init__(self, image_array, kernel):
        self.array = image_array
        self.kernel = kernel

        self.__rangeX_ = self.array.shape[0]
        self.__rangeY_ = self.array.shape[1]

        self.__rangeKX_ = self.kernel.shape[0]
        self.__rangeKY_ = self.kernel.shape[1]

        if (self.__rangeKX_ >= self.__rangeX_ or \
            self.__rangeKY_ >= self.__rangeY_):
            raise ValueError('Must submit suitable sizes for convolution.')

    @jit(nopython=True)
    def spaceConv(self):
        """ normal convolution, O(N^2*n^2). This is usually too slow """

        # pad array for convolution
        offsetX = self.__rangeKX_ // 2
        offsetY = self.__rangeKY_ // 2

        self.array = np.pad(self.array,               \
            [(offsetY, offsetY), (offsetX, offsetX)], \
               mode='constant', constant_values=0)

        # this is the O(N^2) part of this algorithm
        for i in xrange(self.__rangeX_ - 2*offsetX):
            for j in xrange(self.__rangeY_ - 2*offsetY):
                # Now O(n^2) portion
                total = 0.0
                for k in xrange(2*offsetX+1):
                    for t in xrange(2*offsetY+1):
                        total += self.kernel[k][t] * self.array[i+k][j+t]
                self.array[i+offsetX][j+offsetY] = total

        return self.array

作为附加说明(如果有人要求),_kernel只会生成特定的内核,可能需要将图像与其进行卷积(例如Gaussian,Moffat等),因此它与此类无关。

当我在图像和内核上调用上面的类时,我收到以下错误:

Traceback (most recent call last):
  File "fftconv.py", line 147, in <module>
    plt.imshow(conv.spaceConv(), interpolation='none', cmap='gray')
  File "/root/anaconda2/lib/python2.7/site-packages/numba/dispatcher.py", line 304, in _compile_for_args
    raise e
numba.errors.UntypedAttributeError: Caused By:
Traceback (most recent call last):
  File "/root/anaconda2/lib/python2.7/site-packages/numba/compiler.py", line 249, in run
    stage()
  File "/root/anaconda2/lib/python2.7/site-packages/numba/compiler.py", line 465, in stage_nopython_frontend
    self.locals)
  File "/root/anaconda2/lib/python2.7/site-packages/numba/compiler.py", line 789, in type_inference_stage
    infer.propagate()
  File "/root/anaconda2/lib/python2.7/site-packages/numba/typeinfer.py", line 717, in propagate
    raise errors[0]
UntypedAttributeError: Unknown attribute "rangeKX" of type pyobject
File "fftconv.py", line 45
[1] During: typing of get attribute at fftconv.py (45)

Failed at nopython (nopython frontend)
Unknown attribute "rangeKX" of type pyobject
File "fftconv.py", line 45
[1] During: typing of get attribute at fftconv.py (45)

This error may have been caused by the following argument(s):
- argument 0: cannot determine Numba type of value <__main__.convolve object at 0xaff5628c>

通常我非常善于通过Python错误追踪原因,但由于我不熟悉Numba的内部作品,我不确定它为什么不会这样做。知道offsetX是什么类型。有什么建议吗?

1 个答案:

答案 0 :(得分:1)

numba执行的一步是类型推断。这会将类型分配给函数中存在的不同值,以便它可以编译(以一种快速工作的方式)。

错误意味着numba不理解函数的第一个输入参数(在本例中为self)。 Numba在普通函数中效果最好,其中参数是标量或数组(所有数字)。一种选择是将O(n ^ 2)循环移动到它自己的函数中,并使该函数显式接收数组和任何其他值,并用numba.njit(或numba.jit(nopython = True)修饰该函数。 ),等同于

另外值得一试只是尝试删除“nopython = True”的代码“原样”。如果性能足够好,那就别管了:)这可能发生,因为numba.jit能够检测代码中的循环,这些循环可以在“no python”模式下编译并自动执行所需的操作,以便循环本身以全速模式编译。显式的“nopython = True”关键字会禁用该模式。