Forge și căutare care își merită dovada
Vechiul truc cu problema
Fiecare sistem software serios are câteva bucăți de cod care contează mult mai mult decât sugerează dimensiunea lor. O buclă care rulează de milioane de ori. O operație pe biți într-o cale de compresie. O rutină mică de matrice. Un nucleu de aritmetică modulară. Genul de lucru care pare inofensiv la revizuirea codului și apoi decide în liniște factura de energie, bugetul de latență sau numărul de mașini pe care trebuie să le cumperi. Foarte democratic, software-ul. O singură funcție mică poate strica ședința pentru toată lumea.
Istoric, aceste nuclee sunt îmbunătățite de oameni. Un inginer senior își amintește un truc dintr-o lucrare. Cineva scormonește printr-o postare veche de pe un forum. Se scrie un set de benchmark-uri. Se încearcă câțiva candidați. Cel mai rapid câștigă dacă pare în continuare corect. Apoi organizația îl îngheață, pentru că a-l atinge din nou pare ca și cum ai înțepa un transformator adormit cu o furculiță.
Forge este cercetare pentru o versiune mai bună a acestui proces. Este un motor de sinteză de programe pentru implementări mici și critice: dă-i o specificație tipizată și proprietăți, lasă-l să caute programe candidate, măsoară și compară compromisurile, verifică echivalența, apoi coboară implementarea descoperită către țintele care contează. Cuvântul important nu este căutare. Cuvântul important este în continuare. Trebuie să fie corect în continuare.
De aceea Forge trăiește în cercetare. Nu este un buton de produs public unde cineva tastează fă-l mai rapid și primește o minune. Este un banc de lucru pentru sinteză pentru experimente cu parteneri, descoperire de nuclee și cercetare despre cât de departe poate ajunge căutarea automată atunci când este legată de verificare în loc de teatru de benchmark-uri.
O specificație este linia de start
Optimizarea fără o specificație este doar joc de noroc cu nume de variabile mai frumoase. În momentul în care apare un candidat inteligent, echipa trebuie să știe ce ar trebui să păstreze. Se ocupă de fiecare intrare sau doar de cele prietenoase din benchmark? Respectă comportamentul de depășire? Este identitatea algebrică validă sub reprezentarea folosită efectiv? Păstrează aceeași semantică atunci când este coborât către un backend diferit?
Forge pornește de la expresii tipizate și proprietăți pentru că căutarea are nevoie de o graniță. Granița spune ce contează ca echivalent. Fără ea, motorul poate găsi ceva uluitor de rapid ștergând jumătate din muncă. Calculatoarele sunt excelente la conformitate rău intenționată atunci când contractul este vag.
Partea de căutare este deliberat la plural. Căutarea enumerativă este utilă când spațiul este suficient de mic pentru a fi acoperit. CEGIS este util când contraexemplele pot ghida rafinarea. Programarea genetică și MCTS explorează diferit. Căutarea ghidată de ML poate învăța modele de cost și poate prioritiza regiuni promițătoare. Niciuna dintre acestea nu este universal cea mai bună. Asta nu este o slăbiciune. Așa se comportă căutarea în lumea reală. Dacă un singur ciocan ar rezolva fiecare nucleu, trusele de scule ar fi foarte plictisitoare, iar furnizorii de hardware ar fi șomeri.
Întrebarea de cercetare este cum să combini aceste motoare cu suficientă presiune de demonstrare încât rezultatul să nu fie doar inteligent. Un nucleu sintetizat trebuie să supraviețuiască atât benchmark-ului pe calea fericită, cât și verificatorului pe calea nefericită. Altfel, îmbunătățirea nu este inginerie. Este un truc de magie cu un cost de întreținere.
Verificatorul este adultul din cameră
Forge folosește un stiv de verificare pentru că nicio verificare unică nu este suficientă pentru fiecare domeniu. Exemplele rapide sunt ieftine și utile. Testele de proprietăți găsesc clase largi de erori și reduc contraexemplele la ceva ce poate citi un om. Solverele SMT precum Z3 și CVC5 pot demonstra echivalența acolo unde codificarea este tractabilă. Verificarea exhaustivă este practică pentru domenii mici. Saturația de egalitate cu e-graph oferă o altă cale prin echivalența algebrică.
Stivul contează pentru că nucleele eșuează în moduri enervante. Un candidat poate trece fiecare test standard și totuși să fie greșit într-un caz limită. Poate fi corect pentru intrări fără semn și greșit pentru cele cu semn. Poate fi corect într-un câmp matematic și greșit după ce reprezentarea aleasă depășește limita. Poate fi corect înainte de lowering și subtil greșit după o decizie de selecție a instrucțiunilor. Verificatorul există pentru că optimismul nu este o strategie de testare. Am verificat. În mod repetat. Rămâne adevărat.
Există și un motiv practic pentru a păstra mai multe căi de demonstrare. Metodele formale sunt puternice, dar nu sunt gratuite. Unele codificări expiră. Unele domenii sunt prea mari pentru verificarea exhaustivă. Unele proprietăți sunt mai ușor de testat probabilistic mai întâi și de demonstrat mai târziu. Forge tratează verificarea ca pe o pâlnie, nu ca pe un ritual de puritate. Verificările ieftine resping prostiile evidente. Verificările mai puternice protejează candidatul final.
Rapid nu înseamnă un singur număr
Munca de performanță devine ridicolă când o singură metrică are voie să domine fiecare conversație. Latența contează. Numărul de operații contează. Utilizarea memoriei contează. Presiunea pe registre contează. Timpul de compilare uneori contează. Portabilitatea contează când același nucleu trebuie să trăiască pe mai mult de un backend. Un candidat care câștigă la latență arzând registre ca un foc de tabără mic poate fi greșit pentru ținta reală. Un candidat mic dar lent poate fi util în altă parte. Contextul rămâne neînvins.
Forge încadrează deci optimizarea ca pe o problemă Pareto. Motorul poate căuta între obiective în loc să pretindă că există un scor universal dat de o foaie de calcul foarte încrezătoare. Rezultatul util nu este întotdeauna cel mai rapid candidat. Uneori este o familie de candidați cu compromisuri vizibile, astfel încât un inginer să poată alege pe cel care se potrivește constrângerii de implementare.
Acesta este și motivul pentru care nu îmi plac afirmațiile goale de accelerare în postările de blog. Pagina de cercetare poate descrie așteptările interne și obiectivele experimentale, dar afirmațiile publice au nevoie de rulări proaspete, hardware actual, flaguri de compilator actuale și context exact al sarcinii de lucru. Altfel, numărul devine un suvenir. Suvenirurile sunt drăguțe. Nu sunt arhitectură.
Afirmația onestă este oricum mai puternică: Forge este despre a face căutarea reproductibilă, comparabilă și verificabilă. Când un candidat câștigă, ar trebui să știm ce obiectiv a câștigat, ce candidați a bătut, ce verificator l-a acceptat și ce backend vizează. Asta este mult mai util decât un număr care plutește printr-un slide deck părând scump.
Lowering este locul unde dovezile sunt puse la încercare
O implementare descoperită este utilă doar dacă supraviețuiește drumului către țintele reale. Cercetarea Forge acoperă coborârea către backend-uri precum x86-64, RISC-V, WASM, căi GPU Vulkan, C și Verilog. Această listă de ținte nu este decorativă. Fiecare backend are propriile constrângeri, forme de instrucțiuni, comportament de memorie și moduri de eșec. Aceeași specificație trebuie să-și păstreze sensul în timp ce implementarea devine ceva ce ținta poate rula efectiv.
Aici sinteza se conectează cu restul stivei Dweve. Core vrea bucle interioare eficiente. Numerus se concentrează pe nuclee numerice deterministe. BitWeave vrea operații binare pe vectori și matrice care nu irosesc CPU-ul. Kera se ocupă de coborârea graficelor de calcul către hardware real. Forge poate alimenta aceste straturi doar dacă implementarea generată este mai mult decât rapidă. Trebuie să fie echivalentă, suficient de portabilă pentru ținta aleasă și inspectabilă atunci când ceva se schimbă.
Ce înseamnă asta pentru echipe
Pentru o echipă, schimbarea interesantă nu este că o mașină ar putea descoperi un nucleu mai rapid. Este că munca la nuclee devine mai puțin dependentă de folclor. În loc ca un expert să-și amintească trucul potrivit, procesul devine: enunță contractul, caută în spațiu, măsoară candidații, dovedește echivalența, înregistrează compromisul și generează codul țintă. Oamenii încă decid. Doar că nu mai fac toată descoperirea manual.
Asta contează pentru operațiuni, pentru că datoria de performanță este scumpă într-un mod pe care organizațiile îl ascund adesea. Un nucleu lent înseamnă mai multe servere. Mai multe servere înseamnă mai mult cost, mai multă energie, mai multă complexitate de implementare și mai mult zgomot în planificare. O optimizare greșită devine incidente. Un truc corect dar nedocumentat devine un risc de migrare viitor. Forge este cercetare pentru reducerea acestei grămezi de prostii evitabile.
Există și o schimbare culturală. Munca manuală de performanță recompensează adesea isprăvile eroice. Cineva dispare în peșteră și se întoarce cu un truc ingenios. Toți aplaudă, nimeni nu înțelege pe deplin, iar compania a dobândit un mic obiect sacru. Forge împinge procesul către dovezi: iată specificația, iată ruta de căutare, iată candidații respinși, iată verificatorul, iată backend-ul selectat. Mai puțină mitologie. Mai multe chitanțe.
Unde munca este încă dificilă
Nimic din toate acestea nu face sinteza ușoară. Specificațiile sunt dificile. Dacă specificația este greșită, motorul poate descoperi fidel lucrul greșit. Spațiile de căutare pot exploda. Solverele pot expira. Modelele de cost pot induce în eroare. Backend-urile pot expune detalii de care expresia abstractă nu se îngrijea. Verificarea poate fi puternică într-un domeniu și stângace în altul. Oricine vinde sinteza de programe ca pe un automat de cod optim fie sare peste părțile dificile, fie percepe un preț suplimentar pentru dezamăgire.
Forge este interesant tocmai pentru că se confruntă direct cu aceste părți dificile. Combină mai multe strategii de căutare. Ține verificarea aproape. Tratează obiectivele ca pe compromisuri. Vizează backend-uri reale. Rămâne un program de cercetare pentru că încă învățăm unde se află granița dintre descoperirea automată, judecata umană, limitele solverelor și realitatea implementării.
Această graniță merită explorată. Industria software are prea multe bucle fierbinți mici, prea mult folclor de performanță duplicat și prea multe optimizări de care nimeni nu vrea să se atingă din nou. Dacă Forge poate transforma chiar și o parte din această muncă într-un proces repetabil bazat pe dovezi, rezultatul nu este doar cod mai rapid. Este cod mai calm. Codul calm este subestimat, mai ales de cei care nu au fost chemați la 02:17.
Ce presupune o rulare Forge reușită
Un experiment Forge serios începe înainte de rularea motorului. Echipa trebuie să aducă un kernel real, nu o plângere vagă legată de performanță. Sunt necesare intrări reprezentative, cazuri limită cunoscute, hardware țintă, benchmark-uri actuale și motivul de business pentru care acest kernel contează. Altfel, motorul de sinteză poate petrece mult timp rezolvând o problemă pe care nimeni nu o are de fapt. Instrumentele de cercetare nu sunt imune la intrări nedorite. Ele doar fac deșeurile mai scumpe de inspectat.
Cea mai utilă intrare este un contract mic și clar. Ce ar trebui să calculeze funcția? Ce legi algebrice contează? Ce comportament de overflow este intenționat? Ce intervale sunt imposibile prin construcție și care pur și simplu nu au apărut în ultima rulare de test? Ce ieșiri pot tolera aproximarea și care nu? O echipă care nu poate răspunde la aceste întrebări probabil nu are încă o problemă de optimizare. Are o problemă de clarificare a produsului deghizată în problemă de compilator.
O rulare bună are nevoie și de o postură țintă. x86-64 și RISC-V nu sunt același lucru. WASM are constrângeri diferite. Căile GPU Vulkan țin cont de forme și de mișcarea memoriei. Verilog ridică întrebări hardware pe care echipele obișnuite de aplicații rareori le abordează înainte de cafea. Forge poate explora lowerarea țintă, dar nu poate decide prioritățile organizaționale. Dacă portabilitatea contează mai mult decât viteza pe o singură țintă, spuneți asta. Dacă latența este mai importantă decât memoria, spuneți asta. Dacă presiunea pe registre este limita practică, spuneți și asta. Motorul este puternic, nu psihic.
Rezultatul ar trebui tratat ca un pachet de dovezi. Candidat, obiectiv, traseu de demonstrație, contraexemple respinse, backend, context de benchmark și limitări deschise. Acest pachet este ceea ce permite oamenilor să ia o decizie rațională. Uneori, mutarea câștigătoare este adoptarea candidatului. Alteori, este păstrarea kernelului vechi pentru că compromisul de portabilitate nu merită. Uneori, descoperirea este că specificația era prea laxă. Toate cele trei rezultate sunt utile. Doar unul dintre ele pare interesant într-o demonstrație, motiv pentru care demonstrațiile sunt un substitut slab pentru inginerie.
Lecția
Lecția Forge este simplă: performanța nu ar trebui să depășească demonstrația. Căutarea este puternică, dar un motor de căutare fără verificare este doar o modalitate foarte energică de a crea bug-uri. Verificarea este puternică, dar fără căutare așteaptă ca oamenii să aducă candidați. Forge le pune pe cele două împreună și întreabă ce kernel-uri putem descoperi atunci când mașinii i se permite să exploreze, dar nu i se permite să mintă.
Aceasta este cercetarea care merită făcută. Specificații tipizate, căutare de candidați, pâlnii de demonstrație, obiective Pareto și lowerare backend. Nu magie. Nu o scurtătură de produs. O modalitate de a crea cod mic mai bun, cu dovezi atașate.