Numpy数组元素数增4倍但内存大小增32倍的原因排查
问题分析与解答
核心原因:数据类型不匹配
你看到的32倍内存差异,本质是原数组与新数组的数据类型(dtype)不一致:
- 原数组是单通道图像,大概率是
uint8类型(每个元素占1字节),这是图像存储的常规类型。 - 你的代码里用
np.zeros()创建新数组时,没有指定dtype,numpy默认会使用float64类型(每个元素占8字节)。
计算验证:
- 原数组元素总数:
1684 × 129 × 522,总字节数为元素数 × 1 ≈ 113MB(和你输出的Initial size数值一致)。 - 新数组元素总数是原数组的4倍,每个元素占8字节,总字节数就是原数组的
4×8=32倍,完全匹配你看到的Final size。
补充:sys.getsizeof()返回的是numpy数组对象的总内存(包括数据缓冲区和对象本身的额外开销),如果要更精准查看数据部分的内存占用,建议使用数组的nbytes属性,你可以分别打印episode.nbytes和final_episode.nbytes来验证上述结论。
代码存在的问题
你的代码逻辑能生成目标形状的数组,但有两处可以优化的点:
- 未保持原数组的数据类型:创建
new_episode和初始化deque中的数组时,应该指定dtype与原数组一致,避免不必要的内存浪费:def create_frame_windows(episode, frame_window_length=4): episode_length, dim1, dim2 = episode.shape # 显式指定dtype为原数组的类型 new_episode = np.zeros((episode_length, frame_window_length, dim1, dim2), dtype=episode.dtype) data_q_deque = deque(maxlen=4) for _ in range(frame_window_length): # 初始化数组时也用原dtype data_q_deque.append(np.zeros((dim1, dim2), dtype=episode.dtype)) data_q = np.array(data_q_deque) print('Initial data queue', data_q.shape) for frame_no in range(len(episode)): frame = episode[frame_no] data_q[:-1] = data_q[1:]; data_q[-1] = frame new_episode[frame_no] = data_q print('New episode length', new_episode.shape) return new_episode - 滑动窗口实现可以更高效:用numpy的索引技巧可以替代循环和deque操作,大幅提升效率:
这种方式完全避免了循环操作,运行效率更高,同时也能保持原数组的dtype。def create_frame_windows(episode, frame_window_length=4): episode_length, dim1, dim2 = episode.shape # 生成滑动窗口的索引矩阵 indices = np.arange(episode_length)[:, None] - np.arange(frame_window_length) # 处理边界:前frame_window_length-1个窗口的左侧用0填充(和原逻辑一致) indices[indices < 0] = 0 # 按索引提取窗口 new_episode = episode[indices] # 调整维度顺序以匹配原输出(原输出是(帧序号, 窗口内帧, dim1, dim2)) new_episode = new_episode[:, ::-1, :, :] return new_episode
内容的提问来源于stack exchange,提问作者Swami
相关产品推荐
相关产品推荐

