Träning och resonemang av stora modeller involverar ofta begreppet noggrannhet, och det finns många typer, och de är också indelade i olika format på samma noggrannhetsnivå. Dessutom finns även begreppen multiprecision och blandad precision i praktiska scenarier.
Gemensam precision
Flyttalsnoggrannhet: dubbel precision (FP64), enkel precision (FP32, TF32), halv precision (FP16, BF16), 8-bitars noggrannhet (FP8), 4-bitars noggrannhet (FP4, NF4) Kvantifieringsnoggrannhet: INT8, INT4 (även INT3/INT5/INT6)
Ett flyttalstal består av tre delar: tecken-, exponential- och mantissabitar. Ju större exponentiell bit, desto större talintervall kan representeras. Ju större mantisssiffran, desto högre noggrannhet på talet.
Tabellen sammanfattar det enligt följande
| format | symbolbit | Exponentiell bit | Decimalplats | Totala siffror | | FP64 | 1 | 11 | 52 | 64 | | FP32 | 1 | 8 | 23 | 32 | | TF32 | 1 | 8 | 10 | 19 | | BF16 | 1 | 8 | 7 | 16 | | FP16 | 1 | 5 | 10 | 16 | | FP8 E4M3 | 1 | 4 | 3 | 8 | | FP8 E5M2 | 1 | 5 | 2 | 8 | | FP4 | 1 | 2 | 1 | 4 |
FP32: 32-bitars flyttalstal, 4 byte per data TF32: 19-bitars flyttalstal, varje data är 2 byte FP16: 16-bitars flyttalstal, 2 byte per data BF16: 16-bitars flyttalstal, varje data är 2 byte Int8: 8-bitars heltal, varje data tar hänsyn till 1 byte Int4: 4-bitars heltal, varje data är 0,5 byte
Varför så mycket precision
På grund av kostnad och noggrannhet. Vi vet alla att hög noggrannhet definitivt är mer exakt, men det kommer också att medföra högre kostnader för beräkning och lagring. Lägre precision minskar beräkningsnoggrannheten men kan förbättra beräkningseffektivitet och prestanda. Så en mängd olika precisioner gör att du kan välja den mest lämpliga i olika situationer. Dubbel precision är mer exakt än uttryck med enkel precision, men det tar upp dubbelt så mycket lagringsutrymme och mer tid att beräkna.
Varför behöver stora modeller kvantifieras?
1. Minska minnesanvändningen Stora modeller använder vanligtvis 32-bitars flyttal (FP32) eller 16-bitars flyttalstal (FP16) för att representera vikter och aktiveringsvärden. Genom kvantisering kan dessa högprecisionsvärden omvandlas till lägre precisionsrepresentationer (t.ex. 8-bitars heltal, INT8), vilket avsevärt minskar modellens lagringsutrymme. Detta är viktigt för distribution på resursbegränsade enheter såsom mobila enheter, inbyggda system med mera.
2. Öka resonemangshastigheten Kvantiserade modeller kan köras mer effektivt på hårdvara. Mycket modern hårdvara (såsom GPU:er, TPU:er, NPU:er, etc.) har specialiserat optimeringsstöd för lågprecisionsberäkningar, vilket möjliggör snabbare kvantiseringsoperationer. Dessutom involverar lågprecisionsberäkningar ofta färre bitoperationer, vilket minskar beräkningskomplexiteten och därmed påskyndar inferensen.
3. Minska strömförbrukningen Den kvantiserade modellen minskar inte bara behovet av datorresurser utan minskar även energiförbrukningen. Detta är särskilt viktigt för batteridrivna enheter som smartphones, IoT-enheter med mera, där låg strömförbrukning innebär längre batteritid.
4. Lätta att distribuera edge-enheter Många stora modeller tränades och distribuerades initialt i molnet, men med utvecklingen av edge computing kräver allt fler applikationsscenarier att modeller distribueras på edge-enheter. Med begränsad datorkraft och lagringsresurser på edge-enheter kan kvantisering hjälpa dessa modeller att fungera mer effektivt på edge-enheter.
5. Minska bandbreddskraven I processen med distribuerad inferens eller modelluppdateringar kan kvantisering minska bandbredden som krävs för modellöverföring. Detta är användbart i miljöer med begränsad nätverksbandbredd, såsom IoT-enheter i avlägsna områden.
6. Upprätthålla modellens prestanda Även om kvantisering medför en viss förlust av precision kan modellens ursprungliga prestanda till stor del bevaras genom lämpliga kvantiseringsmetoder (såsom blandprecisionskvantisering, efterträningskvantisering, kvantitativ perceptionsträning, etc.). Därför kan kvantifiering i praktiska tillämpningar hitta en bra balans mellan prestanda och effektivitet.
Minnesreferens
| typ | Varje miljard parametrar behöver uppta minnet | | float32 | 4G | | FP16/BF16 | 2G | | int8 | 1G | | int4 | 0,5G |
FP64 (Dubbelprecision)
64-bitars flyttalsformat, vanligtvis ett dubbelprecisions binärt flyttalsformat definierat av IEEE 754, har:
1-siffrig symbol 11-siffrigt index 52 decimaler
Räckvidd: ~2,23e-308 ... ~1,80e308 med full 15-17 decimalprecision.
Användning:
Detta format används för vetenskapliga beräkningar som kräver hög precision. Den används vanligtvis inte för djupinlärningsberäkningar. Mjukvarustöd: Representerar dubbeltypen på de flesta C/C++-system. Stöds i TensorFlow (t.ex. tf.float64) / PyTorch (t.ex. torch.float64 eller torch.double). Hårdvarustöd: Vanligtvis stöds det i x86-processorer. De flesta GPU:er, särskilt gaming-GPU:er, inklusive RTX-serien, är kraftigt begränsade i FP64-prestanda (vanligtvis 1/32 av FP32:s prestanda istället för 1/2). Nyligen obegränsade FP64-stödda GPU:er inkluderar GP100/100/102/104 i Tesla P40/P4 och Quadro GP100, GV100 i Tesla V100/Quadro GV100/Titan V, samt den nyligen tillkännagivna GA100 i A100 (intressant nog har den nya Ampere-arkitekturen en tredje generation) jämfört med FP64-aktiverade Tensor-kärnor Den nya IEEE-kompatibla FP64-processorn ingår nu och levererar 2,5 gånger FP64-prestandan jämfört med V100.
FP32 (Full precision)
Detta format har länge varit en arbetshäst för djupinlärning. Ett annat IEEE 754-format, enkelprecisionsflyttal, har:
1-siffrig symbol 8-siffrigt index 23 decimaler Idealiskt bör både träning och inferens göras i FP32, men FP32 är dubbelt så långsamt som FP16/BF16, så metoder med blandad precision används ofta i praktiken, där FP32-vikter används som exakt "huvudvikt", FP16/BF16-vikter används för framåt- och bakåtpropagering för att förbättra träningshastigheten, och slutligen uppdateras FP32-suveräna vikter med FP16/BF16-gradienter i gradientuppdateringsfasen.
Under träningen är den suveräna vikten alltid FP32. I praktiken ger halvprecisionsvikter ofta liknande noggrannhet som FP32 vid inferensering – eftersom exakta FP32-vikter endast behövs när modellgradienten uppdateras. Detta innebär att vi kan använda halvprecisionsvikter vid inferens, så vi kan få samma resultat med bara halva GPU-minnet.
Räckvidd: ~1,18e-38 ... ~3,40e38 med en noggrannhet på 6–9 signifikanta decimaler.
Användning:
Den standardtyp av neurala nätverksberäkningar under lång tid. Vikter, aktiveringar och andra värden i neurala nätverk har länge varit standard på FP32. För många vetenskapliga beräkningar, särskilt iterativa, räcker noggrannheten inte till, vilket leder till felackumulering. Mjukvarustöd: Representerar flottörstypen på de flesta C/C++-system. Stöds i TensorFlow (t.ex. tf.float32) / PyTorch (t.ex. torch.float32 eller torch.float). Hårdvarustöd: Vanligtvis stöds det i x86-processorer. Vanligtvis stöds det av NVIDIA/AMD GPU.
FP16 (Halvprecision)
På liknande sätt har IEEE 754-standardformatet, halvprecisionsformatet flyttalsformat:
1-siffrig symbol 5-siffrigt index 10 decimaler FP16-numret har ett mycket lägre numeriskt intervall än FP32. Därför riskerar FP16 att bli överflöd (när det används för att representera mycket stora tal) och underflöde (när det används för att representera mycket små tal). Till exempel, när du gör 10k * 10k, ska slutresultatet bli 100M, vilket FP16 inte kan representera eftersom det maximala antalet FP16 kan representera är 64k. Så du får NaN (Inte ett Tal) i neurala nätverksberäkningar, eftersom beräkningarna görs i lager- och batchordning, så när NaN dyker upp förstörs alla tidigare beräkningar. Generellt kan detta mildras genom förlustskalning, men detta tillvägagångssätt fungerar inte alltid.
Omfång: ~5,96e−8 (6,10e−5) ... 65504, med en noggrannhet på 4 betydande decimalsiffror.
Användning:
Djupinlärning tenderar att använda FP16 istället för FP32, eftersom beräkningar med lägre precision inte verkar spela någon roll för neurala nätverk. Den extra precisionen gör ingenting, och samtidigt är det långsammare, kräver mer minne och saktar ner kommunikationen. Kan användas för träning, vanligtvis med blandad precisionsträning (TensorFlow/PyTorch). Kan användas för kvantisering efter träning för att påskynda inferensen (TensorFlow Lite). Andra format som används för kvantisering efter träning inkluderar heltal INT8 (8-bitars heltal), INT4 (4-bitars) och till och med INT1 (binära värden). Mjukvarustöd: Inte för närvarande i C/C++-standarden (men det finns ett förslag om kort flyt). Vissa C/C++-system stöder __fp16 typer. Annars kan den användas med specialbibliotek. Stöds i TensorFlow (t.ex. tf.float16) / PyTorch (t.ex. torch.float16 eller torch.half). Hårdvarustöd: x86-processorer stöds inte (som en unik typ). Stödet på äldre gaming-GPU:er är dåligt (32/1-prestanda för FP64, se inlägget om GPU:er för mer information). Det stöds för närvarande väl på moderna GPU:er, såsom NVIDIA RTX-serien.
BFLOAT16 (Halvprecision)
Ett annat 16-bitarsformat som ursprungligen utvecklades av Google kallas "Brain Floating Point Format", eller "bfloat16" i korthet. Namnet kommer från Google Brain.
Den ursprungliga IEEE FP16 designades utan djupinlärningsapplikationer i åtanke, och dess dynamiska omfång var för smalt. BFLOAT16 löser detta problem och ger samma dynamiska omfång som FP32.
Därför har BFLOAT16:
1-siffrig symbol 8-siffrigt index 7 decimaler
bfloat16-formatet är förkortat till IEEE 754 FP32, vilket möjliggör snabb konvertering till och från IEEE 754 FP32. Vid konvertering till bfloat16-formatet bevaras exponentiella bitar, medan mantissfälten kan minskas genom trunkering.
Räckvidd: ~1,18e-38 ... ~3,40e38 med 3 betydande decimaler. Användning:
Nu verkar det ersätta FP16. Till skillnad från FP16, som ofta kräver specialbearbetning genom tekniker som förlustskalning, är BF16 nästan en direkt ersättning för FP32 vid träning och drift av djupa neurala nätverk. Mjukvarustöd: Inte i C/C++-standarden. Kan användas med specialbibliotek. Stöds i TensorFlow (t.ex. tf.bfloat16) / PyTorch (t.ex. torch.bfloat16).
TF32
TensorFloat-32 eller TF32 är det nya matematikläget i NVIDIA A100-grafikkort.
Med samma 10-bitars mantissor som halvprecisionsmatematik (FP16) visar TF32 att den har tillräckligt med utrymme för att uppfylla precisionskraven för AI-arbetsbelastningar. Och TF32 använder samma 8-bitars index som FP32, så det kan stödja samma numeriska intervall.
Tekniskt sett är det ett 19-bitars format. Tänk på det som en utökad precisions BFLOAT16, som "BFLOAT19" eller en minskad precision som FP32.
Så, TF32 har:
1-siffrig symbol 8-siffrigt index 10 decimaler Fördelen med TF32 är att det har samma format som FP32. När inomprodukten beräknas med TF32 avrundas mantissan för ingångsoperanden från 23 till 10 bitar. Avrundningsoperanderna multipliceras exakt och ackumuleras i normal FP32.
TF32 Tensor Core körs på FP32-indata och genererar resultat i FP32 utan kodändringar. Icke-matrisoperationer fortsätter att använda FP32. Detta ger ett enkelt sätt att accelerera FP32-in-/utdata i djupinlärningsramverk och HPC.
Räckvidd: ~1,18e-38 ... ~3,40e38 med en noggrannhet på 4 signifikanta decimaler. Användning:
En av de bästa sakerna med TF32 är att det bara behöver kompilatorstöd på den djupaste nivån, alltså inuti CUDA-kompilatorn. Resten av koden visar bara FP32 med mindre precision, men samma dynamiska omfängd. Att använda TF32 är främst för att ringa biblioteket för att visa om det fungerar som det ska. Närvaron av TF32 möjliggör snabba plug-in-inkopplingar och utnyttjar hastigheten hos Tensor Cores utan mycket arbete. Format som FP16 och BFLOAT16 kräver mer finjustering eftersom de involverar olika bitlayouter. Men användningen av dessa format minskar minnesbandbredden, vilket möjliggör snabbare exekvering. Som jämförelse är A100:s toppprestanda:
FP32 utan tensorkärnor: 19,5 TFLOPS TF32 Tensorkärnor: 156 TFLOPS (så att använda TF32 istället för FP32 gör det enkelt att öka hastigheten). FP16/BF16 Tensor-kärnor: 312 TFLOPS (därför kan ett rimligt byte till FP16/BF16 ge fler hastighetsökningar, men till högre kostnad). Mjukvarustöd: Inte i C/C++-standarden. CUDA 11 stöds. Hårdvarustöd: GPU: NVIDIA A100 är den första modellen som stöds
FP8
Introducerad av H100-GPU:n möjliggör den större matrismultiplikation och konvolution, men med lägre precision.
De FP100-datatyper som stöds av H8 är faktiskt två olika datatyper som kan användas för olika delar av träningen av neurala nätverk:
E4M3 – består av 1 symbolisk bit, 4 exponentiella bitar och 3 decimaler. Den kan lagra upp till +/-448 och nan. E5M2 – består av 1 teckenbit, 5 exponentiella bitar och 2 decimaler. Den kan lagra värden upp till +/-57344, +/-inf och nan. Nackdelen med att öka dynamiskt omfång är att de lagrade värdena är mindre exakta.
Struktur för flyttalsdatatyper. Alla visade värden (i FP16, BF16, FP8 E4M3 och FP8 E5M2) är den närmaste representationen av värdet 0,3952.
Båda typerna kan användas vid träning av ett neuralt nätverk. Generellt kräver framåtaktivering och vikter högre precision, så det är bäst att använda E4M3-datatypen under framåtpassning. Vid backpropagation är dock gradienten som flödar genom nätverket generellt mindre känslig för förlust av precision men kräver ett högre dynamiskt omfång. Därför är det bäst att lagra dem med E5M2-dataformatet. H100 TensorCore stöder alla kombinationer av dessa typer som indata, vilket gör att vi kan lagra varje tensor med dess önskade precision.
Hänvisning:
Inloggningen med hyperlänken är synlig.
Inloggningen med hyperlänken är synlig. |