Evaluați și optimizați implementarea punctelor finale în Amazon SageMaker JumpStart | Amazon Web Services

Evaluați și optimizați implementarea punctelor finale în Amazon SageMaker JumpStart | Amazon Web Services

Atunci când implementează un model de limbaj mare (LLM), practicienilor de învățare automată (ML) le pasă de obicei de două măsurători pentru performanța de servire a modelului: latența, definită de timpul necesar pentru a genera un singur token, și debitul, definit de numărul de token-uri generate. pe secunda. Deși o singură cerere către punctul final implementat ar prezenta un debit aproximativ egal cu inversul latenței modelului, acesta nu este neapărat cazul când mai multe cereri concurente sunt trimise simultan către punctul final. Datorită tehnicilor de servire a modelelor, cum ar fi lotul continuu pe partea client a cererilor concurente, latența și debitul au o relație complexă care variază semnificativ în funcție de arhitectura modelului, configurațiile de servire, hardware-ul tipului de instanță, numărul de solicitări simultane și variațiile în încărcăturile utile de intrare, cum ar fi ca număr de jetoane de intrare și jetoane de ieșire.

Această postare explorează aceste relații printr-o evaluare comparativă cuprinzătoare a LLM-urilor disponibile în Amazon SageMaker JumpStart, inclusiv variantele Llama 2, Falcon și Mistral. Cu SageMaker JumpStart, practicienii ML pot alege dintr-o selecție largă de modele de fundație disponibile public pentru a le implementa în programe dedicate. Amazon SageMaker instanțe într-un mediu izolat de rețea. Oferim principii teoretice despre modul în care specificațiile acceleratoarelor influențează evaluarea comparativă a LLM. Demonstrăm, de asemenea, impactul implementării mai multor instanțe în spatele unui singur punct final. În cele din urmă, oferim recomandări practice pentru adaptarea procesului de implementare SageMaker JumpStart pentru a se alinia cu cerințele dumneavoastră privind latența, debitul, costul și constrângerile pentru tipurile de instanțe disponibile. Toate rezultatele benchmarking-ului, precum și recomandările se bazează pe un versatil caiet pe care le puteți adapta la cazul dvs. de utilizare.

Evaluare comparativă a punctelor finale implementate

Următoarea figură arată cele mai mici latențe (stânga) și cele mai mari valori de debit (dreapta) pentru configurațiile de implementare într-o varietate de tipuri de model și tipuri de instanțe. Este important că fiecare dintre aceste implementări de model utilizează configurații implicite, așa cum sunt furnizate de SageMaker JumpStart, având în vedere ID-ul de model și tipul de instanță dorit pentru implementare.

Evaluați și optimizați implementarea punctelor finale în Amazon SageMaker JumpStart | Amazon Web Services PlatoBlockchain Data Intelligence. Căutare verticală. Ai.

Aceste valori de latență și debit corespund sarcinilor utile cu 256 de jetoane de intrare și 256 de jetoane de ieșire. Configurația cu cea mai mică latență limitează servirea modelului la o singură cerere concomitentă, iar configurația cu cea mai mare latență maximizează numărul posibil de cereri simultane. După cum putem vedea în benchmarking-ul nostru, creșterea cererilor simultane mărește monoton debitul cu îmbunătățiri diminuate pentru cererile simultane mari. În plus, modelele sunt complet fragmentate pe instanța acceptată. De exemplu, deoarece instanța ml.g5.48xlarge are 8 GPU-uri, toate modelele SageMaker JumpStart care utilizează această instanță sunt fragmentate folosind paralelismul tensorului pe toate cele opt acceleratoare disponibile.

Putem observa câteva concluzii din această cifră. În primul rând, nu toate modelele sunt acceptate pe toate instanțele; unele modele mai mici, cum ar fi Falcon 7B, nu acceptă fragmentarea modelului, în timp ce modelele mai mari au cerințe mai mari de resurse de calcul. În al doilea rând, pe măsură ce sharding-ul crește, performanța se îmbunătățește de obicei, dar s-ar putea să nu se îmbunătățească neapărat pentru modelele miciAcest lucru se datorează faptului că modelele mici, cum ar fi 7B și 13B, implică o suprasolicitare substanțială de comunicare atunci când sunt fragmentate pe prea multe acceleratoare. Vom discuta despre acest lucru mai în profunzime mai târziu. În cele din urmă, instanțele ml.p4d.24xlarge tind să aibă un randament semnificativ mai bun datorită îmbunătățirii lățimii de bandă a memoriei A100 față de GPU-urile A10G. După cum vom discuta mai târziu, decizia de a utiliza un anumit tip de instanță depinde de cerințele dvs. de implementare, inclusiv de latența, debitul și constrângerile de cost.

Cum puteți obține aceste valori de configurare a celei mai mici latențe și a celei mai mari valori de debit? Să începem prin a trasa latența față de debit pentru un punct final Llama 2 7B pe o instanță ml.g5.12xlarge pentru o sarcină utilă cu 256 de jetoane de intrare și 256 de jetoane de ieșire, așa cum se vede în curba următoare. O curbă similară există pentru fiecare punct final LLM implementat.

Evaluați și optimizați implementarea punctelor finale în Amazon SageMaker JumpStart | Amazon Web Services PlatoBlockchain Data Intelligence. Căutare verticală. Ai.

