Förbättra prestanda för Falcon-modeller med Amazon SageMaker | Amazon webbtjänster

Förbättra prestanda för Falcon-modeller med Amazon SageMaker | Amazon webbtjänster

Vad är det optimala ramverket och konfigurationen för att vara värd för stora språkmodeller (LLM) för textgenererande generativa AI-applikationer? Trots det överflöd av alternativ för att betjäna LLM:er är detta en svår fråga att besvara på grund av storleken på modellerna, varierande modellarkitekturer, prestandakrav för applikationer och mer. De Amazon SageMaker Large Model Inference (LMI) behållare gör det enkelt att betjäna LLM:er genom att sammanföra en mängd olika ramverk och tekniker som optimerar distributionen av LLM:er. LMI-behållaren har en kraftfull serveringsstack som kallas DJL servering som är agnostiskt för den underliggande LLM. Den tillhandahåller konfigurationsparametrar på systemnivå som kan ställas in för att extrahera bästa prestanda för värdinfrastrukturen för en given LLM. Den har också stöd för de senaste optimeringar som kontinuerlig batchning, även känd som iterativ batchning eller rullande batchning, vilket ger betydande förbättringar i genomströmning.

I ett tidigare inlägg, visade vi hur du kan använda LMI-behållaren för att distribuera Falcon-modellfamiljen på SageMaker. I det här inlägget visar vi hur man kan förbättra genomströmningen och latensen för att betjäna Falcon-40B med tekniker som kontinuerlig batchning. Vi tillhandahåller också en intuitiv förståelse av konfigurationsparametrar som tillhandahålls av SageMaker LMI-behållaren som kan hjälpa dig att hitta den bästa konfigurationen för din verkliga applikation.

Grunderna i textgenerativ slutledning för LLM

Låt oss först titta på några grunder om hur man utför slutledning för LLM:er för textgenerering.

Framåtpassning, aktiveringar och KV-cachen

Givet en inmatningssekvens av tokens körs de i en forward pass över alla lager i LLM (som Falcon) för att generera nästa token. A forward pass hänvisar till processen att indata passerar genom ett neuralt nätverk för att producera en utdata. I fallet med textgenerering involverar framåtpassningen att mata in ett initialt frö eller sammanhang i språkmodellen och generera nästa tecken eller token i sekvensen. För att generera en textsekvens görs processen ofta iterativt, vilket innebär att den upprepas för varje steg eller position i utdatasekvensen. Vid varje iteration genererar modellen nästa tecken eller token, som blir en del av den genererade texten, och denna process fortsätter tills den önskade textlängden genereras.

Textgenerering med språkmodeller som Falcon eller GPT är autoregressive. Detta innebär att modellen genererar en token i taget samtidigt som den konditionerar på de tidigare genererade tokens. Med andra ord, vid varje iteration tar modellen den tidigare genererade texten som indata och förutsäger nästa token baserat på det sammanhanget. Som nämnts i vLLM: Enkel, snabb och billig LLM-servering med PagedAttention, i denna autoregressiva avkodningsprocess producerar alla indatatoken till LLM deras uppmärksamhetsnyckel och värdetensorer, och dessa tensorer hålls i GPU-minnet för att generera nästa token. Dessa cachade nyckel- och värdetensorer kallas ofta för KV cache.

Förfyll och avkoda faser

I en autoregressiv avkodningsprocess, som den som används vid textgenerering med språkmodeller som Falcon, finns det vanligtvis två huvudfaser: prefill fas och decode fas. Dessa faser är avgörande för att generera sammanhängande och kontextuellt relevant text.

