当前位置: 首页>C语言>正文

詳解PyTorch中的contiguous

詳解PyTorch中的contiguous

目錄

前言

PyTorch中的is_contiguous是啥?

行優先

為什么需要?contiguous???

為什么不在view?方法中默認調用contiguous方法?


前言

contiguous 本身是形容詞表示連續的關于 contiguous,PyTorch 提供了is_contiguouscontiguous(形容詞動用)兩個方法 ,分別用于判定Tensor是否是 contiguous 的,以及保證Tensor是contiguous的。

PyTorch中的is_contiguous是啥?

is_contiguous直觀的解釋是Tensor底層一維數組元素的存儲順序與Tensor按行優先一維展開的元素順序是否一致

Tensor多維數組底層實現是使用一塊連續內存的1維數組(行優先順序存儲,下文描述),Tensor在元信息里保存了多維數組的形狀,在訪問元素時,通過多維度索引轉化成1維數組相對于數組起始位置的偏移量即可找到對應的數據。某些Tensor操作(如transpose、permute、narrow、expand)與原Tensor是共享內存中的數據,不會改變底層數組的存儲,但原來在語義上相鄰、內存里也相鄰的元素在執行這樣的操作后,在語義上相鄰,但在內存不相鄰,即不連續了(is not contiguous)。

如果想要變得連續使用contiguous方法,如果Tensor不是連續的,則會重新開辟一塊內存空間保證數據是在內存中是連續的,如果Tensor是連續的,則contiguous無操作。

行優先

行是指多維數組一維展開的方式,對應的是列優先。C/C++中使用的是行優先方式(row major),Matlab、Fortran使用的是列優先方式(column major),PyTorch中Tensor底層實現是C,也是使用行優先順序。舉例說明如下:

>>> t = torch.arange(12).reshape(3,4)
>>> t
tensor([[ 0,  1,  2,  3],[ 4,  5,  6,  7],[ 8,  9, 10, 11]])

二維數組 t 如圖1:

圖1. 3X4矩陣行優先存儲邏輯結構

?數組 t 在內存中實際以一維數組形式存儲,通過?flatten?方法查看 t 的一維展開形式,實際存儲形式與一維展開一致,如圖2,

>>> t.flatten()
tensor([ 0,  1,  2,  3,  4,  5,  6,  7,  8,  9, 10, 11])

圖2. 3X4矩陣行優先存儲物理結構

而列優先的存儲邏輯結構如圖3。

圖3. 3X4矩陣列優先存儲邏輯結構

使用列優先存儲時,一維數組中元素順序如圖4:?

圖4. 3X4矩陣列優先存儲物理結構

說明:圖1、圖2、圖3、圖4來自:What is the difference between contiguous and non-contiguous arrays??

圖1、圖2、圖3、圖4 中顏色相同的數據表示在同一行,不論是行優先順序、或是列優先順序,如果要訪問矩陣中的下一個元素都是通過偏移來實現,這個偏移量稱為步長(stride[1])。在行優先的存儲方式下,訪問行中相鄰元素物理結構需要偏移1個位置,在列優先存儲方式下偏移3個位置。

為什么需要?contiguous???

1.?torch.view等方法操作需要連續的Tensor。

transpose、permute 操作雖然沒有修改底層一維數組,但是新建了一份Tensor元信息,并在新的元信息中的 重新指定 stride。torch.view?方法約定了不修改數組本身,只是使用新的形狀查看數據。如果我們在 transpose、permute 操作后執行 view,Pytorch 會拋出以下

invalid argument 2: view size is not compatible with input tensor's size and stride (at least one dimension 
spans across two contiguous subspaces). Call .contiguous() before .view(). 
at /Users/soumith/b101_2/2019_02_08/wheel_build_dirs/wheel_3.6/pytorch/aten/src/TH/generic/THTensor.cpp:213

?為什么 view 方法要求Tensor是連續的[2]?考慮以下操作,

>>>t = torch.arange(12).reshape(3,4)
>>>t
tensor([[ 0,  1,  2,  3],[ 4,  5,  6,  7],[ 8,  9, 10, 11]])
>>>t.stride()
(4, 1)
>>>t2 = t.transpose(0,1)
>>>t2
tensor([[ 0,  4,  8],[ 1,  5,  9],[ 2,  6, 10],[ 3,  7, 11]])
>>>t2.stride()
(1, 4)
>>>t.data_ptr() == t2.data_ptr() # 底層數據是同一個一維數組
True
>>>t.is_contiguous(),t2.is_contiguous() # t連續,t2不連續
(True, False)

?t2 與 t 引用同一份底層數據?a,如下:

[ 0,  1,  2,  3,  4,  5,  6,  7,  8,  9, 10, 11]