Pe măsură ce concurența crește, debitul și latența cresc și ele în mod monoton. Prin urmare, cel mai scăzut punct de latență are loc la o valoare a cererii simultane de 1 și puteți crește eficient din punct de vedere al costurilor debitul sistemului prin creșterea cererilor concurente. Există un „genunchi” distinct în această curbă, unde este evident că câștigurile de debit asociate concurenței suplimentare nu depășesc creșterea asociată a latenței. Locația exactă a acestui genunchi este specifică cazului; unii practicieni pot defini genunchiul în punctul în care o cerință de latență prespecificată este depășită (de exemplu, 100 ms/token), în timp ce alții pot folosi repere de testare a sarcinii și metode teorie de așteptare, cum ar fi regula semi-latenței, iar alții pot folosi specificațiile teoretice ale acceleratorului.

De asemenea, menționăm că numărul maxim de solicitări simultane este limitat. În figura anterioară, trasarea liniei se termină cu 192 de solicitări concurente. Sursa acestei limitări este limita de expirare a invocării SageMaker, unde SageMaker limitează un răspuns la invocare după 60 de secunde. Această setare este specifică contului și nu poate fi configurată pentru un punct final individual. Pentru LLM, generarea unui număr mare de jetoane de ieșire poate dura secunde sau chiar minute. Prin urmare, sarcinile utile mari de intrare sau de ieșire pot duce la eșecul cererilor de invocare. În plus, dacă numărul de solicitări simultane este foarte mare, atunci multe solicitări vor avea timpi mari de coadă, ceea ce duce la această limită de timeout de 60 de secunde. În scopul acestui studiu, folosim limita de timeout pentru a defini debitul maxim posibil pentru implementarea unui model. Este important, deși un punct final SageMaker poate gestiona un număr mare de solicitări concurente fără a respecta un timp de expirare a răspunsului la invocare, este posibil să doriți să definiți solicitări concurente maxime în ceea ce privește genunchiul în curba de latență-debit. Acesta este probabil punctul în care începeți să luați în considerare scalarea orizontală, în care un singur punct final furnizează mai multe instanțe cu replici de model și echilibrează sarcina cererilor primite între replici, pentru a suporta mai multe cereri concurente.

Făcând acest pas mai departe, următorul tabel conține rezultate de analiză comparativă pentru diferite configurații pentru modelul Llama 2 7B, inclusiv număr diferit de jetoane de intrare și ieșire, tipuri de instanțe și număr de solicitări concurente. Rețineți că figura anterioară reprezintă doar un singur rând din acest tabel.

. Debit (jetoane/sec) Latență (ms/token)
Cereri concurente 1 2 4 8 16 32 64 128 256 512 1 2 4 8 16 32 64 128 256 512
Număr total de jetoane: 512, Număr de jetoane de ieșire: 256
ml.g5.2xmare 30 54 115 208 343 475 486 - - - 33 33 35 39 48 97 159 - - -
ml.g5.12xmare 59 117 223 406 616 866 1098 1214 - - 17 17 18 20 27 38 60 112 - -
ml.g5.48xmare 56 108 202 366 522 660 707 804 - - 18 18 19 22 32 50 101 171 - -
ml.p4d.24xlarge 49 85 178 353 654 1079 1544 2312 2905 2944 21 23 22 23 26 31 44 58 92 165
Număr total de jetoane: 4096, Număr de jetoane de ieșire: 256
ml.g5.2xmare 20 36 48 49 - - - - - - 48 57 104 170 - - - - - -
ml.g5.12xmare 33 58 90 123 142 - - - - - 31 34 48 73 132 - - - - -
ml.g5.48xmare 31 48 66 82 - - - - - - 31 43 68 120 - - - - - -
ml.p4d.24xlarge 39 73 124 202 278 290 - - - - 26 27 33 43 66 107 - - - -

Observăm câteva modele suplimentare în aceste date. La creșterea dimensiunii contextului, latența crește și debitul scade. De exemplu, pe ml.g5.2xlarge cu o concurență de 1, debitul este de 30 de jetoane/sec când numărul total de jetoane este de 512, față de 20 de jetoane/sec dacă numărul total de jetoane este 4,096. Acest lucru se datorează faptului că este nevoie de mai mult timp pentru a procesa intrarea mai mare. Putem vedea, de asemenea, că creșterea capacității GPU și sharding-ul afectează debitul maxim și cererile simultane maxime acceptate. Tabelul arată că Llama 2 7B are valori de debit maxim diferite în mod semnificativ pentru diferite tipuri de instanțe, iar aceste valori de debit maxim apar la valori diferite ale cererilor concurente. Aceste caracteristici l-ar determina pe un practician ML să justifice costul unei instanțe față de alta. De exemplu, având în vedere o cerință de latență scăzută, practicantul poate selecta o instanță ml.g5.12xlarge (4 GPU-uri A10G) peste o instanță ml.g5.2xlarge (1 GPU A10G). Dacă i se oferă o cerință de debit mare, utilizarea unei instanțe ml.p4d.24xlarge (8 GPU-uri A100) cu fragmentare completă ar fi justificată doar în condiții de concurență ridicată. Rețineți, totuși, că este adesea benefic să încărcați mai multe componente de inferență ale unui model 7B pe o singură instanță ml.p4d.24xlarge; un astfel de suport pentru mai multe modele este discutat mai târziu în această postare.

Observațiile precedente au fost făcute pentru modelul Llama 2 7B. Cu toate acestea, modele similare rămân valabile și pentru alte modele. O concluzie principală este că numerele de performanță ale latenței și debitului depind de sarcina utilă, tipul instanței și numărul de solicitări concurente, așa că va trebui să găsiți configurația ideală pentru aplicația dvs. specifică. Pentru a genera numerele precedente pentru cazul dvs. de utilizare, puteți rula linkul caiet, unde puteți configura această analiză a testului de încărcare pentru modelul dvs., tipul de instanță și sarcina utilă.

