Forbedre ytelsen til Falcon-modeller med Amazon SageMaker | Amazon Web Services

Forbedre ytelsen til Falcon-modeller med Amazon SageMaker | Amazon Web Services

Hva er det optimale rammeverket og konfigurasjonen for å være vert for store språkmodeller (LLM) for tekstgenererende generative AI-applikasjoner? Til tross for overfloden av alternativer for å betjene LLM-er, er dette et vanskelig spørsmål å svare på på grunn av størrelsen på modellene, varierende modellarkitektur, ytelseskrav til applikasjoner og mer. De Amazon SageMaker Large Model Inference (LMI) container gjør det enkelt å betjene LLM-er ved å samle en rekke forskjellige rammeverk og teknikker som optimaliserer distribusjonen av LLM-er. LMI-beholderen har en kraftig serveringsstabel kalt DJL servering som er agnostisk for den underliggende LLM. Den gir konfigurasjonsparametere på systemnivå som kan justeres for å trekke ut den beste ytelsen til vertsinfrastrukturen for en gitt LLM. Den har også støtte for nyere optimaliseringer som kontinuerlig batching, også kjent som iterativ batching eller rullende batching, som gir betydelige forbedringer i gjennomstrømning.

I et tidligere poste, viste vi hvordan du kan bruke LMI-beholderen til å distribuere Falcon-familien av modeller på SageMaker. I dette innlegget demonstrerer vi hvordan vi kan forbedre gjennomstrømningen og ventetiden for å betjene Falcon-40B med teknikker som kontinuerlig batching. Vi gir også en intuitiv forståelse av konfigurasjonsparametere levert av SageMaker LMI-beholderen som kan hjelpe deg med å finne den beste konfigurasjonen for din virkelige applikasjon.

Grunnleggende om tekstgenerativ slutning for LLM-er

La oss først se på noen få grunnleggende om hvordan du utfører slutninger for LLM-er for tekstgenerering.

Videresending, aktiveringer og KV-cachen

Gitt en inndatasekvens av tokens, kjøres de i en forward pass på tvers av alle lagene i LLM (som Falcon) for å generere neste token. EN forward pass refererer til prosessen med inndata som sendes gjennom et nevralt nettverk for å produsere en utgang. Når det gjelder tekstgenerering, involverer videresendingen å mate et første frø eller kontekst inn i språkmodellen og generere neste tegn eller token i sekvensen. For å generere en tekstsekvens, gjøres prosessen ofte iterativt, noe som betyr at den gjentas for hvert trinn eller posisjon i utdatasekvensen. Ved hver iterasjon genererer modellen neste tegn eller token, som blir en del av den genererte teksten, og denne prosessen fortsetter til ønsket lengde på teksten er generert.

Tekstgenerering med språkmodeller som Falcon eller GPT er autoregressive. Dette betyr at modellen genererer ett token om gangen mens den kondisjonerer på de tidligere genererte tokenene. Med andre ord, ved hver iterasjon tar modellen den tidligere genererte teksten som input og forutsier neste token basert på den konteksten. Som nevnt i vLLM: Enkel, rask og billig LLM-servering med PagedAttention, i denne autoregressive dekodingsprosessen produserer alle input-tokenene til LLM sine oppmerksomhetsnøkkel- og verditensorer, og disse tensorene holdes i GPU-minnet for å generere neste tokens. Disse bufrede nøkkel- og verditensorene blir ofte referert til som KV cache.

Forutfyll og dekode faser

I en autoregressiv dekodingsprosess, som den som brukes i tekstgenerering med språkmodeller som Falcon, er det vanligvis to hovedfaser: prefill fase og decode fase. Disse fasene er avgjørende for å generere sammenhengende og kontekstuelt relevant tekst.

Forfyllingsfasen inkluderer følgende:

  • Opprinnelig kontekst – Forutfyllingsfasen begynner med en innledende kontekst eller starttekst gitt av brukeren. Denne innledende konteksten kan være en setning, en setning eller til og med bare et enkelt ord. Det setter utgangspunktet for tekstgenerering og gir kontekst for det som kommer etterpå.
  • Modellkondisjonering – Den oppgitte konteksten brukes til å betinge språkmodellen. Modellen tar denne konteksten som input og genererer neste token (ord eller tegn) i sekvensen basert på dens forståelse av konteksten.
  • Tokengenerering – Modellen genererer ett token om gangen, og forutsier hva som skal komme videre i teksten. Dette tokenet er lagt til konteksten, og utvider den effektivt.
  • Iterativ prosess – Prosessen med å generere tokens gjentas iterativt. Ved hvert trinn genererer modellen et token mens den vurderer den oppdaterte konteksten, som nå inkluderer tokenene generert i tidligere trinn.

