节约内存的方法

节约内存的方法

在python中,经常会有大量数据的计算,一般都通过多维数组来存储,或者一些库称之为张量。在读取大量数据的时候,有可能会遇到内存不足的情况,今天了解了一下对多维数组是如何分配内存的,又该如何节约内存。

主要通过测试python listnumpypytorch,对比这几个之间是否有区别。在做之前,自己的判断是没有区别的,先猜测在验证。

  1. python list
a = [[i for i in range(0, 4)] for j in range(3)]
b = [[i for i in range(4, 8)] for j in range(3)]
print(id(a))
print(id(b))
a = a + b
print(id(a))
a += b
print(id(a))
a[:] = a + b
print(id(a))
140434968054720
140434968053376
140434968099968
140434968099968
140434968099968

从上面的输出结果可以看到,刚开始赋值的时候aid为4720,bid为3376;
然后开始对a和b做加法操作,再赋值给a,结果a的id变成了9968,说明a = a + b,是将a + b的结果保存在新的内存中,再使a指向这个新内存地址;
接着计算a += b,a的id是9968,与计算之前的id相同,我们通常都说a += b等价于a = a + b,但是实际上只是结果等价,a += b可没有将a指向新的内存;
最后是使用切片的方式,id与计算之前相同。

  1. numpy
import numpy as np
# 在notebook中注意restart kernel
a = np.arange(12).reshape(3, -1)
b = np.arange(12).reshape(3, -1)
print(id(a))
print(id(b))
a = a + b
print(id(a))
a += b
print(id(a))
a[:] = a + b
print(id(a))
139670777306928
139670777331920
139670777332000
139670777332000
139670777332000
  1. pytorch
import torch
a = torch.arange(12).reshape(3, -1)
b = torch.arange(12).reshape(3, -1)
print(id(a))
print(id(b))
a = a + b
print(id(a))
a += b
print(id(a))
a[:] = a + b
print(id(a))
139881180034624
139881313662592
139881313683840
139881313683840
139881313683840

可见numpy和pytorch与python list的内存分配时一直的。

注意:
在python list中,对两个list做+运算,其实时对两个list进行拼接,并且- * /等操作是不能list对list操作的;
numpy和pytorch是按元素(elementwise)进行操作的,当两个多维数据的shape不相等时会调用广播机制(broadcasting mechanism)来执行按元素操作。

a = [[i for i in range(0, 4)] for j in range(3)]
b = [[i for i in range(4, 8)] for j in range(3)]
c = a
print(id(a), id(c))
print(a), print(c)
a += b
print(id(a), id(c))
print(a), print(c)
139909205242624 139909205242624
[[0, 1, 2, 3], [0, 1, 2, 3], [0, 1, 2, 3]]
[[0, 1, 2, 3], [0, 1, 2, 3], [0, 1, 2, 3]]
139909205242624 139909205242624
[[0, 1, 2, 3], [0, 1, 2, 3], [0, 1, 2, 3], [4, 5, 6, 7], [4, 5, 6, 7], [4, 5, 6, 7]]
[[0, 1, 2, 3], [0, 1, 2, 3], [0, 1, 2, 3], [4, 5, 6, 7], [4, 5, 6, 7], [4, 5, 6, 7]]

原地操作

import numpy as np

a = np.arange(12).reshape(3, -1)
b = np.arange(12).reshape(3, -1)
c = a
print('id a:', id(a), 'id c:', id(c))
print('a: \n', a), print('c: \n', c)
a = a + b
print('id a:', id(a), 'id c:', id(c))
print('a: \n', a), print('c: \n', c)
id a: 139909204801616 id c: 139909204801616
a: 
 [[ 0  1  2  3]
 [ 4  5  6  7]
 [ 8  9 10 11]]
c: 
 [[ 0  1  2  3]
 [ 4  5  6  7]
 [ 8  9 10 11]]
id a: 139912994696288 id c: 139909204801616
a: 
 [[ 0  2  4  6]
 [ 8 10 12 14]
 [16 18 20 22]]
c: 
 [[ 0  1  2  3]
 [ 4  5  6  7]
 [ 8  9 10 11]]

我们使用c = a其实就是将c指向id(a),当我们计算a = a + b时,由于a指向了新的内存地址,a的值更新了,但这并不会影响c的值。如果需要c的值跟着a变化,则可以使用原地操作:

import numpy as np

a = np.arange(12).reshape(3, -1)
b = np.arange(12).reshape(3, -1)
c = a
print('id a:', id(a), 'id c:', id(c))
print('a: \n', a), print('c: \n', c)
a[:] = a + b
print('id a:', id(a), 'id c:', id(c))
print('a: \n', a), print('c: \n', c)
a += b
print('id a:', id(a), 'id c:', id(c))
print('a: \n', a), print('c: \n', c)
id a: 139909204802336 id c: 139909204802336
a: 
 [[ 0  1  2  3]
 [ 4  5  6  7]
 [ 8  9 10 11]]
c: 
 [[ 0  1  2  3]
 [ 4  5  6  7]
 [ 8  9 10 11]]
id a: 139909204802336 id c: 139909204802336
a: 
 [[ 0  2  4  6]
 [ 8 10 12 14]
 [16 18 20 22]]
c: 
 [[ 0  2  4  6]
 [ 8 10 12 14]
 [16 18 20 22]]
id a: 139909204802336 id c: 139909204802336
a: 
 [[ 0  3  6  9]
 [12 15 18 21]
 [24 27 30 33]]
c: 
 [[ 0  3  6  9]
 [12 15 18 21]
 [24 27 30 33]]
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

ayiya_Oese

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值