高性能PyTorch是如何炼成的?整理的10条脱坑指南
https://medium.com/huggingface/training-larger-batches-practical-tips-on-1-gpu-multi-gpu-distributed-setups-ec88c3e51255 https://medium.com/@theaccelerators/learn-pytorch-multi-gpu-properly-3eb976c030ee https://towardsdatascience.com/how-to-scale-training-on-multiple-gpus-dae1041f49d2 建议 5: 如果你拥有两个及以上的 GPU 能节省多少时间很大程度上取决于你的方案,我观察到,在 4x1080Ti 上训练图像分类 pipeline 时,大概可以节约 20% 的时间。另外值得一提的是,你也可以用 nn.DataParallel 和 nn.DistributedDataParallel 来进行推断。 关于自定义损失函数 编写自定义损失函数是一项很有趣的练习,我建议大家都不时尝试一下。提到这种逻辑复杂的损失函数,你要牢记一件事:它们都在 CUDA 上运行,你应该会写「CUDA-efficient」代码。「CUDA-efficient」意味着「没有 Python 控制流」。在 CPU 和 GPU 之间来回切换,访问 GPU 张量的个别值也可以完成这些工作,但是性能表现会很差。 前段时间,我实现了一个自定义余弦嵌入损失函数,是从《Segmenting and tracking cell instances with cosine embeddings and recurrent hourglass networks》这篇论文中来的,从文本形式上看它非常简单,但实现起来却有些复杂。 我编写的第一个简单实现的时候,(除了 bug 之外)花了几分钟来计算单个批的损失值。为了分析 CUDA 瓶颈,PyTorch 提供了一个非常方便的内置分析器,非常简单好用,提供了解决代码瓶颈的所有信息: def test_loss_profiling(): loss = nn.BCEWithLogitsLoss() with torch.autograd.profiler.profile(use_cuda=True) as prof: input = torch.randn((8, 1, 128, 128)).cuda() input.requires_grad = True target = torch.randint(1, (8, 1, 128, 128)).cuda().float() for i in range(10): l = loss(input, target) l.backward() print(prof.key_averages().table(sort_by="self_cpu_time_total")) 建议 9: 如果设计自定义模块和损失——配置并测试他们 在对最初的实现进行性能分析之后,就能够提速 100 倍。关于在 PyTorch 中编写高效张量表达式的更多信息,将在 Efficient PyTorch — Part 2 进行说明。 时间 VS 金钱 最后但非常重要的一点,有时候投资功能更强大的硬件,比优化代码可能更有价值。软件优化始终是结果无法确定的高风险之旅,升级 CPU、RAM、GPU 或者同时升级以上硬件可能会更有效果。金钱和时间都是资源,二者的均衡利用是成功的关键。 通过硬件升级可以更轻松地解决某些瓶颈。 写在最后 懂得充分利用日常工具是提高熟练度的关键,尽量不要制造「捷径」,如果遇到不清楚的地方,请深入挖掘,总有机会发现新知识。正所谓「每日一省」:问问自己,我的代码还能改进吗?这种精益求精的信念和其他技能一样,都是计算机工程师之路的必备品。 原文链接:https://towardsdatascience.com/efficient-pytorch-part-1-fe40ed5db76c 【本文是51CTO专栏机构“机器之心”的原创译文,微信公众号“机器之心( id: almosthuman2014)”】 (编辑:晋中站长网) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |