Tensor存儲結構以下,python
如圖所示,實際上極可能多個信息區對應於同一個存儲區,也就是上一節咱們說到的,初始化或者普通索引時常常會有這種狀況。ide
a = t.arange(0,6) print(a.storage()) b = a.view(2,3) print(b.storage()) print(id(a.storage())==id(b.storage())) a[1] = 10 print(b)
上面代碼,咱們經過.storage()能夠查詢到Tensor所對應的storage地址,能夠看到view雖然不是inplace的,但也僅僅是更改了對同一片內存的檢索方式而已,並無開闢新的內存:函數
0.0 1.0 2.0 3.0 4.0 5.0 [torch.FloatStorage of size 6] 0.0 1.0 2.0 3.0 4.0 5.0 [torch.FloatStorage of size 6] True 0 10 2 3 4 5 [torch.FloatTensor of size 2x3]
注意,id(a.storage())==id(c.storage()) != id(a[2])==id(a[0])==id(c[0]),id(a)!=id(c)blog
c = a[2:] print(c.storage()) # c所屬的storage也在這裏 print(id(a[2]), id(a[0]),id(c[0])) # 指向了同一處 print(id(a),id(c)) print(id(a.storage()),id(c.storage()))
0.0 10.0 2.0 3.0 4.0 5.0 [torch.FloatStorage of size 6] 2443616787576 2443616787576 2443616787576 2443617946696 2443591634888 2443617823496 2443617823496
d = t.Tensor(c.storage()) d[0] = 20 print(a) print(id(a.storage())==id(b.storage())==id(c.storage())==id(d.storage()))
storage_offset():偏移量
stride():步長,注意下面的代碼,步長比咱們一般理解的步長稍微麻煩一點,是有層次結構的步長索引
print(a.storage_offset(),b.storage_offset(),c.storage_offset(),d.storage_offset()) e = b[::2,::2] print(id(b.storage())==id(e.storage())) print(b.stride(),e.stride()) print(e.is_contiguous()) f = e.contiguous() # 對於內存不連續的張量,複製數據到新的連續內存中 print(id(f.storage())==id(e.storage())) print(e.is_contiguous()) print(f.is_contiguous()) g = f.contiguous() # 對於內存連續的張量,這個操做什麼都沒作 print(id(f.storage())==id(g.storage()))
高級檢索通常不共享stroage,這就是由於普通索引能夠經過修改offset、stride、size實現,二高級檢索出的結果座標更加混亂,不方便這樣修改,須要開闢新的內存進行存儲。內存
t.save和t.load,因爲torch的爲單獨Tensor指定設備的特性,實際保存時會保存設備信息,可是load是經過特定參數能夠加載到其餘設備,詳情help(torch.load),其餘的同numpy相似ci
Tensor天生支持廣播和矩陣運算,包含numpy等其餘庫在內,其矩陣計算效率遠高於python內置的for循環,能少用for就少用,換句話說python的for循環實現的效率很低。io
In [13]: a = t.randn(2,3)
In [14]: a
Out[14]:
1.1564 0.5561 -0.2968
-1.0205 0.8023 0.1582
[torch.FloatTensor of size 2x3]
In [15]: t.set_printoptions(precision=10)
In [16]: a
Out[16]:
1.1564352512 0.5561078787 -0.2968128324
-1.0205242634 0.8023245335 0.1582107395
[torch.FloatTensor of size 2x3]for循環
不少torch函數有out參數,這主要是由於torch沒有tf.cast()這類的類型轉換函數,也少有dtype參數指定輸出類型,因此須要事先創建一個輸出Tensor爲LongTensor、IntTensor等等,再由out導入,以下:ast
In [3]: a = t.arange(0, 20000000)
In [4]: print(a[-1],a[-2])
16777216.0 16777216.0
能夠看到溢出了數字,若是這樣處理,
In [5]: b = t.LongTensor()
In [6]: b = t.arange(0,20000000)
In [7]: b[-2]
Out[7]: 16777216.0
仍是不行,只能這樣,
In [9]: b = t.LongTensor()In [10]: t.arange(0,20000000,out=b)Out[10]: 0.0000e+00 1.0000e+00 2.0000e+00 ⋮ 2.0000e+07 2.0000e+07 2.0000e+07[torch.LongTensor of size 20000000]In [11]: b[-2]Out[11]: 19999998In [12]: b[-1]Out[12]: 19999999