今天,我们宣布 PyTorch 1.7 的可用性,以及领域库的更新。PyTorch 1.7 版本包括许多新 API,包括对 NumPy 兼容的 FFT 操作的支持、性能分析工具以及分布式数据并行(DDP)和基于远程过程调用(RPC)的分布式训练的重大更新。此外,一些功能已移至稳定版,包括自定义 C++类、内存分析器、通过自定义张量对象扩展、RPC 中的用户异步函数以及在 torch.distributed 中的许多其他功能,如 Per-RPC 超时、DDP 动态桶分配和 RRef 辅助器。
一些亮点包括:
- CUDA 11 现已正式支持,可在 PyTorch.org 获取二进制文件
- 对 RPC、TorchScript 和 autograd 分析器中的堆栈跟踪的性能分析进行了更新和补充
- (Beta) 支持通过 torch.fft 实现与 NumPy 兼容的快速傅里叶变换 (FFT)
- (原型) 支持 Nvidia A100 代 GPU 和原生 TF32 格式
- (原型) 现已支持 Windows 上的分布式训练
- torchvision
- (稳定版) 转换现在支持张量输入、批量计算、GPU 和 TorchScript
- (稳定) 本地图像 I/O 支持 JPEG 和 PNG 格式
- (测试版) 新的视频读取 API
- torchaudio
- (稳定) 添加了对语音识别(wav2letter)、语音合成(WaveRNN)和源分离(ConvTasNet)的支持
再次强调,从 PyTorch 1.6 版本开始,功能被分为稳定版、测试版和原型版。您可以在以下链接中查看详细公告。请注意,本博客中列出的原型功能作为本版本的一部分提供。
在此处查找完整的发布说明。
前端 API
[Beta] 兼容 NumPy 的 torch.fft 模块
FFT 相关功能在信号处理等众多科学领域中被广泛使用。虽然 PyTorch 历史上支持了一些 FFT 相关函数,但 1.7 版本新增了一个 torch.fft 模块,该模块实现了与 NumPy 相同的 API 的 FFT 相关函数。
此新模块必须导入到 1.7 版本中使用,因为其名称与历史(现已弃用)的 torch.fft 函数冲突。
示例用法:
>>> import torch.fft
>>> t = torch.arange(4)
>>> t
tensor([0, 1, 2, 3])
>>> torch.fft.fft(t)
tensor([ 6.+0.j, -2.+2.j, -2.+0.j, -2.-2.j])
>>> t = tensor([0.+1.j, 2.+3.j, 4.+5.j, 6.+7.j])
>>> torch.fft.fft(t)
tensor([12.+16.j, -8.+0.j, -4.-4.j, 0.-8.j])
[Beta] Transformer NN 模块的 C++支持
自 PyTorch 1.5 以来,我们一直保持 Python 和 C++前端 API 之间的兼容性。此更新允许开发者从 C++前端使用 nn.transformer 模块抽象。而且,开发者不再需要从 Python/JIT 保存模块到 C++中,因为它现在可以直接在 C++中使用。
[Beta] torch.set_deterministic
可重现性(位对位确定性)有助于在调试或测试程序时识别错误。为了便于实现可重现性,PyTorch 1.7 添加了 torch.set_deterministic(bool)
函数,该函数可以指导 PyTorch 运算符在可用时选择确定性算法,并在操作可能导致非确定性行为时抛出运行时错误。默认情况下,此函数控制的标志为 false,行为没有变化,这意味着 PyTorch 默认可能以非确定性方式实现其操作。
更精确地说,当此标志为 true 时:
- 已知没有确定性实现的操作会抛出运行时错误;
- 具有确定性变体的操作使用这些变体(通常与非确定性版本相比有性能损失);并且
-
torch.backends.cudnn.deterministic = True
已设置。
注意,这对于 PyTorch 程序的单次运行中的确定性是必要的,但并不充分。其他随机性来源,如随机数生成器、未知操作或异步或分布式计算,仍可能导致非确定性行为。
请参阅 torch.set_deterministic(bool)
的文档,以获取受影响操作的列表。
性能与性能分析
[Beta] 添加了堆栈跟踪到性能分析器
用户现在不仅可以在性能分析器输出表中看到操作符名称/输入,还可以看到操作符在代码中的位置。此工作流程只需进行很少的更改即可利用此功能。用户仍然使用自动微分性能分析器,但可以添加可选的新参数: with_stack
和 group_by_stack_n
。注意:常规性能分析运行不应使用此功能,因为它会增加显著的开销。
分布式训练 & RPC
[稳定版] TorchElastic 现已集成到 PyTorch Docker 镜像中
Torchelastic 提供了当前 torch.distributed.launch
CLI 的严格超集,并增加了容错性和弹性功能。如果用户对容错性不感兴趣,可以通过设置 max_restarts=0
来获得与 torch.distributed.launch
完全相同的功能/行为一致性,同时增加了自动分配 RANK
和 MASTER_ADDR|PORT
的便利性(而不是在 torch.distributed.launch)
中手动指定)。
通过将 torchelastic
集成到与 PyTorch 相同的 Docker 镜像中,用户可以立即开始使用 TorchElastic 进行实验,无需单独安装 torchelastic
。除了便利性之外,这项工作在为现有的 Kubeflow 分布式 PyTorch 运算符添加弹性参数支持时也是一个很好的补充。
[Beta] 支持在 DDP 中处理不均匀数据集输入
PyTorch 1.7 引入了一个新的上下文管理器,可与使用 torch.nn.parallel.DistributedDataParallel
训练的模型结合使用,以实现不同进程间不同数据集大小的训练。此功能在使用 DDP 时提供了更大的灵活性,并防止用户手动确保不同进程间的数据集大小相同。使用此上下文管理器,DDP 将自动处理不均匀的数据集大小,这可以防止训练结束时出现错误或挂起。
[Beta] NCCL 可靠性 - 异步错误/超时处理
在过去,由于集体操作卡住,NCCL 的训练运行可能会无限期挂起,给用户带来非常不愉快的体验。此功能将在检测到潜在挂起时终止卡住的集体操作并抛出异常/崩溃进程。当与 torchelastic(可以从最后一个检查点恢复训练过程)一起使用时,用户可以拥有更高的分布式训练可靠性。此功能完全为可选,并位于需要显式设置的环境外部变量之后,以启用此功能(否则用户将看到与之前相同的行为)。
[Beta] TorchScript rpc_remote
和 rpc_sync
在之前的版本中, torch.distributed.rpc.rpc_async
已支持 TorchScript。对于 PyTorch 1.7,此功能将扩展到剩余的两个核心 RPC API, torch.distributed.rpc.rpc_sync
和 torch.distributed.rpc.remote
。这将完成针对 TorchScript 支持的 RPC API 的主要目标,允许用户在 TorchScript 中(在脚本函数或脚本方法中,这释放了 Python 全局解释器锁)使用现有的 Python RPC API,并可能在多线程环境中提高应用程序性能。
[Beta] 支持 TorchScript 的分布式优化器
PyTorch 为训练算法提供了一组广泛的优化器,这些优化器已被反复用作 Python API 的一部分。然而,用户通常希望使用多线程训练而不是多进程训练,因为在大规模分布式训练(例如分布式模型并行)或任何基于 RPC 的训练应用程序的上下文中,这提供了更好的资源利用率和效率。由于需要摆脱 Python 全局解释器锁(GIL)的限制,用户之前无法使用分布式优化器。
在 PyTorch 1.7 中,我们启用了分布式优化器对 TorchScript 的支持,以移除全局解释器锁(GIL),并使优化器能够在多线程应用程序中运行。新的分布式优化器与之前的接口完全相同,但它会自动将每个工作进程中的优化器转换为 TorchScript,以实现每个 GIL 免费。这是通过利用功能优化器概念并允许分布式优化器将优化器的计算部分转换为 TorchScript 来实现的。这将有助于分布式模型并行训练等用例,并利用多线程提高性能。
目前,唯一支持与 TorchScript 自动转换的优化器是 Adagrad
,而所有其他优化器仍将像以前一样工作,不提供 TorchScript 支持。我们正在努力将覆盖范围扩展到所有 PyTorch 优化器,并期待未来版本中会有更多内容。启用 TorchScript 支持的使用方法与现有的 Python API 完全相同,以下是如何使用此功能的示例:
import torch.distributed.autograd as dist_autograd
import torch.distributed.rpc as rpc
from torch import optim
from torch.distributed.optim import DistributedOptimizer
with dist_autograd.context() as context_id:
# Forward pass.
rref1 = rpc.remote("worker1", torch.add, args=(torch.ones(2), 3))
rref2 = rpc.remote("worker1", torch.add, args=(torch.ones(2), 1))
loss = rref1.to_here() + rref2.to_here()
# Backward pass.
dist_autograd.backward(context_id, [loss.sum()])
# Optimizer, pass in optim.Adagrad, DistributedOptimizer will
# automatically convert/compile it to TorchScript (GIL-free)
dist_optim = DistributedOptimizer(
optim.Adagrad,
[rref1, rref2],
lr=0.05,
)
dist_optim.step(context_id)
[Beta] 基于 RPC 的性能分析增强
PyTorch 1.6 首次引入了与 RPC 框架结合使用 PyTorch profiler 的支持。在 PyTorch 1.7 中,进行了以下增强:
- 实现了对通过 RPC 分析 TorchScript 函数的更好支持
- 在与 RPC 一起工作的 profiler 功能方面实现了对等性
- 在服务器端添加了对异步 RPC 函数的支持(使用
rpc.functions.async_execution)
装饰的函数)
用户现在可以使用熟悉的配置文件工具,如 torch.autograd.profiler.profile()
和 with torch.autograd.profiler.record_function
,并且这可以与 RPC 框架透明地工作,提供完整功能支持,配置异步函数和 TorchScript 函数。
[原型] 支持分布式训练的 Windows
PyTorch 1.7 在 Windows 平台上支持 DistributedDataParallel
原型和集体通信。在这个版本中,支持仅涵盖基于 Gloo 的 ProcessGroup
和 FileStore
。
要在多台机器上使用此功能,请提供来自共享文件系统的文件 init_process_group
。
# initialize the process group
dist.init_process_group(
"gloo",
# multi-machine example:
# init_method = "file://////{machine}/{share_folder}/file"
init_method="file:///{your local file path}",
rank=rank,
world_size=world_size
)
model = DistributedDataParallel(local_model, device_ids=[rank])
移动
PyTorch Mobile 支持 iOS 和 Android,分别通过 Cocoapods 和 JCenter 提供二进制包。您可以在此处了解更多关于 PyTorch Mobile 的信息。
[Beta] PyTorch Mobile 缓存分配器,用于性能提升
在某些移动平台,如 Pixel 上,我们观察到内存更积极地返回给系统。这导致频繁的页面错误,因为 PyTorch 作为一个功能框架不维护操作符的状态。因此,对于大多数操作,输出在每次执行操作时动态分配。为了减轻由此产生的性能惩罚,PyTorch 1.7 为 CPU 提供了一个简单的缓存分配器。该分配器通过张量大小缓存分配,目前仅通过 PyTorch C++ API 提供。缓存分配器本身由客户端拥有,因此分配器的生命周期也由客户端代码维护。然后可以使用作用域保护器 c10::WithCPUCachingAllocatorGuard
,在该作用域内使用缓存的分配。示例用法:
#include <c10/mobile/CPUCachingAllocator.h>
.....
c10::CPUCachingAllocator caching_allocator;
// Owned by client code. Can be a member of some client class so as to tie the
// the lifetime of caching allocator to that of the class.
.....
{
c10::optional<c10::WithCPUCachingAllocatorGuard> caching_allocator_guard;
if (FLAGS_use_caching_allocator) {
caching_allocator_guard.emplace(&caching_allocator);
}
....
model.forward(..);
}
...
注意:缓存分配器仅在移动构建中可用,因此在外部移动构建中使用缓存分配器将不会有效。
torchvision
[稳定版] 转换现在支持 Tensor 输入、批处理计算、GPU 和 TorchScript
torchvision 转换现在继承自 nn.Module
,并且可以用于 torch Tensor 输入以及 PIL 图像。它们还支持具有批维度的 Tensors,并在 CPU/GPU 设备上无缝工作:
import torch
import torchvision.transforms as T
# to fix random seed, use torch.manual_seed
# instead of random.seed
torch.manual_seed(12)
transforms = torch.nn.Sequential(
T.RandomCrop(224),
T.RandomHorizontalFlip(p=0.3),
T.ConvertImageDtype(torch.float),
T.Normalize([0.485, 0.456, 0.406], [0.229, 0.224, 0.225])
)
scripted_transforms = torch.jit.script(transforms)
# Note: we can similarly use T.Compose to define transforms
# transforms = T.Compose([...]) and
# scripted_transforms = torch.jit.script(torch.nn.Sequential(*transforms.transforms))
tensor_image = torch.randint(0, 256, size=(3, 256, 256), dtype=torch.uint8)
# works directly on Tensors
out_image1 = transforms(tensor_image)
# on the GPU
out_image1_cuda = transforms(tensor_image.cuda())
# with batches
batched_image = torch.randint(0, 256, size=(4, 3, 256, 256), dtype=torch.uint8)
out_image_batched = transforms(batched_image)
# and has torchscript support
out_image2 = scripted_transforms(tensor_image)
这些改进使得以下新功能成为可能:
- 支持 GPU 加速
- 批量转换,例如视频所需的转换
- 转换多波段 torch 张量图像(具有 3-4 个以上通道)
- 将 torchscript 转换与您的模型一起部署,注意:TorchScript 支持的异常包括
Compose
、RandomChoice
、RandomOrder
、Lambda
以及应用于 PIL 图像的转换,如ToPILImage
。
[稳定] 原生 JPEG 和 PNG 图像 IO
torchvision 0.8.0 版本引入了对 JPEG 和 PNG 格式的原生图像读取和写入操作。这些操作支持 TorchScript,并返回 uint8
格式的 CxHxW
张量,因此现在可以成为您模型的一部分,以便在 C++环境中部署。
from torchvision.io import read_image
# tensor_image is a CxHxW uint8 Tensor
tensor_image = read_image('path_to_image.jpeg')
# or equivalently
from torchvision.io import read_file, decode_image
# raw_data is a 1d uint8 Tensor with the raw bytes
raw_data = read_file('path_to_image.jpeg')
tensor_image = decode_image(raw_data)
# all operators are torchscriptable and can be
# serialized together with your model torchscript code
scripted_read_image = torch.jit.script(read_image)
[稳定] RetinaNet 检测模型
本版本增加了基于 Focal Loss 的密集目标检测的 ResNet50 骨干网络的 RetinaNet 预训练模型。
[Beta] 新视频读取 API
本版本引入了新的视频读取抽象,提供了对视频迭代更细粒度的控制。它支持图像和音频,并实现了迭代器接口,以便与其他 Python 库(如 itertools)互操作。
from torchvision.io import VideoReader
# stream indicates if reading from audio or video
reader = VideoReader('path_to_video.mp4', stream='video')
# can change the stream after construction
# via reader.set_current_stream
# to read all frames in a video starting at 2 seconds
for frame in reader.seek(2):
# frame is a dict with "data" and "pts" metadata
print(frame["data"], frame["pts"])
# because reader is an iterator you can combine it with
# itertools
from itertools import takewhile, islice
# read 10 frames starting from 2 seconds
for frame in islice(reader.seek(2), 10):
pass
# or to return all frames between 2 and 5 seconds
for frame in takewhile(lambda x: x["pts"] < 5, reader):
pass
注意事项:
- 为了使用视频读取 API 测试版,您必须从源代码编译 torchvision,并在您的系统中安装 ffmpeg。
- The VideoReader API is currently released as beta and its API may change following user feedback.
torchaudio
With this release, torchaudio is expanding its support for models and end-to-end applications, adding a wav2letter training pipeline and end-to-end text-to-speech and source separation pipelines. Please file an issue on github to provide feedback on them.
[Stable] Speech Recognition
Building on the addition of the wav2letter model for speech recognition in the last release, we’ve now added an example wav2letter training pipeline with the LibriSpeech dataset.
[稳定] 文本转语音
为了支持文本转语音应用,我们添加了一个基于 WaveRNN 模型的声码器,该模型基于此存储库的实现。原始实现是在“高效神经音频合成”中引入的。我们还提供了一个使用 LibriTTS 数据集进行 WaveRNN 训练的示例流程,该数据集已添加到 torchaudio 的本次发布中。
[稳定] 源分离
通过添加基于论文“Conv-TasNet:超越理想时频幅度掩蔽的语音分离”的 ConvTasNet 模型,torchaudio 现在也支持源分离。提供了一个使用 wsj-mix 数据集的 ConvTasNet 训练示例流程。
喝彩!
PyTorch 团队