Înțelegerea specificațiilor acceleratorului

Selectarea hardware-ului potrivit pentru inferența LLM se bazează în mare măsură pe cazuri de utilizare specifice, obiectivele experienței utilizatorului și LLM-ul ales. Această secțiune încearcă să creeze o înțelegere a genunchiului în curba de latență-debit cu privire la principiile de nivel înalt bazate pe specificațiile acceleratorului. Aceste principii singure nu sunt suficiente pentru a lua o decizie: sunt necesare repere reale. Termenul dispozitiv este folosit aici pentru a cuprinde toate acceleratoarele hardware ML. Afirmăm că genunchiul în curba de latență-debit este determinat de unul dintre cei doi factori:

  • Acceleratorul a epuizat memoria pentru a stoca în cache matricele KV, astfel încât solicitările ulterioare sunt puse în coadă
  • Acceleratorul are încă memorie de rezervă pentru memoria cache KV, dar utilizează o dimensiune a lotului suficient de mare încât timpul de procesare este determinat de latența operației de calcul, mai degrabă decât de lățimea de bandă a memoriei

De obicei, preferăm să fim limitați de cel de-al doilea factor, deoarece acest lucru înseamnă că resursele acceleratorului sunt saturate. Practic, maximizezi resursele pentru care ai plătit. Să explorăm această afirmație mai detaliat.

Cache KV și memorie dispozitiv

Mecanismele standard de atenție a transformatorului calculează atenția pentru fiecare jeton nou față de toate jetonele anterioare. Cele mai multe servere ML moderne memorează cheile și valorile de atenție în memoria dispozitivului (DRAM) pentru a evita recalcularea la fiecare pas. Aceasta se numește asta Cache KVși crește cu dimensiunea lotului și lungimea secvenței. Acesta definește câte solicitări de utilizator pot fi servite în paralel și va determina genunchiul în curba de latență-debit dacă regimul de calcul din cel de-al doilea scenariu menționat mai devreme nu este încă îndeplinit, având în vedere DRAM-ul disponibil. Următoarea formulă este o aproximare aproximativă pentru dimensiunea maximă a memoriei cache KV.

Evaluați și optimizați implementarea punctelor finale în Amazon SageMaker JumpStart | Amazon Web Services PlatoBlockchain Data Intelligence. Căutare verticală. Ai.

În această formulă, B este dimensiunea lotului și N este numărul de acceleratori. De exemplu, modelul Llama 2 7B în FP16 (2 octeți/parametru) servit pe un GPU A10G (24 GB DRAM) consumă aproximativ 14 GB, lăsând 10 GB pentru memoria cache KV. Introducând lungimea completă a contextului modelului (N = 4096) și parametrii rămași (n_layers=32, n_kv_attention_heads=32 și d_attention_head=128), această expresie arată că suntem limitați la deservirea unui lot de patru utilizatori în paralel din cauza constrângerilor DRAM . Dacă observați reperele corespunzătoare din tabelul anterior, aceasta este o bună aproximare pentru genunchiul observat în această curbă de latență-debit. Metode precum atenție grupată la interogare (GQA) poate reduce dimensiunea cache-ului KV, în cazul GQA cu același factor reduce numărul de capete KV.

Intensitatea aritmetică și lățimea de bandă a memoriei dispozitivului

Creșterea puterii de calcul a acceleratoarelor ML a depășit lățimea de bandă a memoriei, ceea ce înseamnă că pot efectua mult mai multe calcule pe fiecare octet de date în timpul necesar pentru a accesa acel octet.

intensitatea aritmetică, sau raportul dintre operațiunile de calcul și accesele la memorie, pentru o operație determină dacă este limitată de lățimea de bandă a memoriei sau de capacitatea de calcul pe hardware-ul selectat. De exemplu, un GPU A10G (familie de tip de instanță g5) cu 70 TFLOPS FP16 și 600 GB/sec lățime de bandă poate calcula aproximativ 116 operațiuni/octet. Un GPU A100 (familie de tip de instanță p4d) poate calcula aproximativ 208 operațiuni/octet. Dacă intensitatea aritmetică pentru un model de transformator este sub acea valoare, este legată de memorie; dacă este deasupra, este legat de calcul. Mecanismul de atenție pentru Llama 2 7B necesită 62 de operațiuni/octet pentru dimensiunea lotului 1 (pentru o explicație, vezi Un ghid pentru inferența și performanța LLM), ceea ce înseamnă că este legat de memorie. Când mecanismul de atenție este legat de memorie, FLOPS-urile scumpe sunt lăsate neutilizate.

Există două moduri de a utiliza mai bine acceleratorul și de a crește intensitatea aritmetică: reduceți accesele necesare la memorie pentru operație (acesta este ceea ce FlashAtenție se concentrează pe) sau crește dimensiunea lotului. Cu toate acestea, este posibil să nu putem crește suficient de mult dimensiunea lotului pentru a ajunge la un regim de calcul, dacă DRAM-ul nostru este prea mic pentru a păstra memoria cache KV corespunzătoare. O aproximare brută a dimensiunii critice a lotului B* care separă regimurile legate de calcul de cele legate de memorie pentru inferența standard de decodor GPT este descrisă de următoarea expresie, unde A_mb este lățimea de bandă a memoriei acceleratorului, A_f este FLOPS acceleratorului și N este numărul a acceleratoarelor. Această dimensiune critică a lotului poate fi derivată prin găsirea în care timpul de acces la memorie este egal cu timpul de calcul. A se referi la acest blog pentru a înțelege mai detaliat ecuația 2 și ipotezele acesteia.

Evaluați și optimizați implementarea punctelor finale în Amazon SageMaker JumpStart | Amazon Web Services PlatoBlockchain Data Intelligence. Căutare verticală. Ai.

Acesta este același raport operațiuni/octeți pe care l-am calculat anterior pentru A10G, deci dimensiunea lotului critic pe acest GPU este de 116. O modalitate de a aborda această dimensiune teoretică, critică a lotului este de a crește fragmentarea modelului și de a împărți memoria cache pe mai multe N acceleratoare. Acest lucru crește efectiv capacitatea de cache KV, precum și dimensiunea lotului legat de memorie.

Un alt beneficiu al fragmentării modelului este împărțirea parametrilor modelului și a activității de încărcare a datelor pe N acceleratoare. Acest tip de sharding este un tip de paralelism de model denumit și paralelism tensor. În mod naiv, există de N ori lățimea de bandă a memoriei și puterea de calcul în agregat. Presupunând că nu există nicio suprasarcină (comunicare, software și așa mai departe), acest lucru ar scădea latența de decodificare per token cu N dacă suntem legați de memorie, deoarece latența de decodificare a jetonului în acest regim este limitată de timpul necesar pentru încărcarea modelului. greutăți și cache. În viața reală, totuși, creșterea gradului de fragmentare are ca rezultat o comunicare crescută între dispozitive pentru a partaja activări intermediare la fiecare strat de model. Această viteză de comunicare este limitată de lățimea de bandă de interconectare a dispozitivului. Este dificil să-i estimezi impactul cu precizie (pentru detalii, vezi Paralelismul modelului), dar acest lucru poate înceta în cele din urmă să producă beneficii sau să deterioreze performanța - acest lucru este valabil mai ales pentru modelele mai mici, deoarece transferurile de date mai mici duc la rate de transfer mai mici.

Pentru a compara acceleratoarele ML pe baza specificațiilor lor, vă recomandăm următoarele. Mai întâi, calculați dimensiunea aproximativă a lotului critic pentru fiecare tip de accelerator conform celei de-a doua ecuații și dimensiunea memoriei cache KV pentru dimensiunea lotului critic conform primei ecuații. Apoi puteți utiliza DRAM-ul disponibil pe accelerator pentru a calcula numărul minim de acceleratoare necesare pentru a se potrivi în memoria cache KV și parametrii modelului. Dacă decideți între mai multe acceleratoare, acordați prioritate acceleratoarelor în ordinea costului cel mai mic pe GB/sec de lățime de bandă a memoriei. În cele din urmă, comparați aceste configurații și verificați care este cel mai bun cost/token pentru limita superioară a latenței dorite.

Selectați o configurație de implementare a punctului final

Multe LLM-uri distribuite de SageMaker JumpStart folosesc text-generare-inferență (TGI) Container SageMaker pentru servirea modelului. Următorul tabel discută cum să ajustați o varietate de parametri de servire a modelului fie pentru a afecta difuzarea modelului, care are un impact asupra curbei de latență-debit, fie pentru a proteja punctul final împotriva solicitărilor care ar supraîncărca punctul final. Aceștia sunt parametrii principali pe care îi puteți utiliza pentru a configura implementarea punctului final pentru cazul dvs. de utilizare. Dacă nu se specifică altfel, folosim implicit parametrii sarcinii utile pentru generarea de text și Variabilele de mediu TGI.

Variabilă de mediu Descriere SageMaker JumpStart Valoare implicită
Configurații de servire a modelului . .
MAX_BATCH_PREFILL_TOKENS Limitează numărul de jetoane în operația de precompletare. Această operație generează memoria cache KV pentru o nouă secvență de prompt de intrare. Este intensiv în memorie și este legat de calcul, astfel încât această valoare limitează numărul de jetoane permise într-o singură operațiune de pre-completare. Pașii de decodare pentru alte interogări se întrerup în timp ce are loc completarea preliminară. 4096 (implicit TGI) sau lungimea contextului maxim acceptată specifică modelului (SageMaker JumpStart furnizat), oricare dintre acestea este mai mare.
MAX_BATCH_TOTAL_TOKENS Controlează numărul maxim de jetoane de inclus într-un lot în timpul decodării sau o singură trecere înainte prin model. În mod ideal, acesta este setat pentru a maximiza utilizarea întregului hardware disponibil. Nu este specificat (implicit TGI). TGI va seta această valoare cu privire la memoria CUDA rămasă în timpul încălzirii modelului.
SM_NUM_GPUS Numărul de fragmente de utilizat. Adică, numărul de GPU-uri utilizate pentru a rula modelul folosind paralelismul tensor. Dependent de instanță (furnizat SageMaker JumpStart). Pentru fiecare instanță acceptată pentru un model dat, SageMaker JumpStart oferă cea mai bună setare pentru paralelismul tensorului.
Configurații pentru a vă proteja punctul final (setați-le pentru cazul dvs. de utilizare) . .
MAX_TOTAL_TOKENS Aceasta limitează bugetul de memorie al unei singure cereri de client prin limitarea numărului de jetoane din secvența de intrare plus numărul de jetoane din secvența de ieșire ( max_new_tokens parametrul de sarcină utilă). Lungimea contextului maxim acceptată specifică modelului. De exemplu, 4096 pentru Llama 2.
MAX_INPUT_LENGTH Identifică numărul maxim permis de jetoane în secvența de intrare pentru o singură cerere client. Lucrurile de luat în considerare la creșterea acestei valori includ: secvențele de intrare mai lungi necesită mai multă memorie, ceea ce afectează loturile continue și multe modele au o lungime de context acceptată care nu trebuie depășită. Lungimea contextului maxim acceptată specifică modelului. De exemplu, 4095 pentru Llama 2.
MAX_CONCURRENT_REQUESTS Numărul maxim de solicitări simultane permise de punctul final implementat. Noile solicitări dincolo de această limită vor genera imediat o eroare de supraîncărcare a modelului pentru a preveni o latență slabă pentru cererile curente de procesare. 128 (implicit TGI). Această setare vă permite să obțineți un randament ridicat pentru o varietate de cazuri de utilizare, dar ar trebui să fixați după caz ​​pentru a atenua erorile de expirare a timpului de invocare SageMaker.

Serverul TGI utilizează loturi continue, care grupează în mod dinamic cererile simultane pentru a partaja o singură trecere înainte de inferență de model. Există două tipuri de treceri înainte: pre-completare și decodare. Fiecare cerere nouă trebuie să ruleze o singură trecere înainte de completare preliminară pentru a popula memoria cache KV pentru indicatoarele de secvență de intrare. După ce memoria cache KV este populată, o trecere înainte de decodare realizează o singură predicție pentru tokenul următor pentru toate cererile grupate, care este repetată iterativ pentru a produce secvența de ieșire. Pe măsură ce noi solicitări sunt trimise către server, următorul pas de decodare trebuie să aștepte, astfel încât pasul de precompletare să poată rula pentru noile solicitări. Acest lucru trebuie să se întâmple înainte ca acele noi solicitări să fie incluse în pașii de decodare ulterioare, grupați continuu. Din cauza constrângerilor hardware, lotul continuu utilizat pentru decodare poate să nu includă toate solicitările. În acest moment, cererile intră într-o coadă de procesare și latența de inferență începe să crească semnificativ cu doar un câștig minor de debit.

Este posibil să se separe analizele de evaluare comparativă a latenței LLM în latența de precompletare, latența de decodare și latența cozii. Timpul consumat de fiecare dintre aceste componente este fundamental diferit în natură: pre-completarea este un calcul unic, decodarea are loc o dată pentru fiecare token din secvența de ieșire, iar coada implică procese de loturi de server. Atunci când sunt procesate mai multe solicitări concurente, devine dificil să se desprindă latența de la fiecare dintre aceste componente, deoarece latența experimentată de orice cerere de client implică latențe în coadă determinate de necesitatea de a precompleta noile cereri simultane, precum și de latența de coadă determinată de includere. a cererii în procesele de decodare batch. Din acest motiv, această postare se concentrează pe latența procesării end-to-end. Genunchiul în curba latență-debit apare în punctul de saturație în care latențele cozii încep să crească semnificativ. Acest fenomen are loc pentru orice model de server de inferență și este determinat de specificațiile acceleratorului.

Cerințele comune în timpul implementării includ satisfacerea unui debit minim necesar, latența maximă permisă, costul maxim pe oră și costul maxim pentru generarea a 1 milion de jetoane. Ar trebui să condiționați aceste cerințe pe sarcinile utile care reprezintă solicitări ale utilizatorilor finali. Un proiect care să îndeplinească aceste cerințe ar trebui să ia în considerare mulți factori, inclusiv arhitectura modelului specific, dimensiunea modelului, tipurile de instanțe și numărul de instanțe (scalare orizontală). În secțiunile următoare, ne concentrăm pe implementarea punctelor finale pentru a minimiza latența, a maximiza debitul și a minimiza costurile. Această analiză ia în considerare un total de 512 de jetoane și 256 de jetoane de ieșire.

Minimizați latența

Latența este o cerință importantă în multe cazuri de utilizare în timp real. În tabelul următor, ne uităm la latența minimă pentru fiecare model și fiecare tip de instanță. Puteți obține o latență minimă prin setare MAX_CONCURRENT_REQUESTS = 1.

Latența minimă (ms/token)
ID model ml.g5.2xmare ml.g5.12xmare ml.g5.48xmare ml.p4d.24xlarge ml.p4de.24xlarge
Lama 2 7B 33 17 18 20 -
Lama 2 7B Chat 33 17 18 20 -
Lama 2 13B - 22 23 23 -
Lama 2 13B Chat - 23 23 23 -
Lama 2 70B - - 57 43 -
Lama 2 70B Chat - - 57 45 -
Mistral 7B 35 - - - -
Mistral 7B Instruct 35 - - - -
Mixtral 8x7B - - 33 27 -
Soimul 7B 33 - - - -
Falcon 7B Instruct 33 - - - -
Soimul 40B - 53 33 27 -
Falcon 40B Instruct - 53 33 28 -
Soimul 180B - - - - 42
Falcon 180B Chat - - - - 42

Pentru a obține o latență minimă pentru un model, puteți utiliza următorul cod în timp ce înlocuiți ID-ul de model și tipul de instanță dorit:

from sagemaker.jumpstart.model import JumpStartModel model = JumpStartModel( model_id="meta-textgeneration-llama-2-7b", model_version="3.*", instance_type="ml.g5.12xlarge", env={ "MAX_CONCURRENT_REQUESTS": "1", "MAX_INPUT_TOKENS": "256", "MAX_TOTAL_TOKENS": "512", },
)
predictor = model.deploy(accept_eula=False) # Change EULA acceptance to True

Rețineți că numerele de latență se modifică în funcție de numărul de jetoane de intrare și de ieșire. Cu toate acestea, procesul de implementare rămâne același, cu excepția variabilelor de mediu MAX_INPUT_TOKENS și MAX_TOTAL_TOKENS. Aici, aceste variabile de mediu sunt setate pentru a ajuta la garantarea cerințelor de latență a punctului final, deoarece secvențele de intrare mai mari pot încălca cerința de latență. Rețineți că SageMaker JumpStart oferă deja celelalte variabile de mediu optime atunci când selectați tipul de instanță; de exemplu, folosind ml.g5.12xlarge se va seta SM_NUM_GPUS la 4 în mediul model.

Maximizați debitul

În această secțiune, maximizăm numărul de jetoane generate pe secundă. Acest lucru se realizează de obicei la cererile concurente maxime valide pentru model și tipul instanței. În tabelul următor, raportăm debitul atins la cea mai mare valoare de solicitare simultană atinsă înainte de a întâlni un timeout de invocare SageMaker pentru orice solicitare.

Debit maxim (jetoane/sec), solicitări simultane
ID model ml.g5.2xmare ml.g5.12xmare ml.g5.48xmare ml.p4d.24xlarge ml.p4de.24xlarge
Lama 2 7B 486 (64) 1214 (128) 804 (128) 2945 (512) -
Lama 2 7B Chat 493 (64) 1207 (128) 932 (128) 3012 (512) -
Lama 2 13B - 787 (128) 496 (64) 3245 (512) -
Lama 2 13B Chat - 782 (128) 505 (64) 3310 (512) -
Lama 2 70B - - 124 (16) 1585 (256) -
Lama 2 70B Chat - - 114 (16) 1546 (256) -
Mistral 7B 947 (64) - - - -
Mistral 7B Instruct 986 (128) - - - -
Mixtral 8x7B - - 701 (128) 3196 (512) -
Soimul 7B 1340 (128) - - - -
Falcon 7B Instruct 1313 (128) - - - -
Soimul 40B - 244 (32) 382 (64) 2699 (512) -
Falcon 40B Instruct - 245 (32) 415 (64) 2675 (512) -
Soimul 180B - - - - 1100 (128)
Falcon 180B Chat - - - - 1081 (128)

Pentru a obține un randament maxim pentru un model, puteți utiliza următorul cod:

from sagemaker.jumpstart.model import JumpStartModel model = JumpStartModel( model_id="meta-textgeneration-llama-2-7b", model_version="3.*", instance_type="ml.g5.12xlarge", env={ "MAX_CONCURRENT_REQUESTS": "128", # For your application, identify it from the benchmarking table with the maximum feasible concurrent requests. "MAX_INPUT_TOKENS": "256", "MAX_TOTAL_TOKENS": "512", },
)
predictor = model.deploy(accept_eula=False) # Change EULA acceptance to True

Rețineți că numărul maxim de solicitări simultane depinde de tipul modelului, tipul instanței, numărul maxim de jetoane de intrare și numărul maxim de jetoane de ieșire. Prin urmare, ar trebui să setați acești parametri înainte de a seta MAX_CONCURRENT_REQUESTS.

De asemenea, rețineți că un utilizator interesat de minimizarea latenței este adesea în contradicție cu un utilizator interesat de maximizarea debitului. Primul este interesat de răspunsurile în timp real, în timp ce cel de-al doilea este interesat de procesarea în loturi, astfel încât coada punctului final să fie întotdeauna saturată, minimizând astfel timpul de nefuncționare a procesării. Utilizatorii care doresc să maximizeze debitul condiționat de cerințele de latență sunt adesea interesați să opereze la genunchi în curba latență-debit.

Minimizați costul

Prima opțiune de minimizare a costurilor implică reducerea costului pe oră. Cu aceasta, puteți implementa un model selectat pe instanța SageMaker cu cel mai mic cost pe oră. Pentru prețurile în timp real ale instanțelor SageMaker, consultați Prețuri Amazon SageMaker. În general, tipul de instanță implicit pentru SageMaker JumpStart LLM este opțiunea de implementare cu cel mai mic cost.

A doua opțiune de minimizare a costurilor implică minimizarea costului de a genera 1 milion de jetoane. Aceasta este o transformare simplă a tabelului despre care am discutat mai devreme pentru a maximiza debitul, unde puteți calcula mai întâi timpul necesar în ore pentru a genera 1 milion de jetoane (1e6 / debit / 3600). Puteți apoi înmulți acest timp pentru a genera 1 milion de jetoane cu prețul pe oră al instanței SageMaker specificate.

Rețineți că instanțele cu cel mai mic cost pe oră nu sunt aceleași cu instanțe cu cel mai mic cost pentru a genera 1 milion de jetoane. De exemplu, dacă solicitările de invocare sunt sporadice, o instanță cu cel mai mic cost pe oră ar putea fi optimă, în timp ce în scenariile de throttling, cel mai mic cost pentru a genera un milion de jetoane ar putea fi mai potrivit.

Tensor paralel vs. compromis multi-model

În toate analizele anterioare, am luat în considerare implementarea unui singur model replică cu un grad paralel tensor egal cu numărul de GPU-uri pe tipul de instanță de implementare. Acesta este comportamentul implicit SageMaker JumpStart. Cu toate acestea, după cum sa menționat anterior, fragmentarea unui model poate îmbunătăți latența și debitul modelului doar până la o anumită limită, dincolo de care cerințele de comunicare între dispozitive domină timpul de calcul. Acest lucru implică faptul că este adesea benefic să implementați mai multe modele cu un grad de paralel tensor mai mic pe o singură instanță, mai degrabă decât un singur model cu un grad de paralel tensor mai mare.

Aici, implementăm punctele finale Llama 2 7B și 13B pe instanțe ml.p4d.24xlarge cu grade tensor paralele (TP) de 1, 2, 4 și 8. Pentru claritate în comportamentul modelului, fiecare dintre aceste puncte finale încarcă doar un singur model.

. Debit (jetoane/sec) Latență (ms/token)
Cereri concurente 1 2 4 8 16 32 64 128 256 512 1 2 4 8 16 32 64 128 256 512
Grad TP Lama 2 13B
1 38 74 147 278 443 612 683 722 - - 26 27 27 29 37 45 87 174 - -
2 49 92 183 351 604 985 1435 1686 1726 - 21 22 22 22 25 32 46 91 159 -
4 46 94 181 343 655 1073 1796 2408 2764 2819 23 21 21 24 25 30 37 57 111 172
8 44 86 158 311 552 1015 1654 2450 3087 3180 22 24 26 26 29 36 42 57 95 152
. Lama 2 7B
1 62 121 237 439 778 1122 1569 1773 1775 - 16 16 17 18 22 28 43 88 151 -
2 62 122 239 458 780 1328 1773 2440 2730 2811 16 16 17 18 21 25 38 56 103 182
4 60 106 211 420 781 1230 2206 3040 3489 3752 17 19 20 18 22 27 31 45 82 132
8 49 97 179 333 612 1081 1652 2292 2963 3004 22 20 24 26 27 33 41 65 108 167

Analizele noastre anterioare au arătat deja avantaje semnificative de debit pe instanțe ml.p4d.24xlarge, ceea ce se traduce adesea într-o performanță mai bună în ceea ce privește costul de a genera 1 milion de jetoane peste familia de instanțe g5 în condiții de încărcare concurență ridicată. Această analiză demonstrează clar că ar trebui să luați în considerare compromisul dintre fragmentarea modelului și replicarea modelului într-o singură instanță; adică un model complet fragmentat nu este de obicei cea mai bună utilizare a resurselor de calcul ml.p4d.24xlarge pentru familiile de modele 7B și 13B. De fapt, pentru familia de modele 7B, obțineți cel mai bun randament pentru o singură replică a modelului cu un grad tensor paralel de 4 în loc de 8.

De aici, puteți extrapola că cea mai mare configurație de debit pentru modelul 7B implică un grad paralel tensor de 1 cu opt replici de model, iar cea mai mare configurație de debit pentru modelul 13B este probabil un grad de paralel tensor de 2 cu patru replici de model. Pentru a afla mai multe despre cum să realizați acest lucru, consultați Reduceți costurile de implementare a modelului cu 50% în medie, folosind cele mai recente funcții ale Amazon SageMaker, care demonstrează utilizarea punctelor finale bazate pe componente de inferență. Datorită tehnicilor de echilibrare a încărcăturii, rutarea serverului și partajarea resurselor CPU, s-ar putea să nu obțineți în totalitate îmbunătățiri ale debitului exact egale cu numărul de replici ori debitul pentru o singură replică.

Scalare orizontală

După cum sa observat mai devreme, fiecare implementare a punctului final are o limitare a numărului de solicitări concurente, în funcție de numărul de jetoane de intrare și de ieșire, precum și de tipul instanței. Dacă acest lucru nu îndeplinește cerințele dvs. de debit sau de solicitare concomitentă, puteți crește pentru a utiliza mai mult de o instanță în spatele punctului final implementat. SageMaker efectuează automat echilibrarea sarcinii interogărilor între instanțe. De exemplu, următorul cod implementează un punct final susținut de trei instanțe:

model = JumpStartModel( model_id="meta-textgeneration-llama-2-7b", model_version="3.*", instance_type="ml.g5.2xlarge",
)
predictor = model.deploy( accept_eula=False, # Change EULA acceptance to True initial_instance_count = 3,
)

Următorul tabel arată câștigul de debit ca factor al numărului de instanțe pentru modelul Llama 2 7B.

. . Debit (jetoane/sec) Latență (ms/token)
. Cereri concurente 1 2 4 8 16 32 64 128 1 2 4 8 16 32 64 128
Număr de instanțe Tip de instanță Număr total de jetoane: 512, Număr de jetoane de ieșire: 256
1 ml.g5.2xmare 30 60 115 210 351 484 492 - 32 33 34 37 45 93 160 -
2 ml.g5.2xmare 30 60 115 221 400 642 922 949 32 33 34 37 42 53 94 167
3 ml.g5.2xmare 30 60 118 228 421 731 1170 1400 32 33 34 36 39 47 57 110

În special, genunchiul din curba de latență-debit se deplasează la dreapta, deoarece un număr mai mare de instanțe poate gestiona un număr mai mare de solicitări concurente în cadrul punctului final cu mai multe instanțe. Pentru acest tabel, valoarea cererii simultane este pentru întregul punct final, nu pentru numărul de solicitări simultane pe care le primește fiecare instanță individuală.

De asemenea, puteți utiliza scalarea automată, o caracteristică pentru a vă monitoriza sarcinile de lucru și pentru a ajusta dinamic capacitatea de a menține performanța constantă și previzibilă la cel mai mic cost posibil. Acest lucru depășește scopul acestei postări. Pentru a afla mai multe despre scalarea automată, consultați Configurarea punctelor finale de inferență cu scalare automată în Amazon SageMaker.

Invocați punctul final cu solicitări simultane

Să presupunem că aveți un lot mare de interogări pe care doriți să le utilizați pentru a genera răspunsuri de la un model implementat în condiții de debit mare. De exemplu, în următorul bloc de cod, alcătuim o listă de 1,000 de încărcări utile, fiecare sarcină utilă solicitând generarea a 100 de jetoane. În total, solicităm generarea a 100,000 de jetoane.

payload = { "inputs": "I believe the meaning of life is to ", "parameters": {"max_new_tokens": 100, "details": True},
}
total_requests = 1000
payloads = [payload,] * total_requests

Când trimiteți un număr mare de solicitări către API-ul de rulare SageMaker, este posibil să întâmpinați erori de limitare. Pentru a atenua acest lucru, puteți crea un client de rulare SageMaker personalizat care crește numărul de încercări de reîncercare. Puteți furniza obiectul de sesiune SageMaker rezultat fie către JumpStartModel constructor sau sagemaker.predictor.retrieve_default dacă doriți să atașați un nou predictor la un punct final deja implementat. În următorul cod, folosim acest obiect de sesiune atunci când implementăm un model Llama 2 cu configurații implicite SageMaker JumpStart:

import boto3
from botocore.config import Config
from sagemaker.session import Session
from sagemaker.jumpstart.model import JumpStartModel sagemaker_session = Session( sagemaker_runtime_client=boto3.client( "sagemaker-runtime", config=Config(connect_timeout=10, retries={"mode": "standard", "total_max_attempts": 20}), )
)
model = JumpStartModel( model_id="meta-textgeneration-llama-2-7b", model_version="3.*", sagemaker_session=sagemaker_session
)
predictor = model.deploy(accept_eula=False) # Change EULA acceptance to True

Acest punct final implementat are MAX_CONCURRENT_REQUESTS = 128 în mod implicit. În următorul bloc, folosim biblioteca concurent futures pentru a repeta invocarea punctului final pentru toate sarcinile utile cu 128 fire de lucru. Cel mult, punctul final va procesa 128 de cereri concurente și ori de câte ori o solicitare returnează un răspuns, executorul va trimite imediat o nouă cerere către punctul final.

import time
from concurrent import futures concurrent_requests = 128 time_start = time.time()
with futures.ThreadPoolExecutor(max_workers=concurrent_requests) as executor: responses = list(executor.map(predictor.predict, payloads)) total_tokens = sum([response[0]["details"]["generated_tokens"] for response in responses])
token_throughput = total_tokens / (time.time() - time_start)

Acest lucru are ca rezultat generarea a 100,000 de jetoane totale cu un debit de 1255 jetoane/sec pe o singură instanță ml.g5.2xlarge. Procesarea durează aproximativ 80 de secunde.

Rețineți că această valoare a debitului este semnificativ diferită de debitul maxim pentru Llama 2 7B pe ml.g5.2xlarge din tabelele anterioare ale acestei postări (486 de jetoane/sec la 64 de solicitări simultane). Acest lucru se datorează faptului că sarcina utilă de intrare utilizează 8 jetoane în loc de 256, numărul de jetoane de ieșire este de 100 în loc de 256, iar numărul de jetoane mai mic permite 128 de solicitări concurente. Acesta este un ultim memento că toate numerele de latență și debit depind de sarcina utilă! Modificarea numărului de jetoane de încărcare utilă va afecta procesele de loturi în timpul difuzării modelului, ceea ce va afecta, la rândul său, timpii emergente de precompletare, decodare și coadă pentru aplicația dvs.

Concluzie

În această postare, am prezentat benchmarking-urile SageMaker JumpStart LLM, inclusiv Llama 2, Mistral și Falcon. Am prezentat, de asemenea, un ghid pentru a optimiza latența, debitul și costul pentru configurația de implementare a punctului final. Puteți începe rulând aplicația caiet asociat pentru a vă compara cazul de utilizare.


Despre Autori

Evaluați și optimizați implementarea punctelor finale în Amazon SageMaker JumpStart | Amazon Web Services PlatoBlockchain Data Intelligence. Căutare verticală. Ai.  Dr. Kyle Ulrich este un om de știință aplicat în echipa Amazon SageMaker JumpStart. Interesele sale de cercetare includ algoritmi scalabili de învățare automată, viziunea computerizată, serii temporale, non-parametrice bayesiene și procese gaussiene. Doctoratul său este de la Universitatea Duke și a publicat lucrări în NeurIPS, Cell, and Neuron.

Evaluați și optimizați implementarea punctelor finale în Amazon SageMaker JumpStart | Amazon Web Services PlatoBlockchain Data Intelligence. Căutare verticală. Ai.Dr. Vivek Madan este un om de știință aplicat în echipa Amazon SageMaker JumpStart. Și-a luat doctoratul la Universitatea din Illinois la Urbana-Champaign și a fost cercetător post-doctoral la Georgia Tech. Este un cercetător activ în învățarea automată și proiectarea algoritmilor și a publicat lucrări în cadrul conferințelor EMNLP, ICLR, COLT, FOCS și SODA.

Evaluați și optimizați implementarea punctelor finale în Amazon SageMaker JumpStart | Amazon Web Services PlatoBlockchain Data Intelligence. Căutare verticală. Ai.Dr. Ashish Khetan este cercetător senior aplicat cu Amazon SageMaker JumpStart și ajută la dezvoltarea algoritmilor de învățare automată. Și-a luat doctoratul la Universitatea din Illinois Urbana-Champaign. Este un cercetător activ în învățarea automată și inferența statistică și a publicat multe lucrări în conferințele NeurIPS, ICML, ICLR, JMLR, ACL și EMNLP.

Evaluați și optimizați implementarea punctelor finale în Amazon SageMaker JumpStart | Amazon Web Services PlatoBlockchain Data Intelligence. Căutare verticală. Ai.João Moura este arhitect senior în soluții de specialitate AI/ML la AWS. João îi ajută pe clienții AWS – de la startup-uri mici până la întreprinderi mari – să antreneze și să implementeze modele mari în mod eficient și să construiască mai larg platforme ML pe AWS.

Timestamp-ul:

Mai mult de la Învățare automată AWS