Förfyllningsfasen inkluderar följande:

  • Inledande sammanhang – Förfyllningsfasen börjar med en inledande kontext eller starttext som tillhandahålls av användaren. Detta initiala sammanhang kan vara en mening, en fras eller till och med bara ett enda ord. Det sätter startpunkten för textgenerering och ger sammanhang för vad som kommer härnäst.
  • Modellkonditionering – Det angivna sammanhanget används för att konditionera språkmodellen. Modellen tar detta sammanhang som input och genererar nästa token (ord eller tecken) i sekvensen baserat på dess förståelse av sammanhanget.
  • Tokengenerering – Modellen genererar en token i taget och förutsäger vad som ska komma härnäst i texten. Denna token läggs till sammanhanget och utökar det effektivt.
  • Iterativ process – Processen att generera tokens upprepas iterativt. Vid varje steg genererar modellen en token samtidigt som den beaktar det uppdaterade sammanhanget, som nu inkluderar de tokens som genererats i tidigare steg.

Förfyllningsfasen fortsätter tills ett förutbestämt stoppvillkor är uppfyllt. Detta villkor kan vara en maximal längd för den genererade texten, en specifik token som signalerar slutet på texten eller andra kriterier som ställts in av användaren eller applikationen.

Avkodningsfasen inkluderar följande:

  • Fullbordan – Efter förfyllningsfasen har du en delvis genererad text som kan vara ofullständig eller avskuren någon gång. Avkodningsfasen är ansvarig för att färdigställa texten så att den blir sammanhängande och grammatiskt korrekt.
  • Fortsättning från sista token – I avkodningsfasen utgår modellen från den sista token som genererades under förfyllningsfasen. Den använder denna token som det initiala sammanhanget och genererar nästa token för att fortsätta texten.
  • Iterativt slutförande – Liksom i förfyllningsfasen är processen att generera tokens återigen iterativ. Modellen genererar en token i taget, beroende på de föregående tokens i sekvensen.
  • Stopptillstånd – Avkodningsfasen har också ett stopptillstånd, som kan vara detsamma som i förfyllningsfasen, som att nå en maximal längd eller stöta på en textslut-token. När detta villkor är uppfyllt stoppas genereringsprocessen.

Kombinationen av förfyllnings- och avkodningsfaserna tillåter autoregressiva modeller att generera text som bygger på ett initialt sammanhang och producerar koherenta, kontextuellt relevanta och kontextuellt konsekventa textsekvenser.

Hänvisa till Ett distribuerat serversystem för transformatorbaserade generativa modeller för en detaljerad förklaring av processen.

Optimering av genomströmning med dynamisk batchning

Hittills har vi bara pratat om en enda ingång. I praktiken förväntar vi oss att hantera flera förfrågningar som kommer in slumpmässigt från applikationsklienterna för slutledning samtidigt eller på ett förskjutet sätt. På traditionellt sätt kan grundläggande batchning användas för att öka genomströmningen och utnyttjandet av datorresurserna i GPU:n. Batchning är att effektivt kombinera de numeriska representationerna av mer än en begäran i en batch och att utföra parallella körningar av de autoregressiva framåtpassningarna. Denna intelligenta dosering görs på serveringssidan. SageMaker LMI:s DJLServing-server kan konfigureras för att gruppera flera förfrågningar för att behandla dem parallellt genom att ställa in följande parametrar i serveringsegenskaper:

  • max_batch_delay = 100 – Den maximala fördröjningen för batchaggregation i millisekunder. Standardvärdet är 100 millisekunder.
  • satsstorlek = 32 – Den dynamiska batchstorleken. Standard är 1.

Detta visar i princip att DJLServing kommer att köa förfrågningar i 100 millisekunder åt gången eller om antalet förfrågningar som är i kö är upp till den specificerade batch_size, kommer batchen att schemaläggas att köras till backend för slutledning. Detta är känt som dynamic batching. Det är dynamiskt eftersom batchstorleken kan ändras över batcher beroende på hur många förfrågningar som lades till under den tidsperioden. Men eftersom förfrågningar kan ha olika egenskaper (till exempel kan vissa förfrågningar ha formen 20 tokens of output och 500 tokens of output, medan andra kan vara omvända, med 500 tokens av input men bara 20 för output), kan vissa förfrågningar slutföra bearbetningen snabbare än andra i samma batch. Detta kan resultera i underutnyttjande av GPU:n medan man väntar på att alla förfrågningar under flygningen i partiet ska slutföra sitt avkodningssteg, även om det finns ytterligare förfrågningar som väntar på att behandlas i kön. Följande diagram illustrerar denna process.