,兩者僅是stride、shape不同。如果執行 t2.view(-1) ,期望返回以下數據?b(但實際會報錯):

[ 0,  4,  8,  1,  5,  9,  2,  6, 10,  3,  7, 11]

在?a?的基礎上使用一個新的 stride 無法直接得到?b?,需要先使用 t2 的 stride (1, 4) 轉換到 t2 的結構,再基于 t2 的結構使用 stride (1,) 轉換為形狀為 (12,)的?b?。但這不是view工作的方式view 僅在底層數組上使用指定的形狀進行變形,即使 view 不報錯,它返回的數據是:

[ 0,  1,  2,  3,  4,  5,  6,  7,  8,  9, 10, 11]

這是不滿足預期的。使用contiguous方法后返回新Tensor t3,重新開辟了一塊內存,并使用照 t2 的按行優先一維展開的順序存儲底層數據。

>>>t3 = t2.contiguous()
>>>t3
tensor([[ 0,  4,  8],[ 1,  5,  9],[ 2,  6, 10],[ 3,  7, 11]])
>>>t3.data_ptr() == t2.data_ptr() # 底層數據不是同一個一維數組
False

可以發現 t與t2 底層數據指針一致,t3 與 t2 底層數據指針不一致,說明確實重新開辟了內存空間。

為什么不在view?方法中默認調用contiguous方法?

因為歷史上view方法已經約定了共享底層數據內存,返回的Tensor底層數據不會使用新的內存,如果在view中調用了contiguous方法,則可能在返回Tensor底層數據中使用了新的內存,這樣打破了之前的約定,破壞了對之前的代碼兼容性。為了解決用戶使用便捷性問題,PyTorch在0.4版本以后提供了reshape方法,實現了類似于?tensor.contigous().view(*args)的功能,如果不關心底層數據是否使用了新的內存,則使用reshape方法更方便。?[3]

2.?出于性能考慮

連續的Tensor,語義上相鄰的元素,在內存中也是連續的,訪問相鄰元素是矩陣運算中經常用到的操作,語義和內存順序的一致性是緩存友好的(What is a “cache-friendly” code?[4]),在內存中連續的數據可以(但不一定)被高速緩存預取,以提升CPU獲取操作數據的速度。transpose、permute 后使用?contiguous?方法則會重新開辟一塊內存空間保證數據是在邏輯順序和內存中是一致的,連續內存布局減少了CPU對對內存的請求次數(訪問內存比訪問寄存器慢100倍[5]),相當于空間換時間。

https://www.zydui.com/af781UG8CDQ9VB1YD.html
>

相关文章:

  • 詳解PyTorch中的contiguous
  • PyTorch中的contiguous解讀
  • Pytorch中contiguous()函數理解
  • ios自定義UITabBar-仿寫掌上英雄聯盟的UITabBar
  • 基于Cocos2d-x的英雄聯盟皮膚選擇菜單
  • lol-登陸英雄聯盟出錯
  • JS中雙層for循環執行順序
  • 關于for循環執行順序
  • 上古卷軸5boss計算機丟失,上古卷軸5常見BUG解決辦法
  • 上古世紀服務器維護真情禮,4月9日例行維護懷舊服合服公告
  • 塔羅牌張數
  • 工程管理中的工程技術
  • 銳派出品:LOL新年特輯S4各類細節之下路篇
  • 藍城兄弟Q4業績背后,垂直社區具備多少想象力?
  • Mac OS啟動服務優化高級篇(launchd tuning)
  • #Geek Point# 為什么現在要去印度看一看?
  • vm 流程運行mac os_什么是“商務”流程,為什么在我的Mac上運行?
  • # 陌生人社交產品:需求、困境與破局之道
  • mac 不受信任在哪里更改_什么是受信任的,為什么它可以在Mac上運行?
  • 車行軌跡分類實踐
  • 智慧車行預約小程序 v9.1
  • i12藍牙耳機充電倉怎么看充滿電_車行藍牙耳機價格高性價比的選擇
  • 車行平安
  • 論文閱讀——《基于卷積神經網絡的車行環境多類障礙物檢測與識別》
  • 飛槳開發者創意薈:PaddleHub一鍵部署,AI創意實現原來如此簡單
  • eclipse左側欄目即包資源管理器怎么打開
  • 卷毛機器人符文_卷毛S6娜美輔助天賦 娜美輔助符文天賦S6最新
  • 天賦介紹
  • 蘋果怎么沒有4g信號還無服務器,不顯示4g信號怎么回事?蘋果手機不顯示4g信號的解決方法...
  • c4D體積生成和Quad Remesher重新拓撲減面插件