我正在尝试使用numba替代我们的一些cython代码。
下面:
@jit
def unique_in_sorted(arr):
result = np.empty_like(arr)
result[0] = arr[0]
last_out = arr[0]
count_out = 1
for i in range(len(arr)):
a = arr[i]
if a<last_out:
raise Exception("Input not sorted: {} .. {}".format(last_out, a))
if last_out!=a:
result[count_out] = a
last_out = a
return result.resize(count_out)
...我发现上面的速度与vanilla python的速度大致相同。
def test_unique_in_sorted(self):
unsorted = np.random.random_integers(0, 200, 1000000)
a = np.sort(unsorted)
for x in range(10):
with timed("unique_in_sorted"):
r = unique_in_sorted(a)
unique_in_sorted.inspect_types()
查看inspect_types的输出似乎所有局部变量都是python对象,而不是类型化的C值。例如,在inspect_types输出中,我们有:
# $0.12 = getitem(index=$const0.11, value=arr) :: pyobject
# last_out = $0.12 :: pyobject
last_out = arr[0]
这让我觉得last_out被视为pyobject,而不是arr中的int64。
是否有办法优化上述内容,以便以与同等cython实现类似的速度运行?
这里是inspect_types的完整输出。
unique_in_sorted (array(int64, 1d, C),)
--------------------------------------------------------------------------------
# File: /home/user1/py/fast_ops.py
# --- LINE 142 ---
# label 0
# del $0.1
# del $0.2
# del $0.4
# del $const0.6
# del $const0.9
# del $0.7
# del $const0.11
# del $0.12
# del $const0.13
@jit
# --- LINE 143 ---
def unique_in_sorted(arr):
# --- LINE 144 ---
# arr = arg(0, name=arr) :: pyobject
# $0.1 = global(np: <module 'numpy' from '/usr/local/lib/python2.7/dist-packages/numpy/__init__.pyc'>) :: pyobject
# $0.2 = getattr(attr=empty_like, value=$0.1) :: pyobject
# $0.4 = call $0.2(arr, kws=[], args=[Var(arr, /home/user1/py/fast_ops.py (144))], func=$0.2, vararg=None) :: pyobject
# result = $0.4 :: pyobject
result = np.empty_like(arr)
# --- LINE 145 ---
# $const0.6 = const(int, 0) :: pyobject
# $0.7 = getitem(index=$const0.6, value=arr) :: pyobject
# $const0.9 = const(int, 0) :: pyobject
# result[$const0.9] = $0.7 :: pyobject
result[0] = arr[0]
# --- LINE 146 ---
# $const0.11 = const(int, 0) :: pyobject
# $0.12 = getitem(index=$const0.11, value=arr) :: pyobject
# last_out = $0.12 :: pyobject
last_out = arr[0]
# --- LINE 147 ---
# $const0.13 = const(int, 1) :: pyobject
# count_out = $const0.13 :: pyobject
# jump 45
# label 45
count_out = 1
# --- LINE 148 ---
# jump 48
# label 48
# $48.1 = global(range: <built-in function range>) :: pyobject
# $48.2 = global(len: <built-in function len>) :: pyobject
# $48.4 = call $48.2(arr, kws=[], args=[Var(arr, /home/user1/py/fast_ops.py (144))], func=$48.2, vararg=None) :: pyobject
# del $48.2
# $48.5 = call $48.1($48.4, kws=[], args=[Var($48.4, /home/user1/py/fast_ops.py (148))], func=$48.1, vararg=None) :: pyobject
# del $48.4
# del $48.1
# $48.6 = getiter(value=$48.5) :: pyobject
# del $48.5
# $phi64.1 = $48.6 :: pyobject
# del $48.6
# jump 64
# label 64
# $64.2 = iternext(value=$phi64.1) :: pyobject
# $64.3 = pair_first(value=$64.2) :: pyobject
# $64.4 = pair_second(value=$64.2) :: pyobject
# del $64.2
# $phi153.2 = $phi64.1 :: pyobject
# del $phi153.2
# $phi153.1 = $64.3 :: pyobject
# del $phi153.1
# $phi67.1 = $64.3 :: pyobject
# del $64.3
# branch $64.4, 67, 153
# label 67
# del $64.4
# i = $phi67.1 :: pyobject
# del $phi67.1
# del i
# del $67.4
# label 155
# del a
# del $119.3
# jump 64
for i in range(len(arr)):
# --- LINE 149 ---
# $67.4 = getitem(index=i, value=arr) :: pyobject
# a = $67.4 :: pyobject
a = arr[i]
# --- LINE 150 ---
# $67.7 = a < last_out :: pyobject
# branch $67.7, 92, 119
# label 92
# del result
# del count_out
# del arr
# del $phi64.1
# del $67.7
# del $const92.2
# del last_out
# del a
# del $92.3
# del $92.6
# del $92.1
if a<last_out:
# --- LINE 151 ---
# $92.1 = global(Exception: <type 'exceptions.Exception'>) :: pyobject
# $const92.2 = const(str, Input not sorted: {} .. {}) :: pyobject
# $92.3 = getattr(attr=format, value=$const92.2) :: pyobject
# $92.6 = call $92.3(last_out, a, kws=[], args=[Var(last_out, /home/user1/py/fast_ops.py (146)), Var(a, /home/user1/py/fast_ops.py (149))], func=$92.3, vararg=None) :: pyobject
# $92.7 = call $92.1($92.6, kws=[], args=[Var($92.6, /home/user1/py/fast_ops.py (151))], func=$92.1, vararg=None) :: pyobject
# raise $92.7
# label 119
# del $67.7
raise Exception("Input not sorted: {} .. {}".format(last_out, a))
# --- LINE 152 ---
# $119.3 = last_out != a :: pyobject
# branch $119.3, 131, 155
# label 131
# del $119.3
# del a
if last_out!=a:
# --- LINE 153 ---
# result[count_out] = a :: pyobject
result[count_out] = a
# --- LINE 154 ---
# last_out = a :: pyobject
# jump 155
# label 153
# del last_out
# del arr
# del $phi67.1
# del $phi64.1
# del $64.4
# jump 154
# label 154
# del result
# del count_out
# del $154.2
# del $154.4
last_out = a
# --- LINE 155 ---
# --- LINE 156 ---
# $154.2 = getattr(attr=resize, value=result) :: pyobject
# $154.4 = call $154.2(count_out, kws=[], args=[Var(count_out, /home/user1/py/fast_ops.py (147))], func=$154.2, vararg=None) :: pyobject
# $154.5 = cast(value=$154.4) :: pyobject
# return $154.5
return result.resize(count_out)
答案 0 :(得分:1)
事实证明异常处理将其置于对象模式。
修正如下:
@jit
def unique_in_sorted(arr):
result = np.empty_like(arr)
count_out =_unique_in_sorted(arr, result)
result.resize(count_out)
return result
@jit(nopython=True)
def _unique_in_sorted(arr, result):
result[0] = arr[0]
last_out = arr[0]
count_out = 1
for i in range(len(arr)):
a = arr[i]
# if a<last_out:
# raise Exception("Input not sorted: {} .. {}".format(last_out, a))
if last_out!=a:
result[count_out] = a
last_out = a
return count_out