Enkel Dynamic Batching Visual

Dynamic Batching Visual – lägg märke till de lediga fönstren i slutet av begäran 2 och 3

Optimera genomströmningen med kontinuerlig batchning

Med continuous batching, också känd som iterative or rolling batchning drar vi nytta av skillnaderna mellan förfyllnings- och avkodningsstegen. För att aktivera kontinuerlig batchning tillhandahåller DJServing följande ytterligare konfigurationer enligt serving.properties:

  • motor=MPI – Vi uppmuntrar dig att använda MPI-motorn för kontinuerlig batchning.
  • option.rolling_batch=auto eller lmi-dist – Vi rekommenderar att du använder auto eftersom det automatiskt kommer att välja den lämpligaste rullande batchalgoritmen tillsammans med andra optimeringar i framtiden.
  • option.max_rolling_batch_size=32 – Detta begränsar antalet samtidiga förfrågningar. Standard är 32.

Med kontinuerlig batchning väntar inte serveringsstacken (DJLServing) på att alla förfrågningar under flygningen i en batch ska slutföra sitt avkodningssteg. Snarare, vid logiska avbrott (i slutet av en iteration i avkodningsstadiet), drar den in ytterligare förfrågningar som väntar i kön medan den aktuella batchen fortfarande bearbetas (därav namnet rullande sats). Den gör denna kontroll efter väntande förfrågningar i slutet av varje iteration av avkodningssteget. Kom ihåg att för varje begäran måste vi köra förfyllningssteget följt av det sekventiella avkodningssteget. Eftersom vi kan bearbeta alla tokens från den första uppmaningen av en begäran parallellt för dess förfyllningsskede, när som helst en ny begäran dras in, pausar vi tillfälligt avkodningsstadiet för förfrågningar under flygning av partiet – vi sparar tillfälligt dess KV-cache och aktiveringar i minnet och kör förfyllningssteget för de nya förfrågningarna.

Storleken på denna cache kan konfigureras med följande alternativ:

När förfyllningen är klar kombinerar vi de nya förfrågningarna och de gamla pausade förfrågningarna i en ny rullande batch, som kan fortsätta med deras avkodningssteg parallellt. Observera att de gamla pausade förfrågningarna kan fortsätta sitt avkodningsstadium där de slutade och de nya förfrågningarna börjar från deras första nya token.

Kontinuerlig eller Iterativ Visuell batchning

Kontinuerlig eller iterativ batchning Visuell – notera att tomgångstiderna ersätts med följ på begäran

Du kanske redan har insett att kontinuerlig batchning är ett nästan liknande tillvägagångssätt som vi naturligt parallelliserar uppgifter i vårt dagliga liv med. Vi har meddelanden, e-postmeddelanden, telefonaviseringar (potentiellt nya förfrågningar) som kommer in vid slumpmässiga tidpunkter (analogt med flera förfrågningar som kommer på ett slumpmässigt förskjutet sätt för GPU:er). Allt detta händer medan vi slutför våra uppgifter ombord – att skriva e-postmeddelanden, koda, delta i möten (analogt med de för närvarande bearbetningsuppgifterna i GPU:erna). Vid logiska pauser pausar vi våra uppgifter under flygningen och kontrollerar våra aviseringar för att avgöra om det krävs någon åtgärd från vår sida, och om det är det lägger vi till det i våra uppgifter under flygningen (real-life rolling batch), eller sätt upp det på en att göra-lista (kön).

