为何16G内存设备可生成10^12规模矩阵并赋值却运算时内存溢出?
为什么16G内存机器能创建10^12规模矩阵却在算术运算时内存溢出?
我在16G内存的机器上设置N=10^6,创建了一个10^12元素规模的矩阵,能正常给元素赋值,但执行算术运算时出现内存问题,具体操作如下:
In [103]: N=int(10**6) In [104]: A=np.zeros((N,N)) In [105]: A Out[105]: array([[0., 0., 0., ..., 0., 0., 0.], [0., 0., 0., ..., 0., 0., 0.], [0., 0., 0., ..., 0., 0., 0.], ..., [0., 0., 0., ..., 0., 0., 0.], [0., 0., 0., ..., 0., 0., 0.], [0., 0., 0., ..., 0., 0., 0.]]) In [106]: A[0,0]=3.14 In [107]: A Out[107]: array([[3.14, 0. , 0. , ..., 0. , 0. , 0. ], [0. , 0. , 0. , ..., 0. , 0. , 0. ], [0. , 0. , 0. , ..., 0. , 0. , 0. ], ..., [0. , 0. , 0. , ..., 0. , 0. , 0. ], [0. , 0. , 0. , ..., 0. , 0. , 0. ], [0. , 0. , 0. , ..., 0. , 0. , 0. ]]) In [108]: A = A+1 zsh: killed ipython
原因解析
- 惰性初始化+写时复制机制:
numpy.zeros创建全零矩阵时,并没有真的把10^12个0全部加载到物理内存,只是记录了矩阵的形状、数据类型等元信息。只有当你修改某个元素(比如A[0,0]=3.14)时,才会为这个元素分配实际的物理内存,其余未修改的元素仍以逻辑存在的形式占用虚拟内存,不消耗物理内存。 - 算术运算触发全量内存分配:执行
A = A+1时,numpy需要生成一个全新的同规模矩阵来存储运算结果,这时候必须为新矩阵分配完整的物理内存——106×106个float64元素,每个占8字节,总大小约7.28TB,远远超过16G的物理内存上限,内存耗尽后系统直接终止了进程。 - 赋值操作的局部性:单个元素赋值只修改极小部分内存,仅需分配8字节空间,完全在16G内存的承受范围内,因此不会出现问题。
内容的提问来源于stack exchange,提问作者zell
相关产品推荐
相关产品推荐

