You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何加速Numpy数组的滑动窗口子数组提取操作?

如何高效提取Numpy数组的滑动窗口子数组?

你的问题核心是循环中反复调用np.append导致的性能瓶颈——每次append都会创建新数组并复制已有数据,随着结果数组越来越大,这个操作的耗时会指数级上升。分半处理虽然能减半循环次数,但本质还是没解决重复复制的问题,所以提升有限。

这里给你两个高效的解决方案,完全不需要循环,利用Numpy的底层机制直接生成所有滑动窗口:

1. 优先推荐:使用np.lib.stride_tricks.sliding_window_view(Numpy 1.20+)

这是Numpy官方在1.20版本新增的安全滑动窗口工具,它不会复制原始数据,只是创建一个新的数组视图,速度和内存效率都拉满。

示例代码:

import numpy as np

a = np.array([55, 12, 12, ...])  # 你的大型输入数组
WINDOW = 300
window_length = WINDOW + 1  # 对应你原代码里的i:i+WINDOW+1

# 一步生成所有滑动窗口,形状为 (len(a)-WINDOW, WINDOW+1)
sliding_windows = np.lib.stride_tricks.sliding_window_view(a, window_shape=window_length)

生成的sliding_windows和你循环生成的new_a结构完全一致,但效率提升几个数量级,处理大型数组时几乎瞬间完成。

2. 低版本Numpy兼容方案:np.lib.stride_tricks.as_strided

如果你用的是低于1.20的Numpy版本,可以手动用as_strided实现,但要注意计算字节步长,避免内存越界:

import numpy as np

a = np.array([55, 12, 12, ...])
WINDOW = 300
window_length = WINDOW + 1
num_windows = len(a) - window_length + 1

# 计算原始数组的字节步长,这里假设数组是int64类型(每个元素8字节)
# 如果是其他类型,比如float32,要替换成a.itemsize
strides = (a.strides[0], a.strides[0])

sliding_windows = np.lib.stride_tricks.as_strided(
    a,
    shape=(num_windows, window_length),
    strides=strides
)

⚠️ 注意:as_strided直接操作内存,若计算错误可能导致读取非法内存,所以仅在无法升级Numpy时使用,优先选第一种方案。

为什么你的原有方法慢?

  • np.append本质是每次调用都执行np.concatenate,会把原有数据复制到新数组中。循环1000次就会复制1000次数据,数据量越大,每次复制的耗时越高。
  • 分半处理只是减少了循环次数,但每次循环里的append仍然在复制数据,所以只能减半耗时,无法从根本上解决问题。

内容的提问来源于stack exchange,提问作者Incompleteness

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.14 06:54:55