Meta 裝置¶
「meta」裝置是一種抽象裝置,表示僅記錄中繼資料但不記錄實際資料的 tensor。 Meta tensor 有兩個主要用例
模型可以載入到 meta 裝置上,讓您載入模型的表示形式,而無需將實際參數載入記憶體中。 如果您需要在載入實際資料之前對模型進行轉換,這會很有用。
大多數操作都可以在 meta tensor 上執行,產生新的 meta tensor,描述如果您在實際 tensor 上執行操作會產生的結果。 您可以使用它來執行抽象分析,而無需花費時間在計算或空間上來表示實際的 tensor。 由於 meta tensor 沒有實際資料,因此您無法執行資料相關的操作,例如
torch.nonzero()
或item()
。 在某些情況下,並非所有裝置類型(例如,CPU 和 CUDA)對操作都有完全相同的輸出中繼資料; 在這種情況下,我們通常更喜歡忠實地表示 CUDA 行為。
警告
雖然原則上 meta tensor 的運算應該總是比等效的 CPU/CUDA 運算更快,但許多 meta tensor 的實作是用 Python 撰寫的,且尚未移植到 C++ 以提高速度,因此您可能會發現對於較小的 CPU tensors,使用 CPU tensors 時反而會獲得較低的絕對框架延遲。
使用 meta tensors 的慣用方法¶
可以透過指定 map_location='meta'
,使用 torch.load()
將物件載入到 meta 裝置上
>>> torch.save(torch.randn(2), 'foo.pt')
>>> torch.load('foo.pt', map_location='meta')
tensor(..., device='meta', size=(2,))
如果您有一些任意的程式碼執行了一些 tensor 構建,而沒有明確指定裝置,您可以使用 torch.device()
上下文管理器來覆寫它,使其改為在 meta 裝置上構建
>>> with torch.device('meta'):
... print(torch.randn(30, 30))
...
tensor(..., device='meta', size=(30, 30))
這在 NN 模組構建中特別有用,在這種情況下,您通常無法明確地傳入裝置來進行初始化
>>> from torch.nn.modules import Linear
>>> with torch.device('meta'):
... print(Linear(20, 30))
...
Linear(in_features=20, out_features=30, bias=True)
您不能直接將 meta tensor 轉換為 CPU/CUDA tensor,因為 meta tensor 不儲存任何資料,且我們不知道新 tensor 的正確資料值是什麼
>>> torch.ones(5, device='meta').to("cpu")
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
NotImplementedError: Cannot copy out of meta tensor; no data!
使用像 torch.empty_like()
這樣的工廠函數來明確指定您希望如何填入遺失的資料。
NN 模組有一個方便的方法 torch.nn.Module.to_empty()
,允許您將模組移動到另一個裝置,並使所有參數保持未初始化狀態。您需要手動重新初始化參數
>>> from torch.nn.modules import Linear
>>> with torch.device('meta'):
... m = Linear(20, 30)
>>> m.to_empty(device="cpu")
Linear(in_features=20, out_features=30, bias=True)
torch._subclasses.meta_utils
包含未記錄的實用程式,用於取得任意 Tensor 並構建一個具有高保真度的等效 meta Tensor。這些 API 是實驗性的,並且可能會隨時以不向後相容的方式更改。