评价此页

Meta device#

创建时间:2025 年 6 月 17 日 | 最后更新时间:2025 年 6 月 17 日

“meta” 设备是一个抽象设备,它表示一个只记录元数据而不实际记录数据的张量。Meta 张量有两个主要用例:

  • 模型可以加载到 meta 设备上,这样你就可以加载模型的表示,而无需将实际参数加载到内存中。如果你需要在加载实际数据之前对模型进行转换,这会很有帮助。

  • 大多数操作都可以在 meta 张量上执行,产生新的 meta 张量,描述如果在真实张量上执行该操作会得到什么结果。你可以利用这一点进行抽象分析,而无需花费时间和空间来表示实际的张量。由于 meta 张量没有真实数据,因此你无法执行依赖于数据的操作,例如 torch.nonzero()item()。在某些情况下,并非所有设备类型(例如 CPU 和 CUDA)对某个操作的输出元数据都完全相同;在这种情况下,我们通常倾向于忠实地表示 CUDA 的行为。

警告

虽然理论上 meta 张量计算应该总是比等效的 CPU/CUDA 计算更快,但许多 meta 张量实现是用 Python 编写的,尚未移植到 C++ 以提高速度,因此你可能会发现使用小型 CPU 张量会获得更低的绝对框架延迟。

使用 meta 张量的惯用法#

可以通过指定 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,))

如果你有一些任意代码在没有明确指定设备的情况下执行某些张量构造,你可以使用 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 张量直接转换为 CPU/CUDA 张量,因为 meta 张量不存储任何数据,我们也不知道新张量的正确数据值是什么。

>>> 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 包含一些未文档化的实用程序,用于将任意张量转换为具有高保真度的等效 meta 张量。这些 API 是实验性的,可能会随时以向后不兼容的方式进行更改。