Att sätta ihop allt: Hur man tänker kring minnesutnyttjande av GPU:er

Det rekommenderas att du laddar din modell för att se vilken konfiguration som är mest kostnadseffektiv för ditt affärsanvändningsfall. För att skapa en förståelse, låt oss visualisera minnesfotavtrycket för GPU:erna när modellen laddas och efterföljande förfrågningar behandlas i en rullande batch. För det här inlägget, låt oss anta att vi laddar Falcon-40B-modellen på en av G5-instanstyperna som är installerade med NVIDIA A10G GPU: er, var och en med 24 GB minne. Observera att en liknande förståelse är tillämplig för instanstyperna p3, p4 och p5, som kommer med V100, A100 och H100 GPU-serierna.

Följande är en översikt över att få ett ungefärligt värde på det totala minne som krävs för att betjäna Falcon-40B:

  • Modellstorlek = Antal modellparametrar (40 miljarder för Falcon-40B) x 4 byte per parameter (för FP32) = 160 GB
  • Ungefärligt totalt minne som krävs för att ladda Falcon-40B för slutledning = Modellstorlek (=160 GB) + KV-cache (Attention Cache) (=*20 GB) + Ytterligare minneskostnader av ML Frameworks (ungefär 2 GB)
Visuellt minne

Memory Visual – Förstå minnesfotavtrycket för en laddad Falcon-40B-modell

För Falcon-40B, om vi komprimerar modellen genom att kvantisera modellen till datatypen bfloat16 (2 byte), blir modellstorleken ungefär 80 GB. Som du kan se är detta fortfarande större än minnet som stöds av en acceleratorenhet, så vi måste anta en modellpartitioneringsteknik (sharding) med en speciell tensorparallellism (TP) närma och skära modellen över flera acceleratorenheter. Låt oss anta att vi har valt g5.24xlarge, som har 4 A10G GPU-enheter. Om vi ​​konfigurerar DJLServing (serving.properties) med följande, kan vi förvänta oss att 80 GB modellvikter kommer att delas lika över alla 4 GPU:er:

Med tensor_parallel_degree inställd på 4, är cirka 20 GB av 24 GB GPU-minnet (ungefär 84 %) redan använt även innan en enda begäran har behandlats. De återstående 16 % av grafikprocessorn kommer att användas för KV-cachen för inkommande förfrågningar. Det är möjligt att för ditt affärsscenario och dess latens- och genomströmningskrav är 2–3 GB av det återstående minnet mer än tillräckligt. Om inte kan du öka instansstorleken till g5.48xlarge, som har 8 GPU:er och använder tensor_parallel_degree inställd på 8. I ett sådant fall används endast cirka 10 GB av det tillgängliga 24 GB-minnet för varje GPU för modellvikter och vi har cirka 60 % av den återstående grafikprocessorn för aktiveringarna och KV-cachen. Intuitivt kan vi se att denna konfiguration kan tillåta oss att ha en högre genomströmning. Dessutom, eftersom vi har en större buffert nu, kan vi öka max_rolling_batch_prefill_tokens och max_rolling_batch_size parametrar för att ytterligare optimera genomströmningen. Tillsammans kommer dessa två parametrar att styra förallokeringarna av aktiveringsförfyllningarna och KV-cachen för modellen. Ett större antal för dessa två parametrar kommer att relateras till en större genomströmning, förutsatt att du har tillräckligt med buffert för KV-cachen i GPU-minnet.

Kontinuerlig batchning med PagedAttention

PagedAttention är en ny optimeringsalgoritm utvecklad av UC Berkeley som förbättrar den kontinuerliga batchprocessen genom att tillåta uppmärksamhetscachen (KV-cachen) att vara icke-sammanhängande genom att allokera minne i fasta sidor eller block. Detta är inspirerat av virtuellt minne och personsökningskoncept som används av operativsystem.

