# Python与C程序异常结束

#### 定位思路

Python与C/C++混编的进程未按设计要求进行执行，出现异常结束的情况。

1. 编写可以复现问题的测试脚本。
2. 打印作业失败的日志。
3. 根据日志定位源码位置，并根据源码分析报错原因。
4. 修改相关代码，重新编译进行验证。
5. 若问题解决，则确认修改，合入原代码。


#### 案例：新线程无法启动导致主进程异常结束

问题现象：

在某集群环境中，客户反馈使用华为Donau Scheduler调度器提交大批量Python分析作业时，其中40%+作业会失败。

定位过程：

1. 编写测试脚本，复现客户问题。
  编写测试脚本mol_map_label_dsub_vs1_chain_pa_hzl.sh并执行。

  1 2 cd exp/cryonet2/ exp/label_data/mol_map_label_dsub_vs1_chain_pa_hzl.sh ~/data/chains8_testhzl/1.list >ID_1000.list

  运行成功600个作业，成功率60%，运行结果通过如下命令写入到djob-s-all-1000.log文件中。

  1 djob -st "2021/12/11 10:44:52" -et "2021/12/11 10:55:00" -s all -n default > djob-s-all-1000.log

  查看运行结果：

  1 cat djob-s-all-1000.log | grep SUCCEEDED | wc -l

  查看提交任务ID：

  1 cat ID_1000.list | grep submit | wc –l

2. 执行脚本，查看失败日志。
3. 定位到OpenBLAS无法创建新线程问题，通过如下命令查看，最终用了10816个进程/线程。
  1 ps -ef -T |grep sync360 | grep mid | wc -l

  查阅文档并结合代码分析，发现OpenBLAS是高度优化的线性代数库，可以通过多线程的方式来加速计算，默认启动的线程数和当前运行的物理核数一致。

  当前计算节点是2 cpu* 52core=104，单条任务会开启104的线程任务。

  而此时提交任务dsub使用了-R cpu=1只申请了1个计算核，导致会有104的任务分配到同一个计算节点。因此OpenBlAS会创建104*104=10816个线程，超过Linux线程的资源限制。

  默认设置为： ulimit -a core file size (blocks, -c) 0 data seg size (kbytes, -d) unlimited scheduling priority (-e) 0 file size (blocks, -f) unlimited pending signals (-i) 511844 max locked memory (kbytes, -l) 64 max memory size (kbytes, -m) unlimited open files (-n) 1024 pipe size (512 bytes, -p) 8 POSIX message queues (bytes, -q) 819200 real-time priority (-r) 0 stack size (kbytes, -s) 8192 cpu time (seconds, -t) unlimited max user processes (-u) 4096 virtual memory (kbytes, -v) unlimited file locks (-x) unlimited Linux普通用户默认配置，默认最多线程数为4096。

4. 运行时添加OMP_NUM_THREADS=1命令限制每次作业的blas线程数和申请的CPU核数匹配，修改后40000+批量作业无失败情况。

```
OMP_NUM_THREADS=1 python tools.py -f label_mol_map_atom1437 -p 2c7c_B -o data/chains7/2c7c_B.npz --res 4 --voxel_size 1.0
```
