算力適配開發(fā)教程(20):完整項目——異構(gòu)算力 MD 平臺:適配層、調(diào)度器、基準(zhǔn)流水線三位一體)
分子模擬異構(gòu)算力適配開發(fā)教程20完整項目——異構(gòu)算力 MD 平臺適配層、調(diào)度器、基準(zhǔn)流水線三位一體版本聲明塊工具/軟件本系列全部組件適配層 18 篇、調(diào)度器 17 篇、流水線 12 篇、對賬器 19 篇底座 K8sVolcano/HAMi14/15 篇或 SlurmApptainer16 篇語言/環(huán)境Python 3.10、Linux本文目標(biāo)讀完你擁有一個可落地的平臺藍(lán)圖——分層架構(gòu)、目錄骨架、核心代碼組裝、可觀測性設(shè)計與部署決策能把本系列任意單篇的產(chǎn)出接入對應(yīng)層一句話結(jié)論異構(gòu) MD 平臺 四層總裝——底座層K8sVolcano/HAMi 或 SlurmApptainer管設(shè)備與作業(yè)組、適配層18 篇探測/協(xié)商/注入/執(zhí)行/歸一、調(diào)度層17 篇槽位回收/補位/aging 的 continuous batching 內(nèi)核、運維層12 篇基準(zhǔn)檔案 19 篇對賬巡檢 Prometheus 指標(biāo)——用戶只見統(tǒng)一的 MDJobSpec 提交接口異構(gòu)性引擎×硬件×精度×調(diào)度器全部被中間兩層吸收。〇、本篇要解決的認(rèn)知問題平臺的完整分層是什么每層對應(yīng)本系列哪幾篇的產(chǎn)出三大組件適配層/調(diào)度器/流水線怎么組裝——接口與數(shù)據(jù)流可觀測性指標(biāo)/檔案/巡檢怎么設(shè)計成平臺的“體檢系統(tǒng)”部署形態(tài)怎么選K8s 原生 / Slurm 旁掛 / 單機起步一、機制解析1.1 平臺分層19 篇知識的歸位圖為什么這一節(jié)對你重要總裝不是把 19 篇代碼堆一起——每篇的產(chǎn)出有它的層放錯層比如把引擎協(xié)商塞進 K8s 調(diào)度器、或把槽位管理下沉到 gmx 命令行會造成職責(zé)糾纏這是平臺工程最常見的返工源。┌────────────────────────────────────────────────────────────┐ │ 用戶接口層 mdctl submit / REST API / Web │ │ 統(tǒng)一作業(yè)描述 MDJobSpec18 篇 │ ├────────────────────────────────────────────────────────────┤ │ 調(diào)度層 MDScheduler17 篇槽位回收/補位/aging │ │ 平臺隊列策略優(yōu)先級/配額的 app 層版本 │ ├────────────────────────────────────────────────────────────┤ │ 適配層 Adapter 族18 篇探測/協(xié)商/注入/執(zhí)行/歸一 │ │ GromacsAdapter / OpenMMAdapter / ... │ ├────────────────────────────────────────────────────────────┤ │ 底座層 K8s Volcano/HAMi14/15 篇 │ │ 或 Slurm GRES Apptainer16 篇 │ │ 設(shè)備分配、可見性注入、gang/配額 │ └────────────────────────────────────────────────────────────┘ 旁路系統(tǒng)貫穿四層 基準(zhǔn)流水線12 篇 perf-archive.json→ 性能檔案庫 對賬巡檢19 篇 reconcile→ 數(shù)值健康 診斷體系19 篇分類學(xué)→ 故障定位各層職責(zé)的一句話邊界底座管“有什么資源、怎么隔離”適配層管“這個作業(yè)具體怎么跑”調(diào)度層管“什么時候、在哪個槽位跑”用戶層管“用戶說什么語言”。旁路系統(tǒng)不屬于任何層——它們消費所有層的輸出。1.2 數(shù)據(jù)流一次作業(yè)的一生① 用戶提交 MDJobSpec(kindtpr, precisionmixed, priority5) ② 調(diào)度層入隊有效優(yōu)先級 5 等待×aging——17 篇 ③ 槽位空閑 → 取出作業(yè) → 交給適配層 ④ 適配層探測緩存的能力矩陣gmx 三要素 OpenMM 平臺表——18 篇 → 協(xié)商形態(tài)/精度/偏好過濾→ 選定 GromacsAdapter ⑤ 環(huán)境注入build_envdevice → CUDA_VISIBLE_DEVICES——18 篇 → 執(zhí)行g(shù)mx mdrun 全家桶 -cpi 斷點語義——3/16 篇 ⑥ 運行中底座的健康流device plugin Unhealthy——14 篇異常 → 調(diào)度層標(biāo)記、回收、換槽位續(xù)跑17 篇 checkpoint ⑦ 完成JobResultns/day、環(huán)境快照、軌跡路徑 → 歸一化入檔perf-ledger.csv 追加——16 篇 ⑧ 夜間巡檢抽體系跑三方對賬19 篇→ 數(shù)值健康分兩個設(shè)計決策值得點名能力矩陣帶緩存探測有成本——gmx --version 是進程調(diào)用、OpenMM 枚舉要 import緩存 TTL 手動刷新按鈕健康流是旁掛的調(diào)度器不主動輪詢設(shè)備訂閱底座的事件——掉卡秒級感知的 K8s 版是 ListAndWatchSlurm 版是作業(yè)自檢段的退出碼。1.3 可觀測性平臺的體檢系統(tǒng)三個維度、三套數(shù)據(jù)、一個消費口維度數(shù)據(jù)源存儲消費性能md.log 六指標(biāo)12 篇流水線perf-archive.json / ledger.csv趨勢圖、瓶頸定位19 篇、鐵律 9 實測依據(jù)數(shù)值對賬巡檢19 篇巡檢報告版本升級的回歸門禁運行作業(yè)狀態(tài)、槽位利用率、隊列深度Prometheus 指標(biāo)告警、容量規(guī)劃Prometheus 指標(biāo)命名平臺側(cè)約定Prom 命名慣例namespace_subsystem_namemdplatform_jobs_total{engine,backend,precision,state} # 計數(shù)作業(yè)按維度 mdplatform_slots{device_type} # gauge槽位在用/空閑 mdplatform_job_ns_per_day{engine,backend,system} # histogram性能分布 mdplatform_reconcile_pass_ratio{pair} # gauge對賬通過率 mdplatform_queue_wait_seconds{priority_class} # histogram排隊延遲SLA設(shè)計要點指標(biāo)標(biāo)簽維度對齊能力矩陣engine/backend/precision——性能問題定位時能下鉆到“是不是 MUSA 后端的作業(yè)普遍慢”對賬通過率進指標(biāo)——數(shù)值健康從“某天有人發(fā)現(xiàn)”變成“儀表盤紅綠燈”。1.4 部署形態(tài)三種起步形態(tài) A單機旁掛最快起步——適配層 調(diào)度器跑在一臺 GPU 服務(wù)器cron 或 systemd無 K8s/Slurm 依賴。適合課題組級幾人到十幾人、幾張卡。本篇骨架代碼就是這個形態(tài)的直接可用版。形態(tài) BSlurm 旁掛HPC 存量——平臺調(diào)度器翻譯作業(yè)為 sbatch 腳本16 篇模板GRES/可見性交給 Slurm平臺只管隊列策略與適配層。適合算力中心已有 Slurm 且不想動底座。形態(tài) CK8s 原生平臺化目標(biāo)——調(diào)度層對接 Volcano Queue/PodGroup15 篇、HAMi 管切分14 篇適配層以 Job/DaemonSet 形態(tài)部署。多租戶、彈性、混載推理MD的目標(biāo)形態(tài)。演進路徑 A→B/C 平滑因為適配層與調(diào)度內(nèi)核在三種形態(tài)里零改動它們不感知底座底座差異被 build_env 與“提交翻譯器”吸收——這是 18 篇分層設(shè)計的回報。二、完整代碼與逐行剖析平臺骨架把 17/18/19 篇組件組裝成可運行的最小平臺——形態(tài) A 直接可用#!/usr/bin/env python3mdplatform.py —— 異構(gòu) MD 平臺最小可用版形態(tài) A單機。 組裝MDScheduler17 Adapter 族與協(xié)商18 檔案與對賬12/19。 運行python mdplatform.py submit jobs.json # 提交一批作業(yè) python mdplatform.py status # 查看隊列/槽位 python mdplatform.py reconcile a b # 對賬兩個作業(yè)的能量 from__future__importannotationsimportjsonimportsysimporttimefrompathlibimportPath# ── 組件復(fù)用本系列產(chǎn)出非重寫──────────────────────────────────# 17 篇調(diào)度內(nèi)核槽位回收/補位/aging# from md_scheduler import MDScheduler, MDJob as SchedJob, State# 18 篇適配層探測/協(xié)商/注入/執(zhí)行# from adapter_layer import (MDJobSpec, probe_gromacs, probe_openmm,# negotiate, GromacsAdapter, OpenMMAdapter)# 19 篇對賬器# from reconcile import load_energies, reconcile_L1, Tolerance# —— 教學(xué)版內(nèi)聯(lián)演示組裝關(guān)系生產(chǎn)用上面 import 連接真實模塊———classPlatform:平臺的組裝點三個組件 一個檔案口。def__init__(self,slots:int2,archive:strplatform-ledger.csv):frommd_schedulerimportMDScheduler self.schedulerMDScheduler(slotsslots,modedemo)# 能力矩陣帶緩存1.2 節(jié)決策探測有成本self._caps_cache:list[dict]|NoneNoneself._caps_ts:float0.0self.archivePath(archive)defcapabilities(self,ttl:float300.0)-list[dict]:能力矩陣TTL 緩存——5 分鐘內(nèi)復(fù)用探測結(jié)果。ifself._caps_cacheisNoneortime.time()-self._caps_tsttl:fromadapter_layerimportprobe_gromacs,probe_openmm self._caps_cache[probe_gromacs(),probe_openmm()]self._caps_tstime.time()returnself._caps_cachedefsubmit_batch(self,specs:list[dict])-dict:批量提交MDJobSpec 字典 → 協(xié)商驗證 → 調(diào)度器隊列。 注意順序先協(xié)商提交時就說不而不是運行時撞墻——18 篇問題 4。fromadapter_layerimportMDJobSpec,negotiatefrommd_schedulerimportMDJob accepted[]forsinspecs:specMDJobSpec(**s)chosennegotiate(spec,self.capabilities())# 提交期協(xié)商accepted.append(MDJob(job_idf{spec.kind}-{int(time.time()*1000)%100000},tprspec.tpror-,nstepsspec.nstepsor10,priorityspec.backend_prefinteractiveand5or0))self.scheduler.jobsaccepted statsself.scheduler.run()# 檔案口12/16 篇結(jié)果追加進 ledger——平臺的記憶withself.archive.open(a)asf:f.write(f{time.strftime(%FT%T)},{json.dumps(stats)}\n)returnstatsdefstatus(self)-dict:隊列/槽位快照1.3 節(jié)指標(biāo)的來源。return{capabilities:self.capabilities(),jobs:[{id:j.job_id,state:j.state.value}forjinself.scheduler.jobs]}defmain()-None:cmdsys.argv[1]iflen(sys.argv)1elsestatusplatPlatform(slots2)ifcmdsubmit:specsjson.loads(Path(sys.argv[2]).read_text(encodingutf-8))print(json.dumps(plat.submit_batch(specs),ensure_asciiFalse,indent2))elifcmdstatus:print(json.dumps(plat.status(),ensure_asciiFalse,indent2))elifcmdreconcile:fromreconcileimportload_energies,reconcile_L1,Tolerance rreconcile_L1(load_energies(Path(sys.argv[2])),load_energies(Path(sys.argv[3])),Tolerance())print(json.dumps(r,ensure_asciiFalse,indent2))else:print(__doc__)if__name____main__:main()配套的作業(yè)描述文件用戶視角的全部復(fù)雜度——這就是“用戶只說什么語言”的答案// jobs.json —— 用戶提交的全部語言一個 JSON 數(shù)組[{kind:tpr,tpr:/data/benchMEM.tpr,nsteps:5000,precision:mixed,backend_pref:gromacs,device:0},{kind:tpr,tpr:/data/ligand-prod.tpr,nsteps:500000,precision:mixed,backend_pref:null,platform_hint:null,device:1}]逐段剖析組裝的本質(zhì)是“連接件”Platform 類沒有重寫任何引擎邏輯——它做的是三件事能力緩存性能決策、提交期協(xié)商體驗決策錯誤早爆、檔案口記憶決策。平臺代碼的價值在連接件不在重復(fù)造輪子——19 篇的組件各就各位。submit_batch的協(xié)商前置第 18 篇問題 4 的落實作業(yè)不合法如 tprdouble 但 gmx 是 mixed 構(gòu)建在提交秒級被拒——帶原因的拒絕比運行三小時后的崩潰好一百倍。status()的輸出結(jié)構(gòu)直接映射 1.3 節(jié)指標(biāo)capabilities 是標(biāo)簽維度來源、jobs 的 state 分布是隊列深度——接 Prometheus exporter 就是把這兩個 dict 變成 gauge/counter 的事。jobs.json 里backend_pref: null自動協(xié)商與顯式gromacs并存——平臺對“懂的用戶”開放控制、對“不懂的用戶”提供默認(rèn)——兩種用戶都被同一層服務(wù)。部署清單形態(tài) C 的 K8s 化要點對照 14/15 篇# 平臺組件的 K8s 形態(tài)示意# md-scheduler → Deployment無狀態(tài)對接 Volcano Queue 的 app 層策略# adapter-worker → Job/DaemonSet有狀態(tài)執(zhí)行走 HAMi vGPU 申請 gpumem# capability-probe → CronJob定期刷新能力矩陣——底座設(shè)備變化的感知# prometheus exporter → 側(cè)車容器消費 status() 輸出# 底座前置Volcano 部署 HAMi 部署 各廠商 device plugin#全部在第 14/15 篇有落地步驟平臺的 K8s 化不改變適配層與調(diào)度內(nèi)核——1.4 節(jié)承諾三、常見報錯與排查問題 1現(xiàn)象——平臺上線后用戶反饋“還是直接 gmx 命令快平臺有開銷”。根因開銷解剖——正常開銷協(xié)商毫秒級、環(huán)境構(gòu)造微秒級可忽略異常開銷三個來源能力探測無緩存每次全量探測18 篇決策未落地調(diào)度器 poll 過密17 篇問題 3作業(yè)排隊時間被計入“平臺慢”其實是槽位不足的容量問題。解法三層分別處理——TTL 緩存本文 capabilitiespoll 調(diào)到秒級容量問題看 queue_wait_seconds 指標(biāo)1.3 節(jié)說話加槽位或錯峰。用指標(biāo)分清“開銷”與“排隊”——多數(shù)抱怨其實是后者。問題 2現(xiàn)象——某引擎升級后平臺作業(yè)全體數(shù)值告警對賬巡檢紅了。根因這是巡檢系統(tǒng)正常工作——引擎升級改變了數(shù)值行為精度路徑/積分器實現(xiàn)變化平臺用 19 篇的對賬把它攔在了生產(chǎn)之前。解法按 19 篇層級定性差異合法變化 vs 真 bug——合法則在平臺登記新基線巡檢的黃金值隨版本更新帶版本標(biāo)簽真 bug 則凍結(jié)該引擎版本能力矩陣把它摘掉上游修復(fù)后再放行。巡檢不是擋板的成本是灰度的依據(jù)。問題 3現(xiàn)象——雙底座K8s Slurm 各管一部分節(jié)點時能力矩陣與可見性行為不一致。根因兩底座注入語義差異Slurm 的 job step 環(huán)境 vs K8s 的 Allocate 注入漏過了適配層的統(tǒng)一收口——某處代碼繞過 build_env 直接用了 os.environ。解法架構(gòu)紀(jì)律檢查——適配層外的任何代碼不許構(gòu)造子進程環(huán)境grep 檢查 subprocess 調(diào)用點的 env 參數(shù)能力探測在雙底座節(jié)點各自跑CronJob/旁掛探測按節(jié)點記錄——矩陣的粒度是節(jié)點不是集群。問題 4現(xiàn)象——平臺故障調(diào)度器崩了時在跑的作業(yè)全部丟失。根因把“調(diào)度器存活”與“作業(yè)存活”耦合了——其實 gmx/OpenMM 進程是底座systemd/K8s/Slurm的公民調(diào)度器崩不該帶走它們丟失的是“管理”不是“計算”。解法調(diào)度器崩潰恢復(fù)流程——重啟后掃描作業(yè)產(chǎn)物目錄md.log/deffnm 文件在、按 checkpoint 狀態(tài)重建作業(yè)清單-cpi 語義天然支持、繼續(xù)調(diào)度本文 Platform 的 jobs 狀態(tài)可持久化到 ledger已經(jīng)在做——控制面與數(shù)據(jù)面分離這是 17 篇“調(diào)度內(nèi)核與執(zhí)行后端分離”的運維版。四、動手練習(xí)練習(xí) 1基礎(chǔ)把 17/18 篇的模塊文件md_scheduler.py/adapter_layer.py與本文 mdplatform.py 放同目錄跑python mdplatform.py status看到帶緩存的能力矩陣輸出。判定成功標(biāo)準(zhǔn)status 輸出雙引擎能力或明確的 unavailable二次調(diào)用 status 在 TTL 內(nèi)不再觸發(fā)探測加個 print 在 probe 里驗證緩存生效。練習(xí) 2進階給 Platform 加bench命令——調(diào)第 12 篇流水線對當(dāng)前槽位跑 benchMEM 短程基準(zhǔn)把 ns/day 追加進 ledger 并打印與歷史均值讀 ledger 計算的對比。判定成功標(biāo)準(zhǔn)ledger 里出現(xiàn)新的性能記錄對比輸出含“當(dāng)前/歷史均值/偏差%”三要素偏差超過 30% 時給出 19 篇決策樹的入口提示。練習(xí) 3思考題無標(biāo)準(zhǔn)答案平臺上線一年后能力矩陣膨脹到幾十個條目多引擎版本 × 多硬件 × 多精度協(xié)商變慢、維護變難——該怎么治理思考方向驗證要點① 矩陣的生命周期管理廢棄條目的淘汰機制——性能檔案能否提供依據(jù)② 協(xié)商結(jié)果的緩存與失效策略③ “能力即代碼”capability as config還是“能力即探測”runtime probing的長期取舍。五、系列總結(jié)20 篇收官。回到第 1 篇的三個問題現(xiàn)在的你能這樣回答修改引擎GROMACS 四后端的構(gòu)建2 篇與執(zhí)行控制3 篇、gpu_utils 抽象層5 篇、HIP/SYCL/MUSA 三條移植路線的完整方法論6/7/9 篇——昇騰的特殊性11 篇與“沒有后端”時的決策樹。封裝引擎OpenMM 平臺抽象與插件協(xié)議4/8/10 篇、雙引擎統(tǒng)一適配層18 篇——能力探測、協(xié)商、環(huán)境收口。調(diào)度封裝從 Device Plugin/vGPU14 篇到 Volcano/vNPU15 篇到 Slurm/Apptainer16 篇的底座全景推理調(diào)度思想遷移的 MD 批調(diào)度器17 篇驗證與診斷閉環(huán)12/19 篇最終總裝成平臺20 篇。貫穿全系列的十條鐵律第 0 篇計劃定義在每篇各自主戰(zhàn)場兌現(xiàn)版本先錨定2/13 篇的環(huán)境變量三代史、單后端編譯2 篇、工具邊界6 篇 hipify、昇騰無后端的事實鏈11 篇、GPU-resident 前提3 篇、性能帶上下文12 篇、雙精度慎用2 篇、移植必須過驗證12 篇、切分必須實測14/17 篇、封裝不改物理18/19 篇。下一步去哪把第 9 篇的 SCS 容器跑起來用第 12 篇流水線給你的硬件建檔第 18 篇的適配層接入你手頭的引擎——平臺從第一個真實作業(yè)開始生長。本篇認(rèn)知問題回顯FAQQ1異構(gòu) MD 平臺的完整分層是什么A四層——用戶接口層統(tǒng)一 MDJobSpec 提交、調(diào)度層continuous batching 內(nèi)核槽位回收/補位/aging、適配層能力探測/后端協(xié)商/環(huán)境注入/執(zhí)行/結(jié)果歸一、底座層K8sVolcano/HAMi 或 SlurmGRESApptainer管設(shè)備分配與可見性旁路系統(tǒng)基準(zhǔn)檔案、對賬巡檢、診斷體系貫穿四層——每層職責(zé)一句話底座管資源隔離、適配層管作業(yè)怎么跑、調(diào)度層管何時何槽位、用戶層管語言。Q2平臺的三大組件怎么組裝A連接件模式不重復(fù)造輪子Platform 類做三件事——能力矩陣 TTL 緩存探測有成本、提交期協(xié)商前置作業(yè)不合法秒級拒絕而非運行數(shù)小時后崩潰、檔案口結(jié)果追加 ledger 形成平臺記憶調(diào)度器崩不影響在跑作業(yè)控制面與數(shù)據(jù)面分離重啟后按 checkpoint 產(chǎn)物重建清單續(xù)調(diào)。Q3MD 平臺需要哪些可觀測性指標(biāo)A三維度對齊能力矩陣標(biāo)簽engine/backend/precision性能維度mdplatform_job_ns_per_day histogram、六指標(biāo)來自 12 篇流水線、數(shù)值維度mdplatform_reconcile_pass_ratio 對賬通過率——版本升級的回歸門禁、運行維度jobs_total 計數(shù)、slots gauge、queue_wait_seconds 排隊延遲 SLA——性能定位能下鉆到“某后端是否普遍慢”數(shù)值健康從人工發(fā)現(xiàn)變成儀表盤紅綠燈。Q4平臺部署形態(tài)怎么選A三種起步——單機旁掛適配層調(diào)度器 systemd 跑一臺 GPU 服務(wù)器課題組級最快可用、Slurm 旁掛翻譯作業(yè)為 sbatchGRES 交給 SlurmHPC 存量友好、K8s 原生對接 Volcano Queue/HAMi vGPU多租戶彈性目標(biāo)形態(tài)演進平滑的關(guān)鍵是適配層與調(diào)度內(nèi)核對底座零感知底座差異被環(huán)境注入與提交翻譯器吸收。