深度学习框架pytorch入门之张量Tensor(四)——Tensor的内部结构

一、Tensor数据结构

Tensor数据结构tensor的结构分为头信息区(Tensor)和存储区(Storage),信息区主要保存着tensor的形状(size)、步长(stride)、数据类型(type)等信息,而真正的数据则保存成连续数组。由于数据规模庞大,因此信息区的元素占用内存较少,主要内存占用取决于tensor中元素的数目,也就是存储区的大小。
一般而言,一个tensor有着与之相对应的storage,storage是在data之上封装的接口,便于使用,。不同tensor的头信息一般不同,但却可能使用相同的storage,也就是共享内存。下面拿几个共享内存的tensor举个例子

创建tensor:

In [17]: import torch as t
In [18]: a=t.arange(8)
In [19]: a
Out[19]: tensor([0, 1, 2, 3, 4, 5, 6, 7])
In [20]: a.storage()
Out[20]:
 0
 1
 2
 3
 4
 5
 6
 7
[torch.LongStorage of size 8]

以view方法改变tensor的形状

In [21]: b=a.view(2,4)
In [22]: b.storage()
Out[22]:
 0
 1
 2
 3
 4
 5
 6
 7
[torch.LongStorage of size 8]

下面我们通过判断两个tensor的storage的id是否相同来判断它们是否共享内存(一个对象的id值可以看作它在内存中的地址)

In [23]: id(a.storage)==id(b.storage)
Out[23]: True

从结果True可以看出,两个tensor的storage地址是一致的,也就是说它们共享内存。
从另一个方面讲,假如a,b共享内存,那么当我们对a修改后,b的数据也会随之改变,下面让我们来验证一下:

In [24]: a[0]=100
In [25]: b
Out[25]:
tensor([[100,   1,   2,   3],
        [  4,   5,   6,   7]])

从这几行代码我们看到,当把a的第一个元素修改为100后,b的第一个元素也变成了100,显然a,b共享内存。

接下来我们对a进行切片,并把它赋值给新的张量c

In [28]: c=a[2:]
In [29]: c
Out[29]: tensor([2, 3, 4, 5, 6, 7])
In [30]: c.storage()
Out[30]:
 100
 1
 2
 3
 4
 5
 6
 7
[torch.LongStorage of size 8]

我们可以看到,尽管在切片后新的张量c的元素仅仅为a的后六个,然而当我们查看c的storage时,我们仍可以惊奇的发现c的storage与a的一致,这意味着切片得到的张量c仍与原张量a共享内存。

data_ptr()函数用以查看tensor的首个元素的内存地址,我么可以查看一下a与c的首个元素的地址

In [31]: c.data_ptr(),a.data_ptr()
Out[31]: (2478227845200, 2478227845184)

从结果来看,c的首个元素地址地址比a的首个元素地址多了16,这是因为a比c多两个元素(每个元素8个字节(float)),而c是a从第三个元素开始切片得到的,由此更加印证了a与c共享内存。
可见,事实上绝大多数操作并不修改tensor的数据,只是修改他们的头信息,如形状,类型等等。通过这种机制可以节省内存,提升处理速度。一般而言,高级索引不共享内存,而普通索引共享内存。

二、有关tensor的其他一些话题

持久化:使用t.save和t.load可以实现tensor的保存和加载,在使用时可以指定使用的pickle模块(用以序列化对象并存储在磁盘上),在load时还可以将GPU tensor映射到CPU或者其他的GPU上。
在这里插入图片描述在这里插入图片描述向量化:向量化计算是一种特殊的并行计算方式,它可在同一时间内执行多个操作,通常是对不同的数据执行同一个或者同一批命令。向量化可极大地提高科学运算的效率。
下面我们一起了解一下向量化计算究竟如何提高运算效率

In [33]: def for_loop_add(x,y):
    ...:     result=[]
    ...:     for i,j in zip(x,y):
    ...:         result.append(i+j)
    ...:     return t.Tensor(result)
    ...:

In [34]: x=t.zeros(1000)

In [35]: y=t.ones(1000)

In [36]: %timeit -n 10 for_loop_add(x,y)
9.84 ms ± 1.83 ms per loop (mean ± std. dev. of 7 runs, 10 loops each)

In [37]:  %timeit -n 10 x+y
10.7 µs ± 5.57 µs per loop (mean ± std. dev. of 7 runs, 10 loops each)

可见,对于两个有1000个元素的tensor,向量化运算的时间仅为for循环的1/1000左右。

  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值