Smedet og søgt, der fortjener sit bevis

Håndoptimerede kerner er som regel folklore med en benchmark vedhæftet. Forge behandler performance som et søgeproblem, der stadig skal bestå verifikation,...

Smedet og søgt, der fortjener sit bevis

Det gamle trickproblem

Ethvert seriøst softwaresystem har et par stykker kode, der betyder langt mere, end deres størrelse antyder. En løkke, der kører millioner af gange. En bitoperation i en komprimeringssti. En lille matrixrutine. En modulær aritmetisk kerne. Den slags, der ser harmløs ud i kodegennemgang og derefter stille og roligt bestemmer energiregningen, latensbudgettet eller antallet af maskiner, du skal købe. Meget demokratisk, software. Én lille funktion kan ødelægge mødet for alle.

Historisk set er disse kerner forbedret af mennesker. En senioringeniør husker et trick fra en artikel. Nogen graver i et gammelt forumindlæg. En benchmarksuite skrives. Et par kandidater afprøves. Den hurtigste vinder, hvis den stadig ser korrekt ud. Så fryser organisationen den, fordi det at røre ved den igen føles som at stikke en sovende transformer med en gaffel.

Forge er forskning i en bedre version af den proces. Det er en programsyntesemotor til små, kritiske implementeringer: giv den en typespecifikation og egenskaber, lad den søge efter kandidatprogrammer, mål og sammenlign afvejninger, verificér ækvivalens, og sænk derefter den fundne implementering ned til de mål, der betyder noget. Det vigtige ord er ikke søgning. Det vigtige ord er stadig. Den skal stadig være korrekt.

Det er derfor, Forge lever i forskningen. Det er ikke en offentlig produktknap, hvor nogen skriver gør hurtigere og modtager et mirakel. Det er en syntesearbejdsbænk til partnereksperimenter, kerneopdagelse og forskning i, hvor langt automatiseret søgning kan nå, når den er bundet til verifikation i stedet for benchmarkteater.

Forge gætter ikke i prosa. Motoren udforsker kandidatprogrammer mod en typekontrakt, og søgestrategien ændrer, hvordan dette rum besøges.

En specifikation er startlinjen

Optimering uden en specifikation er bare gambling med pænere variabelnavne. I det øjeblik en smart kandidat dukker op, skal teamet vide, hvad den skal bevare. Håndterer den alle input eller kun de venlige fra benchmarken? Respekterer den overløbsadfærd? Er den algebraiske identitet gyldig under den repræsentation, der faktisk bruges? Bevarer den den samme semantik, når den sænkes ned til en anden backend?

Forge starter fra typede udtryk og egenskaber, fordi søgningen har brug for en grænse. Grænsen siger, hvad der tæller som ækvivalent. Uden den kan motoren finde noget forbløffende hurtigt ved at slette halvdelen af arbejdet. Computere er fremragende til ondsindet efterlevelse, når kontrakten er vag.

Søgesiden er bevidst i flertal. Enumerativ søgning er nyttig, når rummet er lille nok til at dække. CEGIS er nyttig, når modeksempler kan styre forfining. Genetisk programmering og MCTS udforsker anderledes. ML-styret søgning kan lære omkostningsmodeller og prioritere lovende regioner. Ingen af disse er universelt bedst. Det er ikke en svaghed. Det er sådan, søgning opfører sig i den virkelige verden. Hvis én hammer løste hver kerne, ville værktøjskasser være meget kedelige, og hardwareleverandører ville være arbejdsløse.

Forskningsspørgsmålet er, hvordan man kombinerer disse motorer med tilstrækkeligt bevispres til, at resultatet ikke blot er smart. En syntetiseret kerne skal overleve både happy-path-benchmarken og den ulykkelige sti-verifikator. Ellers er forbedringen ikke ingeniørarbejde. Det er et magisk trick med en vedligeholdelsesomkostning.

Verifikatoren er den voksne i rummet

Forge bruger en verifikationsstak, fordi ingen enkelt kontrol er nok for alle domæner. Hurtige eksempler er billige og nyttige. Egenskabstests finder brede klasser af fejl og reducerer modeksempler til noget, et menneske kan læse. SMT-løsere som Z3 og CVC5 kan bevise ækvivalens, hvor kodningen er håndterbar. Udtømmende kontrol er praktisk for små domæner. E-graf lighedssaturation giver endnu en vej gennem algebraisk ækvivalens.

Stakken betyder noget, fordi kerner fejler på irriterende måder. En kandidat kan bestå alle almindelige benchmarks og stadig være forkert på en kantcase. Den kan være korrekt for usignerede input og forkert for signerede. Den kan være korrekt i et matematisk felt og forkert, efter den valgte repræsentation løber over. Den kan være korrekt før lowering og subtilt forkert efter en beslutning om instruktionsvalg. Verifikatoren findes, fordi optimisme ikke er en teststrategi. Vi tjekkede. Gentagne gange. Det forbliver sandt.

