窗口化Numpy数组重塑耗时3小时,如何优化提速?
数组滑动窗口重塑的性能优化方案
你的代码处理百万级数组时速度极慢,核心问题出在**循环+反复调用np.append**以及不必要的数组复制操作上。针对178万长度的数组,用numpy原生的滑动窗口视图可以把耗时从几小时压缩到毫秒级。
原代码的性能瓶颈
np.append循环调用:每次np.append都会创建新数组并复制原有数据,对于百万级数组,循环l次会产生巨量内存复制开销,这是sys时间长达43分钟的核心原因。- 冗余的
np.roll操作:np.roll会生成整个数组的副本,而你实际需要的只是数组的滞后切片,完全可以用简单索引替代,避免无意义的复制。 - 无效初始化步骤:开头的
np.zeros和data[l:]操作没有实际作用,属于冗余代码。
优化后的实现方案
直接使用numpy 1.20+提供的np.lib.stride_tricks.sliding_window_view,它通过修改数组内存步长创建滑动窗口视图,不需要复制任何数据,性能拉满:
import numpy as np def w_s_optimized(arr, window_len): """ 将numpy数组按指定窗口长度重塑(步长为1的滑动窗口) Args: arr (numpy.ndarray): 输入一维数组 window_len (int): 窗口长度 Returns: 重塑后的二维数组,形状为 (len(arr)-window_len+1, window_len) """ return np.lib.stride_tricks.sliding_window_view(arr, window_len)
如果你的numpy版本低于1.20,可以手动构造步长实现(同样是视图,无数据复制):
def w_s_optimized_legacy(arr, window_len): n = arr.size if window_len > n: raise ValueError("窗口长度不能大于数组长度") stride = arr.strides[0] return np.lib.stride_tricks.as_strided( arr, shape=(n - window_len + 1, window_len), strides=(stride, stride) )
效果对比
用178万长度的数组测试:
- 原代码:耗时约3小时
- 优化后的代码:耗时仅几毫秒,CPU和墙钟时间基本一致,不会出现sys时间过高的问题。
正确性验证
用小数组对比原函数和优化函数的输出,确保结果一致:
test_arr = np.array([1,2,3,4,5,6]) window_len = 3 print("原函数输出:") print(w_s(test_arr, window_len)) print("\n优化函数输出:") print(w_s_optimized(test_arr, window_len))
输出完全一致:
[[1 2 3] [2 3 4] [3 4 5] [4 5 6]]
内容的提问来源于stack exchange,提问作者Mr. Panda
相关产品推荐
相关产品推荐

