用昆仑芯XPU训练模型的常用技巧

查看XPU占用

想要查看XPU的占用率与显存情况,可以用xpu-smi

类似于N卡的nvidia-smi,这个指令能够显示XPU的占用情况,输出结果例如:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
+---------------------------------------------------------------------------------------+
| XPU-SMI Driver Version: 5.0.21.21 XPU-RT Version: 5.0.21 |
|-------------------------------+-----------------------+-------------------------------|
| XPU Name Persistence-M| Bus-Id Disp.A | Volatile Uncorr. ECC |
| Fan Temp Perf Pwr:Usage/Cap| Memory-Usage | XPU-Util Compute M. |
| | L3-Usage | SR-IOV M. |
|===============================+=======================+===============================|
| 0 P800 OAM N/A | 00000000:A3:00.0 N/A | 0 |
| N/A 46C N/A 117W / 400W| 47250MiB / 98304MiB | 1% Default |
| | 4MiB / 96MiB | Disabled |
+-------------------------------+-----------------------+-------------------------------+

+---------------------------------------------------------------------------------------+
| Processes: |
| XPU XI CI PID Type Process name XPU Memory |
| ID ID Usage |
|=======================================================================================|
| 0 N/A N/A 2118 C 21528MiB |
| 0 N/A N/A 3161 C /usr/bin/python 25726MiB |
+---------------------------------------------------------------------------------------+

如果想要终止某个程序,利用kill杀掉对应进程即可

1
2
kill -9 要终止的任务的PID
# 如 kill -9 3161

显存不释放

有的时候,程序明明退出了,且在xpu-smi中也看不到对应进程,但是显存依然被占用,不能被自动释放。此时需要利用lsof指令找到所有占用XPU的进程,再手动全部终止。

在终端中输入:

1
lsof /dev/xpu*

可以看到哪些应用在占用XPU

1
2
3
4
5
6
COMMAND  PID   USER   FD    TYPE  DEVICE  SIZE/OFF  NODE  NAME
python 2801 bml mem CHR 195, 255 943 /dev/xpuctrl
python 2801 bml mem CHR 195, 6 1724 /dev/xpu6
python 2801 bml 3u CHR 195, 255 0t0 943 /dev/xpuctrl
python 2801 bml 4u CHR 195, 6 0t0 1724 /dev/xpu6
......

其中COMMAND下的为程序名,一般用kill终止掉其中所有python后就能释放显存。

在确认本机无其他人用XPU的情况下也可以用

1
lsof -t /dev/xpu* | sargs -r kill -9

终止所有占用XPU的应用。

Dataloader报错

在训练过程中可能遇到Dataloader环节报错,比如

1
2
3
4
5
6
7
8
9
10
11
12
13
Traceback (most recent call last):
File "xxx/PaddleYOLO-example/tools/train.py", line 202, in <module>
main()
File "xxx/PaddleYOLO-example/tools/train.py", line 198, in main
run(FLAGS, cfg)
File "xxx/PaddleYOLO-example/tools/train.py", line 151, in run
trainer.train(FLAGS.eval)
File "xxx/PaddleYOLO-example/ppdet/engine/trainer.py", line 496, in train
for step_id, data in enumerate(self.loader):
File "/usr/local/lib/python3.10/dist-packages/paddle/io/dataloader/dataloader_iter.py", line 850, in __next__
self._reader.read_next_list()[0]
SystemError: (Fatal) Blocking queue is killed because the data reader raises an exception.
[Hint: Expected killed_ != true, but received killed_:1 == true:1.] (at /host/Paddle/paddle/phi/core/operators/reader/blocking_queue.h:175)

可能的原因有三种,一是worker_num太高导致内存不足,适当调低即可。训练时可以用另一个终端,执行watch top来监控系统内存占用情况。

二是kill掉训练进程时,Dataloader进程没被一起结束掉,此时可以用lsof来查询所有Dataloader并kill掉

1
lsof +D 数据集所在目录

三是输入图片的尺寸太大。此时需要对数据集进行预处理,缩小图像尺寸并修改对应的标注。

查看训练程序是哪个用户执行的

一台机器多人公用时,要避免总结掉别人执行的程序,可以用xpi-smi查看程序对应的路径。但是有些时候xpi-smi只显示python,此时可以用ls查看该进程详细情况。

1
2
# XXXX改为对应程序的PID
ll /proc/XXXX | grep 'cwd\|exe'

得到的输出中,cwd最后面为执行程序时所在的路径,exe最后面为程序的路径。根据这些信息即可判断训练程序是哪个用户执行的。

1
2
lrwxrwxrwx  1 xxx xxx  0  4月 22 17:46 cwd -> xxx/sample
lrwxrwxrwx 1 xxx xxx 0 4月 22 17:01 exe -> xxx/miniconda3/envs/pcp/bin/python3.10