整理一些PyTorch,CUDA,OpenGL相关的性能调优trick。
绝不是什么专家,但或许我的workflow可以帮你解决纠结了很久的bug。
之所以整理这个blog,是因为其中记录的几乎所有内容都无法直接在网上、在GPT口中简单搜索得到。即使能有相关信息,也是鱼龙混杂,让人看了眼花缭乱,正儿八经的guide都很少。
我是做计算机视觉的体积视频方向的,工作中会涉及到实时渲染相关内容,但同时又得用python和pytorch(也并不会c++),因此喜欢搞点写起来容易,但性能也不输c++的操作。
一些本blog中会提到的资源和工具:
PyTorch官方的performance tuning guide: https://pytorch.org/tutorials/recipes/recipes/tuning_guide.html
PyTorch和CUDA的相爱相杀关系: https://pytorch.org/docs/master/notes/cuda.html
Python上的CUDA Runtime和NVIDIA Driver接口: https://developer.nvidia.com/cuda-python
Python上的OpenGL接口: https://github.com/mcfletch/pyopengl
PyTorch官方的提供的profiler(有时候比cuda的profiler都好用): https://pytorch.org/blog/introducing-pytorch-profiler-the-new-and-improved-performance-tool/ https://pytorch.org/tutorials/recipes/recipes/profiler_recipe.html
NVIDIA的Nsight Systems和Nsight Graphics(目测只有Windows版本): https://docs.nvidia.com/nsight-systems/UserGuide/index.html https://developer.nvidia.com/nsight-graphics https://developer.nvidia.com/nsight-systems
RenderDoc,无需多言,检查frame和graphics api调用的(Window,WSL2,Ubuntu都能用,MacOS好像也可以用): https://renderdoc.org/
Chrome,浏览器,但是Chrome那帮人也是优化高手,因此他们做了工具来可视化tracing: PyTorch Profiler生成的tracing文件可以用 chrome://tracing 印象里FireFox和Edge也有类似的工具,FireFox的似乎能更好看,但兼容性不太好 https://www.chromium.org/developers/how-tos/trace-event-profiling-tool/ https://profiler.firefox.com/
在读blog之前,我们需要先同步一些事情。
Python代码速度不快,这一点在很多PyTorch应用和codebase中也存在。如果所有指令都线性执行,我们的deep learning work load可能会慢到无法想象。所幸,CPU和GPU的物理分离性导致这两者上可以同时跑代码,PyTorch的大部分CUDA Kenel都是异步运行的,这意味着提交好GPU任务后,CPU上仍然可以运行程序。一个例子是,我们希望计算一张图片中所有像素值的mean,我们执行了 img.mean()
这条指令,那么PyTorch的后端就会启动一个对应的cuda kernel来进行上面的计算。此时如果我想做一些CPU操作,例如打印一句话print('Hello, world.')
这段CPU代码会立刻被执行,即使 img.mean()
还没有被执行完。
当你在测试这一点时,需要注意很多Python的解释器会将你敲击回车前最后一条指令的返回值打印到屏幕上,此时 img.mean()
就不再是异步执行的了,因为你的CPU需要拿到这条指令的结果才会知道要将什么屏幕打印到屏幕上。
要验证PyTorch的异步CUDA Kernel调用相对于使用它要麻烦的多,你需要首先理解Stream的概念。
对于此,最好的文档就是PyTorch官方的documentation: