電梯系列 多進程強力自動評測機
背景
- 電梯輸入需要發射器,手動評測難以復現
- 增量開發時需要迴歸測試
- 電梯進程等待時間較多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上跑,可惜目前筆者不會