DAZ! FTZ!

Det lyder lidt som Præsidentkandidat Bill The Cat, gør det ikke ?

Det er også den slags lyde jeg pruster når jeg bliver stillet overfor moderne floating-point klamp fra Intel og AMDs side.

Engang i tidernes morgen lavede man standard IEEE 754 for floating point tal og den var lavet godt af kompetente mennesker og selv DEC måtte bide i græsset og ændre deres hardware til det nye format.

IEEE 754 specificerede gradvis denomalisering inden "underflow" og hvad pokker er så det ?

Jo, et "normaliseret" floating point tal har formen

[+/-] 1.[mantissebits] * 2^([+/-]exponentbits)

Det vigtige her er 1-bitten først i mantissen, den gør alting meget nemmere at forstå og betyder at man altid har størst muligt præcision.

Men som sagt, hvis tal bliver for små (= når exponenten ikke kan blive mere negativ) denormaliserer man sin mantisse hvilket betyder at det første bit ikke længere er et 1-bit og så regner man ellers videre, indtil man til sidst slet ikke har nogen 1-bits i mantissen og tallet bliver til et nul.

Fint nok, det har alle kunnet finde ud af i årtier, indtil Intel jokkede i spinaten.

Vi kan diskutere hvilket ben Intel først plantede i spinaten, Pentium4 eller MMX instruktionerne, men fakta er, at fra at køre stort set fuld clockrate med normaliserede tal, skal man pludselig bruge over 1500 clockcycles hvis et tal er denormaliseret, fordi opgaven bliver sendt ud til nogle mikrokode subroutiner.

Den bed os i forbindelse med ESO/ELT projektet, fordi der sidder et IIR filter i udgangen, som klinger langsomt ud.

Andre har ramt problemet før os, så der er naturligvis gjort noget ved problemet.

Det der pisser mig af, er at i stedet for at fixe deres skrammel så det overholder IEEE 754 uden at falde tilbage på hulkorthastigheder, har de introduceret to magiske flag, kaldet "DAZ" og "FTZ", hvilket betyder henholdsvis "Denormalized Are Zero" og "Flush To Zero" som virker hhv. på input og output fra MMX instruktionerne, hvor de klamper alle denormaliserede tal til nul, således at den langsomme mikrokode ikke aktiveres.

Klyt & klamp...

Disse to flag er ukendt i IEEE 754 og de tilhørende API'er (fenv(3) osv) så der er ingen portabel måde at sætte dem på og hvis man kører 32 bit mode (i386) er det en større produktion med CPUID instruktionen at finde ud af om flagene i det hele taget findes.

