首先理解什么是contiguous,判断一个tensor是不是contiguous的。
字面意思是连续的,当我们定义一个tensor时,在内存中数据是连续存储的。
如果我们使用transpose等一些 *** 作的时候,会改变连续性,使得数据在逻辑上的顺序与内存中的顺序不一致,这是因为transpose并没有改变tensor内存中的数据存储(data部分),只是改变了其索引(步长等),使得逻辑上的顺序(读取的顺序)发生了变化,但是内存中的顺序没有变。而一些 *** 作只能对连续的tensor使用,对非连续的tensor使用会报错,就需要通过contiguous(),重新开一块内存,将非连续tensor转换为连续的。
如tensor.transpose().view()将会报错,需要改成tensor.transpose().contiguous().view()
需要注意的是,如果对连续的tensor使用contiguous,将不会重新开辟内存,view *** 作过的tensor依然是连续的,view之后可以再接一个view *** 作。
reshape相当于contiguous+view,如果是连续的tensor,其与view相同,对非连续的张量,可以直接使用reshape而不能使用view。
那为什么还要存在view,是一个历史原因。
其他有关张量内存的内容:
如果我们简单的将一个tensor赋值给另一个tensor,则这两个tensor是共享同一内存的。如果不想共享内存,可以使用torch.clone()函数,需要注意的是,clone的tensor并不保存梯度,即本身grad为None,将梯度回传给源张量进行叠加。
如果原tensor的requires_grad=True,则:
clone() *** 作后的tensor requires_grad=True
detach() *** 作后的tensor requires_grad=False。
另一个比较特殊的是当源张量的 require_grad=False,
clone后的张量 require_grad=True,此时不存在张量回传现象,可以得到clone后的张量求导。
像y = x + y这样的运算会新开内存,然后将y指向新内存。我们可以使用Python自带的id函数进行验证:如果两个实例的ID相同,则它们所对应的内存地址相同。
使用索引 *** 作不会开辟新的内存,而想指定结果到原来的y的内存,我们可以使用索引来进行替换 *** 作。比如把x + y的结果通过[:]写进y对应的内存中。
torch.add(x, y, out=y)
y += x
y.add_(x)
Tensor 和tensor唯一区别在于方法名中t的大小写,大写字母T(Tensor)是类构造函数,第二种小写(tensor)是工厂函数。其中,torch.as_tensor 和 torch.from_numpy 也是工厂函数。
构造函数在构造一个张量时使用全局默认值,而工厂函数则根据输入推断数据类型。通过torch.get_default_dtype()可以查看dtype的全局默认值是torch.float32。
Tensor 和tensor是深拷贝,在内存中创建一个额外的数据副本,不共享内存,所以不受数组改变的影响。
from_numpy和as_tensor是浅拷贝,在内存中共享数据,他们不同之处就是在于对内存的共享。
torch.as_tensor()和torch.from_numpy() 函数使得numpy数组与Pytorch张量之间切换可以非常快。因为创建新的Pytorch张量时,数据是共享的,而不是后台复制的。共享数据比复制数据更有效使用更少的内存。因为数据没有写到内存中的两个位置,而是只有一个位置。
我们应该使用哪一种呢???
torch.tensor()是经常使用的。如果想做内存优化,使用torch.as_tensor(),这个为什么要比torch.from_numpy()好呢?因为,torch.as_tensor()函数可以接受任何像Python数据结构这样的数组。
参考:
https://zhuanlan.zhihu.com/p/344458484
https://zhuanlan.zhihu.com/p/345648168
https://blog.csdn.net/Flag_ing/article/details/109129752?spm=1001.2101.3001.6650.1&utm_medium=distribute.pc_relevant.none-task-blog-2%7Edefault%7ECTRLIST%7Edefault-1.opensearchhbase&depth_1-utm_source=distribute.pc_relevant.none-task-blog-2%7Edefault%7ECTRLIST%7Edefault-1.opensearchhbase
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)