Enligt vLLM papper, är uppmärksamhetscachen för varje sekvens av tokens uppdelad i block och mappas till fysiska block genom en blocktabell. Under beräkningen av uppmärksamhet kan en PagedAttention-kärna använda blocktabellen för att effektivt hämta blocken från det fysiska minnet. Detta resulterar i en betydande minskning av minnesslöseri och möjliggör större batchstorlekar, ökat GPU-utnyttjande och högre genomströmning.

Prestanda jämförelse

För att säkerställa effektiv belastningstestning av din distributionskonfiguration, rekommenderas det att du börjar med att överväga affärsscenariot och tydligt definiera egenskaperna för indata och utdata för den LLM-baserade applikationen. Om du till exempel arbetar med ett användningsfall för en sammanfattning av ett callcenter kan inmatningen bestå av större text, till exempel en chattranskription på 500 token mellan en kundtjänstagent och en kund, men utdata kan vara relativt mindre, cirka 100 tokens, som representerar en sammanfattning av utskriften. Å andra sidan, om du arbetar med ett kodgenereringsscenario, kan inmatningen vara så kort som 15 tokens, som "skriv en effektiv implementering i Python för att beskriva alla EC2-resurser, inklusive sidnumrering", men utdata kan vara mycket större och når 500 tokens. Det är också viktigt att överväga om att uppnå lägre latens eller maximera genomströmningen är högsta prioritet för ditt specifika scenario.

Efter att ha fått en omfattande förståelse av affärsscenariot kan du analysera och bestämma den optimala konfigurationen för din värdmiljö. I detta sammanhang omfattar värdmiljön olika nyckelelement, inklusive instanstypen och andra konfigurationsparametrar som t.ex. tensor_parallell_degree, max_rolling_batch_size, max_rolling_batch_prefill_tokens, och mer. Vårt mål är att identifiera den mest effektiva installationen för att stödja våra krav på svarstid, genomströmning och modellutdatakvalitet.

I vår analys jämförde vi prestandan för att illustrera fördelarna med kontinuerlig batchning jämfört med traditionell dynamisk batchning. Vi använde konfigurationerna som beskrivs i följande tabell i serving.properties för dynamisk batchning och iterativ batchning, med hjälp av en LMI-behållare på SageMaker.

Dynamisk batchning Kontinuerlig batchning Kontinuerlig batchning med PagedAttention

motor=Python

option.model_id=tiiuae/falcon-40b

option.tensor_parallel_degree=8

option.dtype=fp16

batch_size=4

max_batch_delay=100

option.trust_remote_code = sant

motor = MPI

option.model_id = {{s3_url}}

option.trust_remote_code = sant

option.tensor_parallel_degree = 8

option.max_rolling_batch_size = 32

option.rolling_batch = auto

option.dtype = fp16

option.max_rolling_batch_prefill_tokens = 1024

option.paged_attention = Falskt

motor = MPI

option.model_id = {{s3_url}}

option.trust_remote_code = sant

option.tensor_parallel_degree = 8

option.max_rolling_batch_size = 32

option.rolling_batch = auto

option.dtype = fp16

option.max_rolling_batch_prefill_tokens = 1024

option.paged_attention = Sant

De två konfigurationerna benchmarkades för Falcon-40B med FP16-datatypen utplacerad på ml.g5.48xlarge i ett par olika scenarier som representerar verkliga tillämpningar:

  • Ett litet antal indata-tokens med ett stort antal tokens som genereras – I det här scenariot fastställdes antalet inmatade tokens till 32 och 128 nya tokens genererades
Doseringsstrategi Genomströmning (tokens/sek) Latens p90 (sek.)
Dynamisk batchning 5.53 58.34
Kontinuerlig batchning 56.04 4.74
Kontinuerlig batchning med PagedAttention 59.18 4.76
  • En stor ingång med ett litet antal tokens som genereras – Här fixar vi antalet inmatade tokens till 256 och uppmanar LLM att sammanfatta inmatningen till 32 tokens