Forfyllingsfasen fortsetter inntil en forhåndsbestemt stoppbetingelse er oppfylt. Denne betingelsen kan være en maksimal lengde for den genererte teksten, et spesifikt token som signaliserer slutten av teksten, eller andre kriterier satt av brukeren eller applikasjonen.

Dekodingsfasen inkluderer følgende:

  • Ferdigstillelse – Etter forhåndsutfyllingsfasen har du en delvis generert tekst som kan være ufullstendig eller avskåret på et tidspunkt. Avkodingsfasen er ansvarlig for å fullføre teksten for å gjøre den sammenhengende og grammatisk korrekt.
  • Fortsettelse fra siste token – I dekodefasen starter modellen fra det siste tokenet som ble generert under forfyllingsfasen. Den bruker dette tokenet som den første konteksten og genererer neste token for å fortsette teksten.
  • Iterativ fullføring – Som i prefill-fasen, er prosessen med å generere tokens igjen iterativ. Modellen genererer ett token om gangen, avhengig av de foregående tokenene i sekvensen.
  • Stoppetilstand – Dekodingsfasen har også en stopptilstand, som kan være den samme som i forhåndsutfyllingsfasen, for eksempel når en maksimal lengde eller støter på et slutt-på-tekst-token. Når denne betingelsen er oppfylt, stopper generasjonsprosessen.

Kombinasjonen av forhåndsutfyllings- og dekodefasene lar autoregressive modeller generere tekst som bygger på en innledende kontekst og produserer sammenhengende, kontekstuelt relevante og kontekstuelt konsistente tekstsekvenser.

Referere til Et distribuert serveringssystem for transformatorbaserte generative modeller for en detaljert forklaring av prosessen.

Optimalisering av gjennomstrømning ved hjelp av dynamisk batching

Så langt har vi bare snakket om en enkelt inngang. I praksis forventer vi å håndtere flere forespørsler som kommer inn tilfeldig fra applikasjonsklientene for slutninger samtidig eller på en forskjøvet måte. På tradisjonell måte kan grunnleggende batching brukes til å øke gjennomstrømningen og utnyttelsen av dataressursene til GPU. Batching kombinerer effektivt de numeriske representasjonene av mer enn én forespørsel i en batch og utfører parallelle kjøringer av autoregressive foroverpasninger. Denne intelligente batchingen gjøres på serveringssiden. SageMaker LMIs DJLServing-server kan konfigureres til å sette sammen flere forespørsler for å behandle dem parallelt ved å sette følgende parametere i serveringsegenskaper:

Dette viser i utgangspunktet at DJLServing vil stille forespørsler i kø i 100 millisekunder om gangen, eller hvis antallet forespørsler som står i kø er opp til den spesifiserte batch_size, vil batchen bli planlagt til å kjøre til backend for slutning. Dette er kjent som dynamic batching. Det er dynamisk fordi batchstørrelsen kan endres på tvers av batcher avhengig av hvor mange forespørsler som ble lagt til i løpet av den tidsperioden. Men fordi forespørsler kan ha forskjellige egenskaper (for eksempel kan noen forespørsler ha formen 20 tokens for input og 500 tokens of output, mens andre kan bli reversert, med 500 tokens for input, men bare 20 for output), kan noen forespørsler fullføre behandlingen raskere enn andre i samme batch. Dette kan føre til underutnyttelse av GPU-en mens du venter på at alle forespørsler under flyvningen i batchen skal fullføre dekodingsstadiet, selv om det er flere forespørsler som venter på å bli behandlet i køen. Følgende diagram illustrerer denne prosessen.

Enkel Dynamisk Batching Visual

Dynamic Batching Visual – legg merke til de inaktive vinduene på slutten av forespørsel 2 og 3

Optimalisering av gjennomstrømning ved hjelp av kontinuerlig batching

Med continuous batching, også kjent som iterative or rolling batching, drar vi nytte av forskjellene mellom forhåndsfyllings- og dekodetrinnene. For å aktivere kontinuerlig batching tilbyr DJServing følgende tilleggskonfigurasjoner i henhold til servering.properties:

  • motor=MPI – Vi oppfordrer deg til å bruke MPI-motoren for kontinuerlig batching.
  • option.rolling_batch=auto eller lmi-dist – Vi anbefaler å bruke auto fordi den automatisk vil velge den mest passende rullende batchalgoritmen sammen med andre optimaliseringer i fremtiden.
  • option.max_rolling_batch_size=32 – Dette begrenser antall samtidige forespørsler. Standard er 32.

Med kontinuerlig batching venter ikke serveringsstakken (DJLServing) på at alle forespørsler ombord i en batch skal fullføre dekodefasen. Snarere, ved logiske pauser (på slutten av én iterasjon i dekodingsstadiet), trekker den inn ytterligere forespørsler som venter i køen mens gjeldende batch fortsatt behandles (derav navnet rullende parti). Den sjekker for ventende forespørsler på slutten av hver iterasjon av dekodingsstadiet. Husk at for hver forespørsel må vi kjøre forhåndsutfyllingsstadiet etterfulgt av det sekvensielle dekodingsstadiet. Fordi vi kan behandle alle tokens fra den første forespørselen til en forespørsel parallelt for forhåndsutfyllingsstadiet, når en ny forespørsel trekkes inn, stanser vi midlertidig dekodingsstadiet for forespørsler under flyvningen til batchen – vi lagrer KV-cachen midlertidig. og aktiveringer i minnet og kjøre forhåndsutfyllingsstadiet for de nye forespørslene.

Størrelsen på denne hurtigbufferen kan konfigureres med følgende alternativ:

Når forhåndsutfyllingen er fullført, kombinerer vi de nye forespørslene og de gamle midlertidige forespørslene i en ny rullende batch, som kan fortsette med dekodingsfasen deres parallelt. Vær oppmerksom på at de gamle midlertidig stoppede forespørslene kan fortsette sitt dekodingsstadium der de slapp, og de nye forespørslene vil starte fra deres første nye token.

Kontinuerlig eller iterativ gruppevisuelt

Kontinuerlig eller iterativ batching Visuelt – legg merke til at tomgangstidene erstattes med følge på forespørsler

Du har kanskje allerede innsett at kontinuerlig batching er en nesten lik tilnærming som vi naturlig paralleliserer oppgaver i hverdagen. Vi har meldinger, e-poster, telefonvarsler (potensielt nye forespørsler) som kommer inn på tilfeldige tidspunkter (analogt med flere forespørsler som kommer på en tilfeldig forskjøvet måte for GPUer). Alt dette skjer mens vi fullfører oppgavene våre ombord – skrive e-poster, kode, delta i møter (analogt med de for øyeblikket behandlende oppgavene i GPU-ene). Ved logiske pauser pauser vi oppgavene våre under flyet og sjekker varslene våre for å avgjøre om det er noe som kreves fra vår side, og hvis det er det, legger vi det til oppgavene våre under flygingen (real-life rullende batch), eller sette den på en huskeliste (køen).

Sette alt sammen: Hvordan tenke på minneutnyttelse av GPUer

Det anbefales å lastetest modellen din for å se hvilken konfigurasjon som er mest kostnadseffektiv for ditt forretningsbruk. For å bygge en forståelse, la oss visualisere minnefotavtrykket til GPU-ene når modellen lastes inn og etter hvert som påfølgende forespørsler behandles i en rullende batch. For dette innlegget, la oss anta at vi laster Falcon-40B-modellen på en av G5-forekomsttypene som er installert med NVIDIA A10G GPUer, hver med 24 GB minne. Merk at en lignende forståelse gjelder for instanstypene p3, p4 og p5, som følger med V100, A100 og H100 GPU-seriene.

Følgende er oversikten over å få en omtrentlig verdi av totalt minne som kreves for å betjene Falcon-40B:

  • Modellstørrelse = Antall modellparametere (40 milliarder for Falcon-40B) x 4 byte per parameter (for FP32) = 160 GB
  • Omtrentlig totalt minne som kreves for å laste Falcon-40B for slutning = Modellstørrelse (=160 GB) + KV-buffer (oppmerksomhetsbuffer) (=*20 GB) + Ekstra minneoverhead av ML Frameworks (omtrent 2 GB)
Minne Visuelt

Memory Visual – Forstå minnefotavtrykket til en lastet Falcon-40B-modell

For Falcon-40B, hvis vi komprimerer modellen ved å kvantisere modellen til datatypen bfloat16 (2 byte), blir modellstørrelsen omtrent 80 GB. Som du kan se, er dette fortsatt større enn minnet som støttes av en akseleratorenhet, så vi må ta i bruk en modellpartisjoneringsteknikk (sharding) med en spesiell tensorparallellisme (TP) nærmer seg og skjærer modellen på tvers av flere akseleratorenheter. La oss anta at vi har valgt g5.24xlarge, som har 4 A10G GPU-enheter. Hvis vi konfigurerer DJLServing (serving.properties) med følgende, kan vi forvente at 80 GB med modellvekter vil bli delt likt på alle 4 GPUer:

Med tensor_parallel_degree satt til 4, er omtrent 20 GB av 24 GB GPU-minnet (omtrent 84 %) allerede brukt selv før en enkelt forespørsel er behandlet. De resterende 16 % av GPUen vil bli brukt til KV-cachen for de innkommende forespørslene. Det er mulig at 2–3 GB av det gjenværende minnet er mer enn nok for forretningsscenarioet ditt og dets latens- og gjennomstrømningskrav. Hvis ikke, kan du øke forekomststørrelsen til g5.48xlarge, som har 8 GPUer og bruker tensor_parallel_degree satt til 8. I et slikt tilfelle blir bare omtrent 10 GB av det tilgjengelige 24 GB minnet til hver GPU brukt for modellvekter, og vi har omtrent 60 % av gjenværende GPU for aktiveringene og KV-cachen. Intuitivt kan vi se at denne konfigurasjonen kan tillate oss å ha en høyere gjennomstrømning. I tillegg, fordi vi har en større buffer nå, kan vi øke max_rolling_batch_prefill_tokens og max_rolling_batch_size parametere for å optimalisere gjennomstrømningen ytterligere. Sammen vil disse to parameterne kontrollere forhåndstildelingene av aktiveringsprefillene og KV-bufferen for modellen. Et større tall for disse to parameterne vil samrelatere til en større gjennomstrømning, forutsatt at du har nok buffer for KV-cachen i GPU-minnet.

Kontinuerlig batching med PagedAttention

PagedAttention er en ny optimaliseringsalgoritme utviklet av UC Berkeley som forbedrer den kontinuerlige batchprosessen ved å la oppmerksomhetsbufferen (KV-cache) være ikke-sammenhengende ved å allokere minne i sider eller blokker med fast størrelse. Dette er inspirert av virtuelt minne og personsøkingskonsepter som brukes av operativsystemer.

I henhold til vLLM papir, blir oppmerksomhetsbufferen til hver sekvens av tokens delt inn i blokker og tilordnet fysiske blokker gjennom en blokktabell. Under beregningen av oppmerksomhet kan en PagedAttention-kjerne bruke blokktabellen for å effektivt hente blokkene fra det fysiske minnet. Dette resulterer i en betydelig reduksjon av minnesløsing og gir mulighet for større batchstørrelse, økt GPU-utnyttelse og høyere gjennomstrømning.

Ytelse sammenligning

For å sikre effektiv belastningstesting av distribusjonskonfigurasjonen din, anbefales det å begynne med å vurdere forretningsscenarioet og tydelig definere egenskapene til input og output for den LLM-baserte applikasjonen. Hvis du for eksempel jobber med en brukssak for oppsummering av kundesenter, kan inndata bestå av større tekst, for eksempel en 500-tokens chat-utskrift mellom en kundeserviceagent og en kunde, men utdataene kan være relativt mindre, rundt 100 tokens, som representerer et sammendrag av transkripsjonen. På den annen side, hvis du jobber med et kodegenereringsscenario, kan inngangen være så kort som 15 tokens, som "skriv en effektiv implementering i Python for å beskrive alle EC2-ressurser, inkludert paginering," men utdataene kan være mye større og når 500 tokens. Det er også viktig å vurdere om oppnåelse av lavere ventetid eller maksimering av gjennomstrømming er toppprioritet for ditt spesifikke scenario.

Etter å ha fått en omfattende forståelse av forretningsscenarioet, kan du analysere og bestemme den optimale konfigurasjonen for ditt vertsmiljø. I denne sammenhengen omfatter vertsmiljøet ulike nøkkelelementer, inkludert instanstypen og andre konfigurasjonsparametere som f.eks. tensor_parallell_grad, max_rolling_batch_size, max_rolling_batch_prefill_tokens, og mer. Målet vårt er å identifisere det mest effektive oppsettet for å støtte våre krav til responstid, gjennomstrømning og modellutdatakvalitet.

I vår analyse har vi sammenlignet ytelsen for å illustrere fordelene med kontinuerlig batching fremfor tradisjonell dynamisk batching. Vi brukte konfigurasjonene beskrevet i følgende tabell i serving.properties for dynamisk batching og iterativ batching, ved å bruke en LMI-beholder på SageMaker.

Dynamisk batching Kontinuerlig batching Kontinuerlig batching 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 = true

motor = MPI

option.model_id = {{s3_url}}

option.trust_remote_code = true

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 = Falsk

motor = MPI

option.model_id = {{s3_url}}