Verifikation bør blive strengere, efterhånden som kandidater bliver mere fristende. Jo hurtigere kandidaten ser ud, jo mindre bør vi stole på den uden bevis.

Der er også en praktisk grund til at have flere bevisveje. Formelle metoder er stærke, men de er ikke gratis. Nogle kodninger løber tør for tid. Nogle domæner er for store til udtømmende kontrol. Nogle egenskaber er nemmere at teste probabilistisk først og bevise senere. Forge behandler verifikation som en tragt, ikke et renhedsritual. Billige kontroller afviser åbenlyst nonsens. Stærkere kontroller beskytter den endelige kandidat.

Hurtig er ikke ét tal

Performancearbejde bliver fjollet, når én metrik får lov til at dominere enhver samtale. Latens betyder noget. Antal operationer betyder noget. Hukommelsesforbrug betyder noget. Registerpres betyder noget. Kompileringstid betyder nogle gange noget. Portabilitet betyder noget, når den samme kerne skal leve på mere end én backend. En kandidat, der vinder på latens ved at brænde registre af som et lille bål, kan være forkert for det faktiske mål. En kandidat, der er lille men langsom, kan være nyttig et andet sted. Kontekst forbliver ubesejret.

Forge indrammer derfor optimering som et Pareto-problem. Motoren kan søge på tværs af mål i stedet for at lade som om, der findes én universel score leveret af et meget selvsikkert regneark. Det nyttige output er ikke altid den enkelt hurtigste kandidat. Nogle gange er det en familie af kandidater med synlige afvejninger, så en ingeniør kan vælge den, der passer til implementeringsbegrænsningen.

En kerne kan være bedre på flere uforenelige måder. Forge holder den afvejning synlig i stedet for at gemme den i én heroisk score.

Det er også derfor, jeg ikke kan lide nøgne hastighedsforøgelsespåstande i blogindlæg. Forskningssiden kan beskrive interne forventninger og eksperimentelle mål, men offentlige påstande kræver friske kørsler, aktuel hardware, aktuelle compilerflag og præcis workloadkontekst. Ellers bliver tallet en souvenir. Souvenirs er rare. De er ikke arkitektur.

Den ærlige påstand er stærkere alligevel: Forge handler om at gøre søgningen reproducerbar, sammenlignelig og kontrollerbar. Når en kandidat vinder, bør vi vide, hvilket mål den vandt, hvilke kandidater den slog, hvilken verifikator der accepterede den, og hvilken backend den retter sig mod. Det er meget mere nyttigt end et tal, der flyder gennem en præsentation og ser dyr ud.

Lowering er, hvor beviser bliver testet

En opdaget implementering er kun nyttig, hvis den overlever turen til rigtige mål. Forge-forskning dækker lowering til backends som x86-64, RISC-V, WASM, Vulkan GPU-stier, C og Verilog. Den målliste er ikke pynt. Hver backend har sine egne begrænsninger, instruktionsformer, hukommelsesadfærd og fejltilstande. Den samme specifikation skal bevare sin betydning, mens implementeringen bliver noget, målet faktisk kan køre.

Det er her, syntese forbinder med resten af Dweve-stakken. Core ønsker effektive indre løkker. Numerus bekymrer sig om deterministiske numeriske kerner. BitWeave ønsker binære vektor- og matrixoperationer, der ikke spilder CPU'en. Kera bekymrer sig om at lowering af beregningsgrafer til rigtig hardware. Forge kan kun fodre de lag, hvis den genererede implementering er mere end hurtig. Den skal være ækvivalent, tilstrækkelig bærbar til det valgte mål og inspicerbar, når noget ændrer sig.

Beviset skal følge med implementeringen. Lowering er ikke stedet, hvor ækvivalens høfligt bliver glemt.

Hvad det betyder for teams

For et team er den interessante ændring ikke, at en maskine måske opdager en hurtigere kerne. Det er, at kernelarbejde bliver mindre afhængigt af folklore. I stedet for at én ekspert husker det rigtige trick, bliver processen: angiv kontrakten, søg i rummet, mål kandidater, bevis ækvivalens, registrer afvejningen, og generer målkode. Mennesker beslutter stadig. De holder bare op med at lave al opdagelse i hånden.

Det betyder noget for driften, fordi præstationsgæld er dyr på en måde, organisationer ofte skjuler. En langsom kerne bliver til flere servere. Flere servere bliver til flere omkostninger, mere energi, mere implementeringskompleksitet og mere støj i planlægningen. En forkert optimering bliver til hændelser. Et korrekt, men udokumenteret trick bliver til en fremtidig migrationsrisiko. Forge er forskning i at reducere den bunke undgåeligt nonsens.

