2017-08-14 75 views
1

我正在研究jitclass,其中一种方法可以接受输入参数int,floatnumpy.ndarray。我需要能够确定参数是否是数组或任何其他两种类型。我已经使用isinstance尝试如下图所示的interp方法:确定jitclass方法的输入参数类型

spec = [('x', float64[:]), 
     ('y', float64[:])] 


@jitclass(spec) 
class Lookup: 
    def __init__(self, x, y): 
     self.x = x 
     self.y = y 

    def interp(self, x0): 
     if isinstance(x0, (float, int)): 
      result = self._interpolate(x0) 
     elif isinstance(x0, np.ndarray): 
      result = np.zeros(x0.size) 
      for i in range(x0.size): 
       result[i] = self._interpolate(x0[i]) 
     else: 
      raise TypeError("`interp` method can only accept types of float, int, or ndarray.") 
     return result 

    def _interpolate(self, x0): 
     x = self.x 
     y = self.y 
     if x0 < x[0]: 
      return y[0] 
     elif x0 > x[-1]: 
      return y[-1] 
     else: 
      for i in range(len(x) - 1): 
       if x[i] <= x0 <= x[i + 1]: 
        x1, x2 = x[i], x[i + 1] 
        y1, y2 = y[i], y[i + 1] 

        return y1 + (y2 - y1)/(x2 - x1) * (x0 - x1) 

,但我得到了以下错误:

numba.errors.TypingError: Failed at nopython (nopython frontend) 
Failed at nopython (nopython frontend) 
Untyped global name 'isinstance': cannot determine Numba type of <class 'builtin_function_or_method'> 
File "Lookups.py", line 17 
[1] During: resolving callee type: BoundFunction((<class 'numba.types.misc.ClassInstanceType'>, 'interp') for instance.jitclass.Lookup#2167664ca28<x:array(float64, 1d, A),y:array(float64, 1d, A)>) 
[2] During: typing of call at <string> (3) 

有没有一种方法来确定一个输入变量是否是某种类型的当使用jitclasses或在nopython模式?

编辑

我之前提到这一点,但使用type内置也似乎并没有工作。例如,如果我更换interp法:

def interp(self, x0): 
     if type(x0) == float or type(x0) == int: 
      result = self._interpolate(x0) 
     elif type(x0) == np.ndarray: 
      result = np.zeros(x0.size) 
      for i in range(x0.size): 
       result[i] = self._interpolate(x0[i]) 
     else: 
      raise TypeError("`interp` method can only accept types of float, int, or ndarray.") 
     return result 

我收到以下错误:

numba.errors.TypingError: Failed at nopython (nopython frontend) 
Failed at nopython (nopython frontend) 
Invalid usage of == with parameters (class(int64), Function(<class 'float'>)) 

我认为这是指蟒蛇float的比较和numba的int64当我这样做lookup_object.interp(370)例如。

回答

2

你的运气了,如果你需要确定,并因为isinstance完全不和type支持支持比较一numba jitclass内或nopython jit函数的类型只有几个数字类型和命名的数组(注意,这只是返回类型 - 它不适合比较 - 因为==不适用于numba函数内的类)。

作为Numba 0.35的唯一支持的内置插件是(来源:numba documentation):

The following built-in functions are supported:

abs() 
bool 
complex 
divmod() 
enumerate() 
float 
int: only the one-argument form 
iter(): only the one-argument form 
len() 
min() 
max() 
next(): only the one-argument form 
print(): only numbers and strings; no file or sep argument 
range: semantics are similar to those of Python 3 even in Python 2: a range object is returned instead of an array of values. 
round() 
sorted(): the key argument is not supported 
type(): only the one-argument form, and only on some types (e.g. numbers and named tuples) 
zip() 

我的建议:使用一个普通的Python类和确定类型那里,然后前进到numba.njit泰德相应功能:

import numba as nb 
import numpy as np 

@nb.njit 
def _interpolate_one(x, y, x0): 
    if x0 < x[0]: 
     return y[0] 
    elif x0 > x[-1]: 
     return y[-1] 
    else: 
     for i in range(len(x) - 1): 
      if x[i] <= x0 <= x[i + 1]: 
       x1, x2 = x[i], x[i + 1] 
       y1, y2 = y[i], y[i + 1] 

       return y1 + (y2 - y1)/(x2 - x1) * (x0 - x1) 

@nb.njit 
def _interpolate_many(x, y, x0): 
    result = np.zeros(x0.size, dtype=np.float_) 
    for i in range(x0.size): 
     result[i] = _interpolate_one(x, y, x0[i]) 
    return result 

class Lookup: 
    def __init__(self, x, y): 
     self.x = x 
     self.y = y 

    def interp(self, x0): 
     if isinstance(x0, (float, int)): 
      result = _interpolate_one(self.x, self.y, x0) 
     elif isinstance(x0, np.ndarray): 
      result = _interpolate_many(self.x, self.y, x0) 
     else: 
      raise TypeError("`interp` method can only accept types of float, int, or ndarray.") 
     return result 
+1

如果你的'x'和'y'确实很大(并且排序好了),你可能需要使用某种二分法。改变Pythons ['bisect'](https://github.com/python/cpython/blob/master/Lib/bisect.py)函数中的一个不应该太复杂,以便在'nb.njit '特德。 – MSeifert

+1

我认为这可能是这种情况。希望将来他们支持njitted方法/函数的某种形式的重载。我基本上按照你所说的做了,但采用了“一”和“多”情况的静态方法。 – pbreach

-1

使用type()

blah = [] 
if type(blah) is list: 
    print "Is a list" 

blah = 5 
if type(blah) is int: 
    print "we have an int" 

即:

>>> blah = 5 
>>> type(blah) 
<type 'int'> 
>>> 
+0

@HughBothwell见为什么isinstance没有工作问题的错误。这是我的第一选择。 – pbreach

+1

我尝试使用类型,但这也没有奏效。我编辑了这个问题来展示这一点。 – pbreach

+0

阅读完一些后,尝试使用'isinstance(x0,(int,np.uint))' – VeNoMouS

相关问题