使用 numba 快速重采样数组

Resampling an array fast with numba

我有一个函数,通过在现有数据点之间使用线性插值,将数组作为 returns 的上采样版本。输入数组大约有 5000 个元素。 我还想实现一个处理形状为 ~(4000, 5000) 的二维数组的版本。

为什么使用 numba njit 时此函数没有更快? 它在没有 numba 的一维数组上运行速度超快。使用 numba.njit 需要更长的时间。 非常感谢任何建议!

import numpy as np
import numba as nb

@nb.njit
def sync_sampl(time_series, repeat=10):
    if time_series.ndim == 1:
        time_series = time_series.repeat(repeat)
        # from https://mail.python.org/pipermail/scipy-user/2010-November/027574.html
        # by Dharas Pothina
        x = time_series
        xtmp = x.copy()
        xtmp[1:] = x[1:] - x[:-1]
        x_idx = np.nonzero(xtmp)[0]
        x_vals = x[x_idx]
        x_new = np.interp(np.arange(len(x)), x_idx, x_vals)
        x_new = x_new[:-(repeat - 1) or None]  # removing last elements to not get straight line at the end.
        return x_new
    else:
        # Implement 2d version here?
        pass

这里有一些使 Numba 代码更快的技巧:

  • 您可以告诉 Numba 输入数组是 连续的(仅当它为真时)并且 pre-compile 前面的函数不用在 运行 时间支付昂贵的编译时间。这是一个例子:@nb.njit('float[::1](float32[::1],int32)').
  • 您可以在 @nb.njit 上使用选项 parallel=True 并行 中执行一些 Numpy 函数。但是,大多数功能尚未 运行ning 与其并行。尽管如此,您仍然可以 运行 与 nb.prange.
  • 并行循环
  • 如评论中所述,Numba 通常在 循环 方面表现出色。 Numba 循环并不总是更快,因为编译后的 Numpy 代码往往比 Numba 的 JIT 代码更好地矢量化。但是,循环使您能够避免 creating/filling/reading 许多临时数组 使您的代码 内存绑定 。优化良好的循环通常还有助于减少执行自定义操作所需的指令数量。在你的情况下,从 xtmp = x.copy()x_vals = x[x_idx] 的行可以使用一个快速内存高效并行循环重写(因此没有临时缓冲区)。
  • 请注意,如果您确定代码中没有 NaN/+Inf/-Inf/-0 值(并且需要精确的 IEEE-754 规则,例如舍入),您也可以使用选项 fastmath=True ) 以进一步提高性能。尽管精度损失很大,但使用 32 位浮点数也可能有所帮助。