似乎numba不支持numpy.resize
。
在nopython模式下使用numba.jit
动态增长数组的最佳方法是什么?
到目前为止,我能做的最好的事情是在jitted函数之外定义和调整数组,是否有更好的(更整洁)选项?
答案 0 :(得分:5)
numpy.resize
是pure python function:
import numpy as np
def resize(a, new_shape):
"""I did some minor changes so it all works with just `import numpy as np`."""
if isinstance(new_shape, (int, np.core.numerictypes.integer)):
new_shape = (new_shape,)
a = np.ravel(a)
Na = len(a)
if not Na:
return np.zeros(new_shape, a.dtype)
total_size = np.multiply.reduce(new_shape)
n_copies = int(total_size / Na)
extra = total_size % Na
if total_size == 0:
return a[:0]
if extra != 0:
n_copies = n_copies+1
extra = Na-extra
a = np.concatenate((a,)*n_copies)
if extra > 0:
a = a[:-extra]
return np.reshape(a, new_shape)
对于1D阵列,这可以直接实现自己。不幸的是,它对于ND阵列来说要复杂得多,因为在nopython numba函数中不支持某些操作:isinstance
,reshape
和元组乘法。这是1D等价物:
import numpy as np
import numba as nb
@nb.njit
def resize(a, new_size):
new = np.zeros(new_size, a.dtype)
idx = 0
while True:
newidx = idx + a.size
if newidx > new_size:
new[idx:] = a[:new_size-newidx]
break
new[idx:newidx] = a
idx = newidx
return new
当你不想要"重复输入"行为只用于增加大小它更容易:
@nb.njit
def resize(a, new_size):
new = np.zeros(new_size, a.dtype)
new[:a.size] = a
return new
这些函数用numba.njit
修饰,因此可以在nopython模式下的任何numba函数中调用。
但请注意:一般情况下,您不想调整大小 - 或者如果您这样做,请确保选择具有amoritzed O(1)
cost (Wikipedia link)的方法。如果您可以估计最大长度,那么最好立即预先分配正确大小(或稍微过度分配)的阵列。
答案 1 :(得分:1)
通常我采用的策略是分配足够多的数组存储以适应计算,然后跟踪所使用的最终索引/索引,然后在返回之前将数组切割为实际大小。这假设您事先知道阵列可能增大的最大大小。我的想法是,在我自己的大多数应用程序中,内存很便宜但是调整大小并在python和jitted函数之间切换很多都很昂贵。
答案 2 :(得分:0)
要动态增加现有数组的大小(因此就地进行),必须使用 numpy.ndarray.resize
而不是 numpy.resize
。此方法未在 Python 中实现,在 Numba 中不可用,因此无法完成。