option.trust_remote_code = true

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 to konfigurasjonene ble benchmarked for Falcon-40B med FP16-datatypen utplassert på ml.g5.48xlarge i et par forskjellige scenarier som representerer virkelige applikasjoner:

  • Et lite antall input-tokens med et stort antall tokens som genereres – I dette scenariet ble antall input-tokens fastsatt til 32 og 128 nye tokens ble generert
Batching-strategi Gjennomstrømning (tokens/sek.) Latens p90 (sek.)
Dynamisk batching 5.53 58.34
Kontinuerlig batching 56.04 4.74
Kontinuerlig batching med PagedAttention 59.18 4.76
  • En stor inngang med et lite antall tokens som genereres – Her fikser vi antall input-tokens til 256 og ber LLM om å oppsummere inndataene til 32 tokens
Batching-strategi Gjennomstrømning (tokens/sek.) Latens p90 (sek.)
Dynamisk batching 19.96 59.31
Kontinuerlig batching 46.69 3.88
Kontinuerlig batching med PagedAttention 44.75 2.67

Vi kan se at kontinuerlig batching med PagedAttention gir en gjennomstrømsforbedring på 10 ganger større i scenario 1 og 2.3 ganger i scenario 2 sammenlignet med å bruke dynamisk batching på SageMaker mens du bruker LMI-beholderen.

konklusjonen

I dette innlegget så vi på hvordan LLM-er bruker minne og forklarte hvordan kontinuerlig batching forbedrer gjennomstrømningen ved å bruke en LMI-beholder på SageMaker. Vi demonstrerte fordelene med kontinuerlig batching for Falcon-40B ved å bruke en LMI-beholder på SageMaker ved å vise referanseresultater. Du finner koden på GitHub repo.


Om forfatterne

Abhigyan ShivadityaAbhi Shivaditya er en senior løsningsarkitekt hos AWS, og jobber med strategiske globale bedriftsorganisasjoner for å lette bruken av AWS-tjenester på områder som kunstig intelligens, distribuert databehandling, nettverk og lagring. Hans ekspertise ligger i Deep Learning innen domenene Natural Language Processing (NLP) og Computer Vision. Abhi hjelper kunder med å implementere høyytelses maskinlæringsmodeller effektivt innenfor AWS-økosystemet.

Forbedre ytelsen til Falcon-modeller med Amazon SageMaker | Amazon Web Services PlatoBlockchain Data Intelligence. Vertikalt søk. Ai.Dhawal Patel er en hovedmaskinlæringsarkitekt ved AWS. Han har jobbet med organisasjoner som spenner fra store bedrifter til mellomstore startups med problemer knyttet til distribuert databehandling og kunstig intelligens. Han fokuserer på dyp læring inkludert NLP- og Computer Vision-domener. Han hjelper kundene med å oppnå høy ytelse modellslutning på SageMaker.

Forbedre ytelsen til Falcon-modeller med Amazon SageMaker | Amazon Web Services PlatoBlockchain Data Intelligence. Vertikalt søk. Ai.Pinak Panigrahi jobber med kunder for å bygge maskinlæringsdrevne løsninger for å løse strategiske forretningsproblemer på AWS. Når han ikke er opptatt med maskinlæring, kan han bli funnet å ta en fottur, lese en bok eller se på sport.

Forbedre ytelsen til Falcon-modeller med Amazon SageMaker | Amazon Web Services PlatoBlockchain Data Intelligence. Vertikalt søk. Ai.Abhi Sodhani har stillingen som Senior AI/ML Solutions Architect hos AWS, hvor han spesialiserer seg på å tilby teknisk ekspertise og veiledning om Generative AI og ML løsninger til kunder. Hans primære fokus er å hjelpe Digital Native Businesses med å realisere det fulle potensialet til Generative AI- og ML-teknologier, slik at de kan nå sine forretningsmål effektivt. Utover sine profesjonelle bestrebelser, viser Abhi en sterk lidenskap for intellektuelle sysler som lesing, i tillegg til å delta i aktiviteter som fremmer fysisk og mentalt velvære, som yoga, meditasjon.

Forbedre ytelsen til Falcon-modeller med Amazon SageMaker | Amazon Web Services PlatoBlockchain Data Intelligence. Vertikalt søk. Ai.Qing Lan er en programvareutviklingsingeniør i AWS. Han har jobbet med flere utfordrende produkter i Amazon, inkludert høyytelses ML-slutningsløsninger og høyytelses loggingssystem. Qings team lanserte den første milliardparametermodellen i Amazon Advertising med svært lav ventetid. Qing har inngående kunnskap om infrastrukturoptimalisering og Deep Learning-akselerasjon.

Tidstempel:

Mer fra AWS maskinlæring