Der er også en kulturel ændring. Manuelt præstationsarbejde belønner ofte heltemod. Nogen forsvinder ind i hulen og vender tilbage med et smart bit-trick. Alle klapper, ingen forstår det fuldt ud, og virksomheden har fået en lille hellig genstand. Forge skubber processen mod beviser: her er spec'en, her er søgeruten, her er de afviste kandidater, her er verificatoren, her er den valgte backend. Mindre mytologi. Flere kvitteringer.

Hvor arbejdet stadig er svært

Intet af dette gør syntese let. Specifikationer er svære. Hvis spec'en er forkert, kan motoren trofast opdage det forkerte. Søgerum kan eksplodere. Løsere kan time out. Omkostningsmodeller kan vildlede. Backends kan afsløre detaljer, som det abstrakte udtryk ikke bekymrede sig om. Verifikation kan være stærk i ét domæne og akavet i et andet. Enhver, der sælger programsyntese som en automat for optimal kode, springer enten over de svære dele eller tager ekstra betaling for skuffelse.

Forge er interessant netop, fordi det møder de svære dele direkte. Det kombinerer flere søgestrategier. Det holder verifikation tæt. Det behandler mål som afvejninger. Det sigter mod rigtige backends. Det forbliver et forskningsprogram, fordi vi stadig lærer, hvor grænsen går mellem automatiseret opdagelse, menneskelig dømmekraft, løserbegrænsninger og implementeringsvirkelighed.

Den grænse er værd at udforske. Softwareindustrien har for mange små hot loops, for meget duplikeret præstationsfolklore og for mange optimeringer, som ingen vil røre igen. Hvis Forge kan forvandle selv en del af det arbejde til en gentagelig bevisproces, er resultatet ikke bare hurtigere kode. Det er roligere kode. Roligere kode er undervurderet, mest af folk, der ikke er blevet paged kl. 02:17.

Hvad en god Forge-kørsel kræver

Et seriøst Forge-eksperiment starter, før motoren kører. Holdet skal have en reel kerne med, ikke en vag klage over ydeevne. Det kræver repræsentative input, kendte kanttilfælde, målhardware, aktuelle benchmarks og den forretningsmæssige begrundelse for, at denne kerne betyder noget. Ellers kan syntesemotoren bruge lang tid på at løse et problem, ingen reelt har. Forskningsværktøjer er ikke immune over for dårligt input. De gør blot skraldet dyrere at inspicere.

Det mest nyttige input er en lille, skarp kontrakt. Hvad skal funktionen beregne? Hvilke algebraiske love betyder noget? Hvilken overløbsadfærd er bevidst? Hvilke intervaller er umulige ved konstruktion, og hvilke skete blot ikke i den sidste testkørsel? Hvilke output kan tåle tilnærmelse, og hvilke kan ikke? Et hold, der ikke kan svare på de spørgsmål, har sandsynligvis ikke et optimeringsproblem endnu. Det har et produktafklaringsproblem klædt i en kompilatorhat.

En god kørsel kræver også en målholdning. x86-64 og RISC-V er ikke det samme. WASM har andre begrænsninger. Vulkan-GPU-stier bekymrer sig om former og hukommelsesbevægelser. Verilog rejser hardware-spørgsmål, som normale applikationshold sjældent nyder før kaffen. Forge kan udforske mål-lowering, men det kan ikke beslutte organisatoriske prioriteter. Hvis portabilitet betyder mere end hastighed på én platform, så sig det. Hvis latenstid slår hukommelse, så sig det. Hvis registerpres er den praktiske grænse, så sig også det. Motoren er kraftfuld, ikke synsk.

Outputtet skal behandles som en evidenspakke. Kandidat, mål, bevisvej, afviste modeksempler, backend, benchmarkkontekst og åbne forbehold. Den pakke er det, der lader mennesker træffe en fornuftig beslutning. Nogle gange er det rigtige træk at adoptere kandidaten. Nogle gange er det at beholde den gamle kerne, fordi portabilitetsafvejningen ikke er det værd. Nogle gange er opdagelsen, at specifikationen var for løs. Alle tre udfald er nyttige. Kun ét af dem ser spændende ud i en demo, hvilket er grunden til, at demoer er en dårlig erstatning for ingeniørarbejde.

Lærdommen

Lærdommen fra Forge er enkel: ydeevne bør ikke overhale bevis. Søgning er kraftfuld, men en søgemaskine uden verifikation er bare en meget energisk måde at skabe bugs på. Verifikation er kraftfuld, men uden søgning venter den på, at mennesker bringer kandidater til den. Forge sætter de to sammen og spørger, hvilke kerner vi kan opdage, når maskinen får lov til at udforske, men ikke til at lyve.

Det er den forskning, der er værd at lave. Typede specifikationer, kandidatsøgning, bevistragter, Pareto-mål og backend-lowering. Ikke magi. Ikke en produktsnitvej. En måde at lave bedre lille kode med evidens vedhæftet.