第一跑 —— 一個(gè)帶腳注的「能」)
系列g(shù)dev-masterNVIDIA/nouveau 用戶(hù)態(tài) GPGPU 運(yùn)行時(shí)從 C/C 到 Rust 的移植工程形狀不是性質(zhì)收在「綠照到的是哪部分」這個(gè)問(wèn)題上還留了一條本機(jī)證否不了的口子libdrm 的版本落差只能上機(jī)當(dāng)天量。這一篇就是那一天的實(shí)錄走完——答案是一個(gè)帶腳注的「能」。先把結(jié)論釘在桌上每個(gè)數(shù)都給口徑數(shù)值口徑真機(jī) gate6/6 用例 stdoutstderrrc 逐字節(jié)一致比對(duì)副本剔除 6 行已登記基線(xiàn)插樁后§三用例構(gòu)成見(jiàn) §四真算力覆蓋首跑 3/6 → 當(dāng)晚補(bǔ)跑后 5/6上 GPU 真算并回拷的用例數(shù)§四、§五倉(cāng)庫(kù)448 個(gè) commit138 個(gè).rs/ 90,636 行g(shù)it rev-list --count HEADfind rust/gdev-rs -name *.rs -not -path */target/*行數(shù)同條加 -exec cat {} 單測(cè)938 全綠cargo test --workspace --lib09-23 體檢真跑的讀數(shù)不是沿用值一、上機(jī)前的最后兩步出「.so 可交」的結(jié)論之前還有兩步收尾都記在案門(mén)-48 整單收口 最終見(jiàn)證48 鍵 93 條判據(jù)全部落地對(duì)賬 69 48 回填 21 顯式不回填出門(mén)清單從干凈 HEAD 重編六步全綠雙庫(kù) sha256 凍結(jié)在 MANIFEST最后做了一次「最終見(jiàn)證 PASS」——48 鍵當(dāng)日全量重掃36 分鐘嚴(yán)格判據(jù) S1…S7 全過(guò)。結(jié)論開(kāi)發(fā)機(jī)段驗(yàn)證完盡.so可交。發(fā)起檢查第一輪查出四類(lèi)真問(wèn)題——最重的一條是49 個(gè)提交未推送本地唯一副本覆蓋門(mén)-48 全程第二輪換方法深查不采信聲明、直接量原始狀態(tài)cargo test真跑 938 全綠、雙庫(kù) sha 字節(jié)級(jí)與 MANIFEST 一致、證偽注入 9/9。順帶把方法論復(fù)盤(pán)如實(shí)入檔第一輪為什么沒(méi)看出來(lái)——看見(jiàn)了信息、沒(méi)看見(jiàn)問(wèn)題檢查做成了「驗(yàn)證聲明」而不是「找未聲明的洞」。49 個(gè)提交當(dāng)天推上遠(yuǎn)端。二、首查目標(biāo)機(jī)是 oceanProxmox上的 Fedora 18 VMGTX 580 直通。第一件事不是跑是查——按單分四批每批只做「讀取證 登記」批次查到什么首查內(nèi)核 ?uname -r3.6.10-4.gdev.fc18.x86_64gdev 內(nèi)核在跑設(shè)備 ?C 基線(xiàn) ?——卡點(diǎn)全在環(huán)境側(cè)批次二GPU 直通 ?nouveau.ko在盤(pán)上、只是從未modprobe批次三modprobe后card0在C 基線(xiàn)定案其構(gòu)建腳本userON/uschedOFF與本工程移植裁定逐項(xiàng)吻合批次四三個(gè)測(cè)試二進(jìn)制與開(kāi)發(fā)機(jī)同源 ?推送段至此打通產(chǎn)物上機(jī)C 基線(xiàn)指紋記下當(dāng)時(shí)口徑 N2 條。三、首跑 5/6gate 首跑?六個(gè)用例里 5 處不一致。沒(méi)慌按逐文件對(duì)讀——.out/.err/.rc兩側(cè)全部取回stderr、退出碼六個(gè)用例兩側(cè)全同數(shù)值memcpy 的14, 17逐字同差異全部且僅是C 側(cè)比 Rust 多兩行調(diào)試打印func:gdev_raw_dev_open line:227、1guyanqing gdev_launch。這兩行是誰(shuí)的三路核實(shí)一路一命令核哪路結(jié)果上游 C 源樹(shù) grep 這兩行零命中目標(biāo)機(jī)上兩份 C 庫(kù)strings命中測(cè)試二進(jìn)制零命中? 目標(biāo)機(jī)的 C 基線(xiàn) 上游 C 調(diào)試 printf。Rust ≡ 上游 C不一致的是「尺子被人加過(guò)字」。這里三條鐵律同時(shí)到場(chǎng)不改 C它帶插樁也是當(dāng)天的尺子、不改 Rust它沒(méi)錯(cuò)、判據(jù)不許為了讓門(mén)變綠而改——那就只剩一條路把這兩行已登記的基線(xiàn)插樁從比對(duì)副本里剔除字面 行尾錨防誤傷原始輸出一個(gè)字節(jié)不動(dòng)exempt_lines6寫(xiě)進(jìn) GATE-SUMMARY豁免行登記進(jìn) RUNBOOK §7。關(guān)鍵是下一步要求對(duì)豁免規(guī)則本身再來(lái)一遍自測(cè)三過(guò)才上線(xiàn)能消掉 5 處已知差異規(guī)則有效注入一個(gè)真差異14, 17改14, 18——仍然紅規(guī)則沒(méi)把門(mén)弄瞎帶后綴的行不剔行尾錨真的在錨。復(fù)跑6/6 用例 stdoutstderrrc 逐字節(jié)一致。設(shè)備旁證 5/6 成立——用LD_PRELOAD把/dev/dri/*藏起來(lái)輸出必須變不變的那 1 個(gè)是matrixadd無(wú)參輪設(shè)計(jì)上就不碰設(shè)備屬預(yù)期這一天的綠是有信息量的綠。當(dāng)天章照跑--falsifyrc011 注入、各紅各通道、checkrc0首跑觀(guān)測(cè)凍成基線(xiàn)deploy_expected/gate.record。四、綠允許寫(xiě)什么三個(gè)腳注「6/6 逐字節(jié)一致」這句話(huà)能寫(xiě)但它帶腳注。六個(gè)用例其實(shí)折成三疊疊用例綠的含義真算力matrixadd -16、memcpy×2數(shù)值/輸出逐字同3/6錯(cuò)誤路徑等價(jià)madd×2兩側(cè)同敗在cuModuleLoad失敗信息與 rc 逐字同設(shè)計(jì)內(nèi)早退matrixadd 無(wú)參Invalid arguments、rc0兩側(cè)同不碰設(shè)備腳注一覆蓋首跑的真算力是 3/6——madd 兩個(gè)用例兩側(cè)一樣地?cái)≡谀K裝載上。錯(cuò)誤路徑等價(jià)也是等價(jià)但它不叫真算力這一條當(dāng)晚就銷(xiāo)掉了§五5/6。腳注二madd 的Test passed驗(yàn)的是什么madd.c:236的回讀循環(huán)是dummy_c c[idx]——讀了不比。所以 madd 的Test passed證明的是「裝載 → launch → 回拷 → 釋放」這條 API 路徑走得通不證明數(shù)值。它跑的 cubin 還是 3080 機(jī)器上新版 nvcc 編的sm_86這份 SASS 在 Fermi 上此測(cè)試設(shè)計(jì)上看不出能不能真跑——照實(shí)寫(xiě)不裝。腳注三計(jì)時(shí)差異是測(cè)試固有的memcpy 打印的是耗時(shí)不是數(shù)據(jù)微秒數(shù)每跑必不同byte-exact 要?dú)w一化設(shè)計(jì)當(dāng)日未立登記在案目標(biāo)機(jī)沒(méi)有 strace序列通道本次未覆蓋——同樣寫(xiě)明。五、oracle 被換sha 對(duì)撞逮住的一天當(dāng)晚先銷(xiāo)遺留。madd 裝載失敗的根因坐實(shí)main.c:13傳的是path.madd.c:97從 cwd 拼./madd_gpu.cubin而 gate 在倉(cāng)庫(kù)根跑 ? 永遠(yuǎn)找不到。修法很樸素用例從自己的目錄跑——deploy.sh、device_probe 三處、本地 gate.sh三處一致不一致的話(huà)藏設(shè)備那一輪 cwd 不同會(huì)造出「假設(shè)備旁證」。真機(jī)補(bǔ)跑madd 兩輪兩側(cè)Test passed、rc0全 API 鏈走通Exec 耗時(shí)非零C 0.584ms / Rust 0.084ms。真算力 3/6 →5/6。順手把 C 基線(xiàn)指紋從 2 條補(bǔ)滿(mǎn)到 6 條4 條 sha 2 條 LINK 拓?fù)湫懈惶幍怯浤繕?biāo)機(jī)build/{lib,cuda}是軟鏈、指入build/release同 inode——一套構(gòu)建兩條路徑原先登記的「兩套并存」機(jī)制說(shuō)錯(cuò)了判讀僥幸未受影響更正也是斷言復(fù)量過(guò)才落筆。然后是這一天真正值得記的事。補(bǔ)跑輪 gate 判紅mismatch9逐文件歸因無(wú)一處是 Rust 跑偏計(jì)時(shí)打印 6 處madd / memcpy 用例固有的計(jì)時(shí)行腳注三Opened/Closed3 處。后三處把一個(gè)事實(shí)釘死了gdev_platform.h:65的用戶(hù)態(tài)GDEV_PRINT就是無(wú)條件fprintf(stderr, …)沒(méi)有任何編譯條件受GDEV_DEBUG_PRINT控制的是GDEV_DPRINT? Rust 側(cè)的打印p1/api.rs:883是忠實(shí)的缺打印的是 C 那邊。而 C 那邊為什么缺基線(xiàn)當(dāng)天被人換了。push 時(shí) sha 對(duì)撞01:30 還在的bc86bec1…15:03 變成了307bb011…exempt_lines6→0舊的調(diào)試 printf 沒(méi)了但上游無(wú)條件打印也不打了 ? 這是一份第三種源狀態(tài)既非上游原物也非首跑那份。這件事的兩層教訓(xùn)比當(dāng)天任何一行代碼都值錢(qián)指紋只護(hù) push→gate 這個(gè)窗口??鐣?huì)話(huà)換基線(xiàn)指紋管不著——管著的是 GATE-SUMMARY 里sha_lib_c的對(duì)撞本輪就是這么逮住的不是理論。「C 是 oracle」第一次反過(guò)來(lái)咬oracle 不是天上掉的是人在目標(biāo)機(jī)上編出來(lái)的人會(huì)重編。尺子自己會(huì)變所以量尺子的動(dòng)作指紋、對(duì)撞必須是流程的一部分而不是當(dāng)天的儀式。操作面同日兩筆也入檔cloudflared「一次連接即僵」用ControlMaster復(fù)用一條活連接撐過(guò) push/gate 連發(fā)pkill -f匹配到自己命令行把 shell 殺了兩次——?dú)?啟分開(kāi)調(diào)用 中括號(hào)技巧。產(chǎn)物方面gate 結(jié)果目錄收攏進(jìn)~/gdev-rust-gate/時(shí)間戳/并修掉 do_fetch 的一個(gè)空串假綠——門(mén)-11 同族。六、遺留與下線(xiàn)目標(biāo)機(jī)下線(xiàn)sshNo route to host宿主機(jī)上qm start報(bào)PCI 0000:01:00.0 already in use by VMID 106——GTX 580 被 VM 106 占著106 不是本方的 VM。留下去的賬都在 STATUS 待辦區(qū)登記oracle 源狀態(tài)對(duì)齊待環(huán)境負(fù)責(zé)人要么恢復(fù)上游原物 ? 豁免歸零、純逐字節(jié)綠要么明確「以此版為準(zhǔn)」? 3 行進(jìn)豁免表。在那之前gate 判紅恒為那 3 處.err裁決那兩行[gdev] Opened/Closed字面進(jìn)豁免同款字面加行尾錨模式自測(cè)三過(guò)后才上線(xiàn)管線(xiàn)級(jí)驗(yàn)證等機(jī)器恢復(fù)后的首輪 gate計(jì)時(shí)打印的 byte-exact 歸一化設(shè)計(jì)未立真機(jī)恢復(fù)后的續(xù)跑。但主問(wèn)題已經(jīng)答完了。plan 序 8 ——「全項(xiàng)目唯一未被回答的問(wèn)題」——能。項(xiàng)目主體P0–P4 M4至此收口。這一篇的一句話(huà)真機(jī)上的綠和開(kāi)發(fā)機(jī)上的綠是同一種東西——不是結(jié)論是信號(hào)。它這一天的信息量被三件事?lián)沃卦O(shè)備會(huì)變紅的旁證、先自測(cè)三過(guò)的豁免、對(duì)撞就報(bào)警的指紋。