加入收藏 | 设为首页 | 会员中心 | 我要投稿 温州站长网 (https://www.52wenzhou.com/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 创业 > 模式 > 正文

高性能PyTorch是如何炼成的?整理的10条脱坑指南

发布时间:2020-06-23 18:57:24 所属栏目:模式 来源:站长网
导读:副标题#e# 如何用最少的精力,完成最高效的 PyTorch 训练?一位有着 PyTorch 两年使用经历的 Medium 博主最近分享了他在这方面的 10 个真诚建议。 在 Efficient PyTorch 这一部分中,作者提供了一些识别和消除 I/O 和 CPU 瓶颈的技巧。第二部分阐述了一些高

将 RGB 图像保持在每个通道深度 8 位。可以轻松地在 GPU 上将图像转换为浮点形式或者标准化。 在数据集中用 uint8 或 uint16 数据类型代替 long。 class MySegmentationDataset(Dataset):   ...   def __getitem__(self, index):     image = cv2.imread(self.images[index])     target = cv2.imread(self.masks[index])      # No data normalization and type casting here     return torch.from_numpy(image).permute(2,0,1).contiguous(),            torch.from_numpy(target).permute(2,0,1).contiguous()  class Normalize(nn.Module):     # https://github.com/BloodAxe/pytorch-toolbelt/blob/develop/pytorch_toolbelt/modules/normalize.py     def __init__(self, mean, std):         super().__init__()         self.register_buffer("mean", torch.tensor(mean).float().reshape(1, len(mean), 1, 1).contiguous())         self.register_buffer("std", torch.tensor(std).float().reshape(1, len(std), 1, 1).reciprocal().contiguous())      def forward(self, input: torch.Tensor) -> torch.Tensor:         return (input.to(self.mean.type) - self.mean) * self.std  class MySegmentationModel(nn.Module):   def __init__(self):     self.normalize = Normalize([0.221 * 255], [0.242 * 255])     self.loss = nn.CrossEntropyLoss()    def forward(self, image, target):     image = self.normalize(image)     output = self.backbone(image)      if target is not None:       loss = self.loss(output, target.long())       return loss      return output 

通过这样做,会大大减少 RAM 的需求。对于上面的示例。用于高效存储数据表示的内存使用量将为每批 33Mb,而之前是 167Mb,减少为原来的五分之一。当然,这需要模型中添加额外的步骤来标准化数据或将数据转换为合适的数据类型。但是,张量越小,CPU 到 GPU 的传输就越快。

DataLoader 的工作程序的数量应该谨慎选择。你应该查看你的 CPU 和 IO 系统有多快,你有多少内存,GPU 处理数据有多快。

多 GPU 训练 & 推理神经网络模型变得越来越大。今天,使用多个 GPU 来增加训练时间已成为一种趋势。幸运的是,它经常会提升模型性能来达到更大的批处理量。PyTorch 仅用几行代码就可以拥有运行多 GPU 的所有功能。但是,乍一看,有些注意事项并不明显。

model = nn.DataParallel(model) # Runs model on all available GPUs 

运行多 GPU 最简单的方法就是将模型封装在 nn.DataParallel 类中。除非你要训练图像分割模型(或任何生成大型张量作为输出的其他模型),否则大多数情况下效果不错。在正向推导结束时,nn.DataParallel 将收集主 GPU 上所有的 GPU 输出,来通过输出反向运行,并完成梯度更新。

于是,现在就有两个问题:

GPU 负载不平衡; 在主 GPU 上聚合需要额外的视频内存

首先,只有主 GPU 能进行损耗计算、反向推导和渐变步骤,其他 GPU 则会在 60 摄氏度以下冷却,等待下一组数据。

其次,在主 GPU 上聚合所有输出所需的额外内存通常会促使你减小批处理的大小。nn.DataParallel 将批处理均匀地分配到多个 GPU。假设你有 4 个 GPU,批处理总大小为 32;然后,每个 GPU 将获得包含 8 个样本的块。但问题是,尽管所有的主 GPU 都可以轻松地将这些批处理放入对应的 VRAM 中,但主 GPU 必须分配额外的空间来容纳 32 个批处理大小,以用于其他卡的输出。

对于这种不均衡的 GPU 使用率,有两种解决方案:

(编辑:温州站长网)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

推荐文章
    热点阅读