使用IPython在服务器上打断点(交互式编程)

写在前面

自从本地的显卡已经不能满足模型的计算需求过后,小弟我就只能在服务器上训练自己的模型,但是其debug实在是令人头大,由于无法像在本地一样打断点,我只能笨笨的print参数的维度来查看自己是否写错,或者运行一波再查看报错信息,这是在是太拉了。我也尝试过在本地使用服务器的显卡运行代码,这样可以打断点,但是由于其内存占用太高,导致非常卡顿,debug的效果也不理想。所以最近有时间就来寻找一些亲民的debug方法。目前已找到一个,日后会持续更新。

IPython

本次介绍的方法就是使用IPython这个库,在服务器上可以模拟本地的断点,关于IPython的介绍可以点击这里

如何使用

环境配置

很简单,只需要在我们的环境中pip一下这个库就可以啦。

pip install IPython

用法(本地)

话不多说,直接上代码:

from IPython import embed

if __name__ == '__main__':
    a = [1,2,3,4]
    b = [2,2,2]
    embed()
    print("运行不到这里哦")

简单解说一下,使用这个IPython进行交互编程只需要两步:

  • 在开头from IPython import embed导入embed这个包
  • 在你需要打断点的地方写上一行embed()
    只需要以上两步,程序运行到embed()所在位置时就会自动暂停,且将之前程序中所有的变量全部保存在缓存中,我们变可以在控制台进行交互查看变量的属性。如下图所示。
    在这里插入图片描述
    可以看到,程序运行到embed()所在位置就暂停了,后面的print没有被运行,我们可以查看所有变量的数值、维度等信息。但是我认为最强的一点是你可以使用这些变量的数值来尝试一些写法,看看是否达到了自己预期的结果,简单来说就是可以快速试错,而不用每次都尝试一种写法,重新运行遍程序了,美滋滋好吧。
    在这里插入图片描述
    那么如何退出这个交互命令行呢,只需要输入exit()即可,然后程序便会自动继续运行下面的程序。
    在这里插入图片描述
    自此,我们就可以在程序所有需要断点的地方先提前写上embed(),查看完变量后,exit()退出,运行到下一个embed()的位置,就完成了模拟断点的操作啦。现将代码改为如下所示:
from IPython import embed

if __name__ == '__main__':
    a = [1,2,3,4]
    embed()
    a = [1,1,1]
    b = [2,2,2]
    embed()
    print("运行不到这里哦")

运行的结果如下所示:
在这里插入图片描述
可以看到,程序首先在第一个embed()的位置停止,查看完变量后,输入exit()退出,运行到下一个断点,再次查看完变量后,输入exit()退出,程序运行完成,是不是无敌爽。

用法(服务器)

看完了如何在本地运行,接下来小弟使用pytorch框架写了一个XLNet放到服务器上,看看在调用服务器GPU的时候能否使用embed()来愉快的进行断点。
代码如下:

import torch
from transformers import AutoModel, AutoTokenizer
import numpy as np
from IPython import embed

tokenizer = AutoTokenizer.from_pretrained("./chinese-xlnet-mid")
xlnet = AutoModel.from_pretrained("./chinese-xlnet-mid")

USE_CUDA = torch.cuda.is_available()
device = torch.device("cuda:" + str(0) if USE_CUDA else "cpu")

xlnet = xlnet.to(device)

if __name__ == '__main__':
    '''
	XLNet的demo
    '''
    sequence_a = "我叫龙城狂少。"
    sequence_b = "你叫灭世宇皇吗?"
    sequence_c = "快放假了好开心,我要玩两个月!"
    embed()

    padded_sequences = tokenizer([sequence_a, sequence_b, sequence_c], padding=True)
    print(padded_sequences["input_ids"])
    print(padded_sequences["attention_mask"])


    length_list = [str(item).count("1") for item in padded_sequences["attention_mask"]] # 获取1的个数,即不padding的句子长度
    input_ids = torch.tensor(padded_sequences["input_ids"]).to(device)
    attention_mask = torch.tensor(padded_sequences["attention_mask"]).to(device)
    sentence_vector = xlnet(input_ids, attention_mask)
    sentence_vector_rep = sentence_vector[0].cpu().detach().numpy().tolist()
    sentence_vector_rep = [temp[-1] for temp in sentence_vector_rep] # 直接取CLS作为句子向量表示
    embed()
    # sentence_vector_rep:(1, 3, 768)
    sentence_vector_rep = torch.tensor(sentence_vector_rep).unsqueeze(0)
    print("sentence_vector_rep.shape:", sentence_vector_rep.shape)

运行过程如下:
在这里插入图片描述
在这里插入图片描述
可以看到,在服务器上调用GPU的时候依旧可以使用embed()来进行断点,查看变量,通过显示GPU占用可以观察到在断点的过程中程序确实是暂停的。
注意到上图的In [2]中我直接使用了torch.tensor,这是因为embed()还会同时把代码中import的包也同时放入缓存中,实在是猛的很。

写在后面

听说大佬们写代码都是一把写完直接运行成功的,所以不需要这么麻烦的什么断点啥的,不过对于我这种菜鸟还是老老实实,保证代码不出错吧。
提高代码能力才是重中之重!

猜你喜欢

转载自blog.csdn.net/qq_42068614/article/details/122826524