Doseringsstrategi Genomströmning (tokens/sek) Latens p90 (sek.)
Dynamisk batchning 19.96 59.31
Kontinuerlig batchning 46.69 3.88
Kontinuerlig batchning med PagedAttention 44.75 2.67

Vi kan se att kontinuerlig batchning med PagedAttention ger en genomströmningsförbättring på 10 gånger större i scenario 1 och 2.3 gånger i scenario 2 jämfört med att använda dynamisk batchning på SageMaker när man använder LMI-behållaren.

Slutsats

I det här inlägget tittade vi på hur LLM:er använder minne och förklarade hur kontinuerlig batchning förbättrar genomströmningen med en LMI-behållare på SageMaker. Vi visade fördelarna med kontinuerlig batchning för Falcon-40B med en LMI-behållare på SageMaker genom att visa benchmarkresultat. Du hittar koden på GitHub repo.


Om författarna

Abhigyan ShivadityaAbhi Shivaditya är en Senior Solutions Architect på AWS, som arbetar med strategiska globala företagsorganisationer för att underlätta införandet av AWS-tjänster inom områden som artificiell intelligens, distribuerad datoranvändning, nätverk och lagring. Hans expertis ligger inom djupinlärning inom områdena Natural Language Processing (NLP) och Computer Vision. Abhi hjälper kunder att implementera högpresterande maskininlärningsmodeller effektivt inom AWS-ekosystemet.

Förbättra prestanda för Falcon-modeller med Amazon SageMaker | Amazon Web Services PlatoBlockchain Data Intelligence. Vertikal sökning. Ai.Dhawal Patel är en huvudarkitekt för maskininlärning på AWS. Han har arbetat med organisationer som sträcker sig från stora företag till medelstora startups med problem relaterade till distribuerad datoranvändning och artificiell intelligens. Han fokuserar på djupinlärning inklusive NLP- och Computer Vision-domäner. Han hjälper kunder att uppnå högpresterande modellslutningar på SageMaker.

Förbättra prestanda för Falcon-modeller med Amazon SageMaker | Amazon Web Services PlatoBlockchain Data Intelligence. Vertikal sökning. Ai.Pinak Panigrahi arbetar med kunder för att bygga maskininlärningsdrivna lösningar för att lösa strategiska affärsproblem på AWS. När han inte är sysselsatt med maskininlärning kan han hittas på en vandring, läsa en bok eller titta på sport.

Förbättra prestanda för Falcon-modeller med Amazon SageMaker | Amazon Web Services PlatoBlockchain Data Intelligence. Vertikal sökning. Ai.Abhi Sodhani innehar positionen som Senior AI/ML Solutions Architect på AWS, där han är specialiserad på att erbjuda teknisk expertis och vägledning om Generativ AI- och ML-lösningar till kunder. Hans primära fokus är att hjälpa Digital Native Businesses att realisera den fulla potentialen hos Generative AI- och ML-tekniker, vilket gör det möjligt för dem att uppnå sina affärsmål effektivt. Utöver sina professionella ansträngningar uppvisar Abhi en stark passion för intellektuella sysselsättningar som läsning, samt att engagera sig i aktiviteter som främjar fysiskt och mentalt välbefinnande, som yoga, meditation.

Förbättra prestanda för Falcon-modeller med Amazon SageMaker | Amazon Web Services PlatoBlockchain Data Intelligence. Vertikal sökning. Ai.Qing Lan är en mjukvaruutvecklingsingenjör i AWS. Han har arbetat med flera utmanande produkter i Amazon, inklusive högpresterande ML-slutledningslösningar och högpresterande loggsystem. Qings team lanserade framgångsrikt den första miljardparametermodellen i Amazon Advertising med mycket låg latens som krävs. Qing har djupgående kunskaper om infrastrukturoptimering och Deep Learning-acceleration.

Tidsstämpel:

Mer från AWS maskininlärning