jittor与pytorch的区别一览

前言

最近在完成一个利用Jittor复现GaussianSplatting的项目,里面用到了清华大学自主开发的深度学习框架jittor,因为GaussianSplatting官方代码是基于Pytorch和CUDA,所以复现过程中遇到了许许多多的问题,这里记录一下,希望能对读者有所帮助

jittor安装问题

经过测试发现,在1.3.7.3往后的jittor版本,在Linxu系统上安装通过不了CUDA测试,里面生成的变量都有问题,无法正确计算data属性,推荐安装版本1.3.6.5, 1.3.7.3,另外jittor安装CUDA版本一般都需要你安装配套的CUDNN

jittor梯度求法

jittor和torch生成的变量var与tensor相比,有个比较重要的区别就是jittor.var没有grad属性,grad只能通过创建优化器,然后对优化器参数求jt.opt_grad,并且jittor无法实现对非叶子节点的梯度保留

jittor的C++和CUDA扩展

相对于Pytorch来说,jittor主要为python环境设计,没有提供类似于Pytorch的C++和CUDA扩展,这导致无法复用GaussianSplatting的CUDA光栅化器,最后采用的解决方法是利用python和jittor手写一个光栅化器

jittor.meshgrid

jittor.meshgrid默认的indexing是ij,而torch.meshgrid默认的indexing是xy

jittor中的no_grad

与pytorch不同的是 jittor中no_grad方法里的梯度无法重新设置梯度,因为jittor不存在设置require_grad的方法,所以一定要注意不要把你需要计算梯度的参量,比如优化器参量放入道no_grad函数里,jittor不支持像pytorch那样的nn.paremeter()函数来将张量设置为可优化的,有梯度的

jittor优化器的状态参数

与pytorch优化器不同的是 pytorch优化器的状态参数都存在优化器.stact属性中。jittor不存在这个属性,但jittor的param_groups属性储存了优化器参数,每个优化器参数里面又存有其对应的状态参数,如果你想修改优化器状态参数,请采用param_groups获取优化器参数,并修改其中的状态参数部分即可

CUDA占用参数空间过多

因为 jittor 通过 jt.flags.use_cuda 设置是否使用 GPU,所有的 jt.Var 根据此开关自动使用 cpu 或者 gpu 计算,不需要关心 var 所在的设备。这导致很多参数全部都是无脑的放在CUDA设备上,对显卡资源丰富的人来说,这显然不是个问题,但如果你的卡的显存有限,且模型较大,这会使你很容易就显存爆炸或参数空间溢出

如果你的显存空间爆炸,推荐你可以尝试在定义并使用完函数的局部变量后,及时将其del删除,然后利用jt.gc()函数回收参数空间

jittor调试技巧

因为jittor默认是异步执行的,这可以大大加快其运算速度,但这在调试时非常难以准确定位错误发生位置,推荐关闭延迟执行,可以在环境变量中将export lazy_execution=0 或者在python代码中jt.flags.lazy_execution=0

jittor模型的保存和加载

与pytorch不同的是 jittor.save函数只支持dict方式保存参数,而且目前经过测试发现其对pth,pt格式的文件的保存读取会报错,建议使用pkl文件格式

总结

以上是本人在编写jittor项目是遇到的一些比较大的Bug,也有一些比较小的问题没有一一列举,因为jittor和pytorch大部分函数和属性还是比较相似的,一些比较简单的问题,可以直接问chatGPT就可以解决,这里只记录了一些我认为比较重要或比较难发现的区别,如果你在复现jittor时,遇到了一些问题,你可以参考我的GitHub仓库里转换好的模型JGaussian