Med nogle compilere kan man specificere "-fast-math" og så bliver disse bits sat automatisk, på de processorer der kender til dem, (forudsat compileren ikke er skrevet af Intel og CPU'en lavet af AMD osv. osv.) men bla. LLVM har ikke denne detalje og -fast-math fjerner også en hel masse anden IEEE 754 opførsel.

Og tro mig, det er ikke noget særligt nemt problem at debugge....

Kors hvor er jeg ikke imponeret...

phk

Poul-Henning Kamps billede
Poul-Henning er selvstændig systemprogrammør, kernekoder, Varnish-forfatter, data-arkæolog og brokkehoved uden særlig portefølje.

Kommentarer (14)

Torben Mogensen

For mange år siden lavede jeg som studenterprojekt en fortolker for et LOGO-lignende sprog til en PERQ (http://en.wikipedia.org/wiki/PERQ), som KU havde fået til låns. Sproget havde ikke en særskilt heltalstype, for jeg ræsonerede, at sålænge man holdt sig under mantissens størrelse, så var de sædvanlige heltalsoperationer eksakte. Hvad de selvfølgelig burde i enhver nogenlunde fornuftig FP-repræsentation.

Følgelig implementerede jeg REPEAT N (gentag N gange) ved at sætte en variabel til N og tælle denne ned med 1, indtil man rammer 0. Jeg afprøvede konstruktionen med REPEAT 6, men til min overraskelse terminerede løkken ikke. Jeg regnede med, at det var mig, der havde kvajet mig, så jeg hev fat i debuggeren og kørte programmet igennem skridt for skridt. Dermed opdagede jeg, at 6-1-1-1-1-1-1 ikke gav 0, men et meget lille tal forskellig fra 0. Derfor ændrede jeg sammenligningen til at bruge et lille epsilon.

Jeg ved ikke hvem, der havde skrevet FP-rutinerne til PERQ, men det har i hvert fald været noget hø. Den PERQ, vi havde, var en førstegenerationsmodel. Jeg håber, at senere modeller havde bedre FP-rutiner.

Torben Mogensen

There once was a chip from Intel,
whose floating-point unit was hell.
With every division,
it lost some precision,
but they hoped that noone could tell.

Skrevet af John O'Donnel fra Glasgow University i kølvandet på Intels FDIV skandale.

Klaus Post

MMX er kun integer instruktioner - SSE er MMX med 32 bit floats (dvs. næsten, registre er 128bit i stedet for 64 bit), SSE2 tilføjer integers og double precision floats (64 bit per styk) i 128bit registre.

SSE er dog et skridt fremad i forhold til x87, der intent opererede med 80 bit præcisision, men hver gang et resultat blev skrevet til hukommelse/stakken blev det "rundet ned" til max. 64 bits præcision. Fantastisk, at det var compiler-afhængigt hvor præcist man fik sit resultat.

Troels Henriksen

Hvad med base-10/decimal arithmetic, er det ikke snart på tide at få dette indført i hardware (eller CISC->RISC bro i det mindste)?

Det lyder ikke som en god idé. Hvilket problem skulle det løse? Du vil stadigvæk have behov for præcisionsskadende afrunding, med mindre du også begynder at have tal med dynamisk størrelse (bignums).

Derimod mener jeg at man nutildags bør fokusere mindre på floating-point, og mere på rationale tal (eller fixed-point) i programmeringssprog og biblioteker. Bevares, floating point har nogle exceptionelt nyttige egenskaber, for slet ikke at snakke om god ydelse på hardwareniveau, men mange programmer har blot brug for at udføre relativt få operationer på enkle brøker, og at undgå floating-point ville være at fjerne en unødvendig kilde til fejl.

Torben Mogensen

Hvad skulle fordelen ved base-10 tal være? Du skal bruge mere tid og plads, og du får ikke bedre præcision, undtagen for brøker, hvor nævner er af formen 2^m*5^n.

Nogle vil argumentere for, at beløb i kroner og øre netop falder i denne kategori, men man bør ikke bruge FP-tal til at repræsentere beløb. I stedet skal beløb repræsenteres som et heltalligt antal øre (eller cent, pence, osv.). Der er standardiserede regler for afrunding ved renteudregning m.m., og de er nemmere at opnå med heltalsberegninger end ved FP-beregninger.

Det er rigtigt, at ældre computere havde hardware til decimalaritmetik, men det er man stort set gået bort fra i dag, og det er kun fossilsprog som COBOL, der definerer talvariable som et antal decimale cifre før og efter komma, og aritmetik er sjældent flaskehalsen i COBOL-programmer -- typisk dominerer i/o.

Jacob Christian Munch-Andersen

Ingen tvivl om at Intel har skåret et hjørne mere end de burde. Få ting er så irriterende som næsten overholdte standarder og uforudsigelige performance problemer.

Dog finder jeg nu også den oprindelige specifikation noget mærkværdig, hvis man skriver sig ud i en situation hvor forskellen på 0 og 2^-127 er væsentlig så burde man ikke bruge 32 bit float til at starte med. Brugsscenariet hvor denne feature gør en forskel forekommer simpelthen ikke at eksistere. Til gengæld er det klart at det må koste ekstra transistorer, den sparede mantissebit i formatet kan ikke på nogen elegant måde tages med over som en virtuel bit i kredsløbet, fordi den i specialtilfældet er 0 uden at tallet er 0.

Jesper Hansen

Jeg er (absolut) ikke kyndig på området, så jeg kommer lige med et helt basalt spørgsmål - kan Intel ikke 'bare' rette fejlen?

Det lyder som om at de kunne rette deres arkitektur uden de helt store kompatibilitets problemer, så længe de bevarer deres lidet yndefulde DAZ og FTZ flag. Det forudsætter naturligvis at de er enige i at det rent faktisk er en fejl og ikke en eller anden avanceret feature...

Torben Mogensen

Pricipielt er det ikke en fejl, at Intels processorer bruger lang tid på denormaliserede tal. IEEE 754 siger nemlig ikke noget om tidsforbrug, den definerer blot, hvad resultaterne af operationerne skal være -- helt ned i sidste bit.

Men det er bestemt ikke en hensigtsmæssig opførsel. Og hvis det får de fleste oversættere til at sætte DAZ eller FTZ flagene som default, så er det et de facto brud på standarden.

Intel laver det nok ikke om, før der kommer en væsentlig konkurrent på hurtige FP-beregninger. Men hvis næste generation af ARM har sammenlignelige Linpack tal med Intels processorer OG bedre tal for denormaliserede tal, så skal vi nok se Intel gøre noget ved det. Men lige nu opfører de sig som en monopolvirksomhed.

Log ind eller opret en konto for at skrive kommentarer

IT Businesses