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

NumPy中就地赋值为何比创建新数组更慢?与内存管理有关吗?

为什么NumPy中就地赋值D[:] = A @ B比创建新数组C = A @ B更慢?

核心原因不是内存分配的开销,而是额外的内存拷贝步骤和临时数组的处理,具体拆解如下:

1. 矩阵乘法的执行流程差异

  • 方法1(C = A @ B):
    NumPy调用BLAS/LAPACK底层库执行矩阵乘法时,会直接分配一块连续的内存块存储计算结果,这个过程是高度优化的——BLAS会利用CPU缓存、SIMD向量指令等最大化计算效率。最后只是把新数组的引用赋值给C,几乎没有额外开销。

  • 方法2(D[:] = A @ B):
    流程变成了两步:先计算A@B生成临时数组,再把临时数组的内容逐元素复制到D的内存空间里。这多出来的内存拷贝操作,才是拖慢速度的关键——尤其是当数组规模较大时,拷贝的开销远超过你以为的“重复内存分配”开销。

2. 内存分配的实际开销被高估

现代操作系统的内存管理器对固定大小的连续内存分配优化极强,加上NumPy自身的内存池机制,重复分配相同尺寸的数组时,开销几乎可以忽略不计。相比之下,额外的内存拷贝是实打实的线性时间开销,自然会让方法2变慢。

3. 内存布局与缓存的影响

矩阵乘法生成的临时数组默认是**C连续(行优先)**的内存布局,而即使D也是C连续的,复制过程也无法利用BLAS的高效计算指令,只能做简单的内存拷贝。如果D的内存布局不连续(比如之前做过切片转置等操作),拷贝的开销会更大。

正确的高效预分配方式

想要真正利用预分配提升性能,应该使用np.matmul的out参数,让计算结果直接写入预分配的数组,跳过临时数组的生成:

import numpy as np

A = np.random.rand(10, 10)
B = np.random.rand(10, 10000)
D = np.random.rand(10, 10000)

# 真正高效的原地计算
for i in range(20000):
    np.matmul(A, B, out=D)

用%timeit测试的话,这个版本的速度会和方法1持平甚至更快,因为它既复用了预分配的内存,又避免了临时数组的拷贝。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.19 07:22:46