[OO] 电梯系列 多进程强力自动评测机
电梯系列 多进程强力自动评测机
背景
- 电梯输入需要发射器,手动评测难以复现
- 增量开发时需要回归测试
- 电梯进程等待时间较多CPU利用率低
- 常规的开多个评测机的加速方案难以控制
- 增加挑战性,在学会Java多线程的同时学会Python多进程
- 实际测试第三次作业同时评测8个人4000个测试点,耗时13小时
组成部分
- DataMaker按照一定规则产生新数据
- RunJava调用Java程序产生output
- SpecialJudge根据output按照一定规则判断正确性及出错原因放到本地log
- 可以看到组成部分如右图,评测后只需要查看log目录
强力性——高并发
- 显然一个一个case一个一个人评测速度太慢了,开发时回归测试也将跟不上开发的速度
- 注意到Python的多个进程能够被调度到多个CPU上
- 考虑将每个 (case, name) 的Pair映射到一个进程中
- 每个进程工作目录独立,用后清除
- 两种模式:
- 广泛撒网
- 精准打击
运行结果示例
广泛撒网模式
精准打击模式
具体实现细节
时间控制
-
time.sleep()控制投放时间
-
-
将系统时间与Java程序时间进行同步,排除评测机自身运行时间的影响
-
使用 subprocess.Popen() 控制Java进程及输入投放
-
-
注意最后判断Java是否结束不要做成了轮询
RE与TLE检测
- 经讨论区大佬提醒
- RE可以通过subprocess.poll()获取返回值判断
- TLE可以通过subprocess.communicate(timeout)抛出异常来判断
性能值判定
- 前两次作业只需要统计运行时间即可
- 第三次作业需要在判定正确性的同时统计每个任务的开始时间和结束时间,进而获取性能值(上图的评测结果为第二次作业,第三次作业增加了cost, T1, T2的输出,便于比较性能)
数据生成
-
楼层生成可以直接用MIN到MAX的均匀分布
-
下一个输入的到达时间根据实际应满足指数分布,具有无后效性
-
平均时间间隔为
多进程管理
- 使用multiprocessing.Process包,将自己写的进程类继承自该类
- 需要注意使用multiprocessing.Lock将某些冲突的操作同步
优化空间
- 本地行为与课程组评测机行为有时候差别较大
- 本地????一个,交上去????三个,可能是评测组评测机采用了重复测试的方法
- CPU时间难以准确测定,由zly大佬的研讨课分享提醒,目前可能的解决方案是CPU时间检测部分通过java的内置包java.lang.management 来判断,即所谓的JMX(Java Management Extensions)
- 对评测速度仍然不满意,考虑CUDA编程放在GPU上跑,可惜目前笔者不会