|高性能PyTorch是如何炼成的?过来人吐血整理的10条避坑指南( 二 )


根据你的方案 , 你可以将每个文件的二进制内容保持不变 , 并在 RAM 中进行即时解码 , 或者对未压缩的图像进行讲解码 , 并保留原始像素 。 但是无论你采用什么方法 , 这里有第二条建议:
建议 2:解析、度量、比较 。 每次你在管道中提出任何改变 , 要深入地评估它全面的影响 。
假设你对模型、超参数和数据集等没做任何改动 , 这条建议只关注训练速度 。 你可以设置一个魔术命令行参数(魔术开关) , 在指定该参数时 , 训练会在一些合理的数据样例上运行 。 利用这个特点 , 你可以迅速解析管道 。
# Profile CPU bottleneckspython -m cProfile training_script.py --profiling
# Profile GPU bottlenecksnvprof --print-gpu-trace python train_mnist.py
# Profile system calls bottlenecksstrace -fcT python training_script.py -e trace=open,close,read
Advice 3: *Preprocess everything offline*
建议 3:离线预处理所有内容
如果你要训练由多张 2048x2048 图像制成的 512x512 尺寸图像 , 请事先调整 。 如果你使用灰度图像作为模型的输入 , 请离线调整颜色 。 如果你正在进行自然语言处理(NLP) , 请事先做分词处理(tokenization) , 并存入磁盘 。 在训练期间一次次重复相同的操作没有意义 。 在进行渐进式学习时 , 你可以以多种分辨率保存训练数据的 , 这还是比线上调至目标分辨率更快 。
对于表格数据 , 请考虑在创建 Dataset 时将 pd.DataFrame 目标转换为 PyTorch 张量 。
建议 4:调整 DataLoader 的工作程序
PyTorch 使用一个 DataLoader 类来简化用于训练模型的批处理过程 。 为了加快速度 , 它可以使用 Python 中的多进程并行执行 。 大多数情况下 , 它可以直接使用 。 还有几点需要记住:
每个进程生成一批数据 , 这些批通过互斥锁同步可用于主进程 。 如果你有 N 个工作程序 , 那么你的脚本将需要 N 倍的 RAM 才能在系统内存中存储这些批次的数据 。 具体需要多少 RAM 呢?
我们来计算一下:
假设我们为 Cityscapes 训练图像分割模型 , 其批处理大小为 32 , RGB 图像大小是 512x512x3(高、宽、通道) 。 我们在 CPU 端进行图像标准化(稍后我将会解释为什么这一点比较重要) 。 在这种情况下 , 我们最终的图像 tensor 将会是 512 * 512 * 3 * sizeof(float32) = 3,145,728 字节 。 与批处理大小相乘 , 结果是 100,663,296 字节 , 大约 100Mb;
除了图像之外 , 我们还需要提供 ground-truth 掩膜 。 它们各自的大小为(默认情况下 , 掩膜的类型是 long , 8 个字节)——512 * 512 * 1 * 8 * 32 = 67,108,864 或者大约 67Mb;
因此一批数据所需要的总内存是 167Mb 。 假设有 8 个工作程序 , 内存的总需求量将是 167 Mb * 8 = 1,336 Mb 。
听起来没有很糟糕 , 对吗?当你的硬件设置能够容纳提供 8 个以上的工作程序提供的更多批处理时 , 就会出现问题 。 或许可以天真地放置 64 个工作程序 , 但是这将消耗至少近 11Gb 的 RAM 。
当你的数据是 3D 立体扫描时 , 情况会更糟糕 。 在这种情况下 , 512x512x512 单通道 volume 就会占 134Mb , 批处理大小为 32 时 , 8 个工作程序将占 4.2Gb , 仅仅是在内存中保存中间数据 , 你就需要 32Gb 的 RAM 。
对于这个问题 , 有个能解决部分问题的方案——你可以尽可能地减少输入数据的通道深度:
将 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])


推荐阅读