Maksimer stabil diffusjonsytelse og reduser slutningskostnader med AWS Inferentia2 | Amazon Web Services

Maksimer stabil diffusjonsytelse og reduser slutningskostnader med AWS Inferentia2 | Amazon Web Services

Generative AI-modeller har opplevd rask vekst de siste månedene på grunn av dens imponerende evner til å lage realistisk tekst, bilder, kode og lyd. Blant disse modellene skiller Stable Diffusion-modeller seg ut for sin unike styrke ved å lage bilder av høy kvalitet basert på tekstmeldinger. Stabil diffusjon kan generere et bredt utvalg av bilder av høy kvalitet, inkludert realistiske portretter, landskap og til og med abstrakt kunst. Og, som andre generative AI-modeller, krever stabile diffusjonsmodeller kraftig databehandling for å gi slutninger med lav latens.

I dette innlegget viser vi hvordan du kan kjøre stabile diffusjonsmodeller og oppnå høy ytelse til lavest mulig pris i Amazon Elastic Compute Cloud (Amazon EC2) ved hjelp av Amazon EC2 Inf2-forekomster drevet av AWS Inferentia2. Vi ser på arkitekturen til en stabil diffusjonsmodell og går gjennom trinnene for å kompilere en stabil diffusjonsmodell ved hjelp av AWS nevron og distribuere den til en Inf2-instans. Vi diskuterer også optimaliseringene som Neuron SDK automatisk gjør for å forbedre ytelsen. Du kan kjøre både Stable Diffusion 2.1 og 1.5 versjoner på AWS Inferentia2 kostnadseffektivt. Til slutt viser vi hvordan du kan distribuere en stabil diffusjonsmodell til en Inf2-instans med Amazon SageMaker.

Stable Diffusion 2.1-modellstørrelsen i flytende komma 32 (FP32) er 5 GB og 2.5 GB i bfoat16 (BF16). En enkelt inf2.xlarge-forekomst har én AWS Inferentia2-akselerator med 32 GB HBM-minne. Stable Diffusion 2.1-modellen kan passe på en enkelt inf2.xlarge-instans. Stable Diffusion er en tekst-til-bilde-modell som du kan bruke til å lage bilder av forskjellige stiler og innhold ganske enkelt ved å gi en tekstmelding som input. For å lære mer om stabil diffusjonsmodellarkitektur, se Lag bilder av høy kvalitet med Stable Diffusion-modeller og distribuer dem kostnadseffektivt med Amazon SageMaker.

Hvordan Neuron SDK optimaliserer stabil diffusjonsytelse

Før vi kan distribuere Stable Diffusion 2.1-modellen på AWS Inferentia2-forekomster, må vi kompilere modellkomponentene ved å bruke Neuron SDK. Neuron SDK, som inkluderer en kompilator for dyp læring, kjøretid og verktøy, kompilerer og optimaliserer automatisk dyplæringsmodeller slik at de kan kjøre effektivt på Inf2-forekomster og trekke ut full ytelse fra AWS Inferentia2-akseleratoren. Vi har eksempler tilgjengelig for Stable Diffusion 2.1-modellen på GitHub repo. Denne notatboken presenterer et ende-til-ende-eksempel på hvordan man kompilerer en stabil diffusjonsmodell, lagrer de kompilerte Neuron-modellene og laster den inn i kjøretiden for slutning.

Vi bruker StableDiffusionPipeline fra Hugging Face diffusers bibliotek for å laste og kompilere modellen. Vi kompilerer deretter alle komponentene i modellen for Neuron ved hjelp av torch_neuronx.trace() og lagre den optimaliserte modellen som TorchScript. Kompileringsprosesser kan være ganske minnekrevende, og krever en betydelig mengde RAM. For å omgå dette, før vi sporer hver modell, lager vi en deepcopy av den delen av rørledningen som spores. Etter dette sletter vi pipeline-objektet fra minnet ved hjelp av del pipe. Denne teknikken er spesielt nyttig når du kompilerer på forekomster med lav RAM.

I tillegg utfører vi også optimaliseringer til de stabile diffusjonsmodellene. UNet har det mest beregningsintensive aspektet av slutningen. UNet-komponenten opererer på inngangstensorer som har en batchstørrelse på to, og genererer en tilsvarende utgangstensor også med en batchstørrelse på to, for å produsere et enkelt bilde. Elementene i disse partiene er helt uavhengige av hverandre. Vi kan dra nytte av denne oppførselen for å få optimal ventetid ved å kjøre én batch på hver Neuron-kjerne. Vi kompilerer UNet for en batch (ved å bruke inngangstensorer med en batch), og bruker deretter torch_neuronx.DataParallel API for å laste denne enkelt batch-modellen på hver kjerne. Utgangen til denne API-en er en sømløs to-batch-modul: vi kan overføre inngangene til to batcher til UNet, og en to-batch-utgang returneres, men internt kjører de to single-batch-modellene på de to Neuron-kjernene . Denne strategien optimaliserer ressursutnyttelsen og reduserer ventetiden.

Kompiler og distribuer en stabil diffusjonsmodell på en Inf2 EC2-instans

For å kompilere og distribuere den stabile diffusjonsmodellen på en Inf2 EC2-forekomst, logg inn på AWS-administrasjonskonsoll og lag en inf2.8xlarge-forekomst. Merk at en inf2.8xlarge-forekomst bare kreves for kompilering av modellen fordi kompilering krever et høyere vertsminne. Den stabile diffusjonsmodellen kan hostes på en inf2.xlarge-instans. Du kan finne de nyeste AMI med Neuron-bibliotekene ved å bruke følgende AWS kommandolinjegrensesnitt (AWS CLI) kommando:

aws ec2 describe-images --region us-east-1 --owners amazon --filters 'Name=name,Values=Deep Learning AMI Neuron PyTorch 1.13.? (Amazon Linux 2) ????????' 'Name=state,Values=available' --query 'reverse(sort_by(Images, &CreationDate))[:1].ImageId' --output text

For dette eksemplet opprettet vi en EC2-forekomst ved å bruke Deep Learning AMI Neuron PyTorch 1.13 (Ubuntu 20.04). Du kan deretter opprette et JupyterLab-labmiljø ved å koble til forekomsten og kjøre følgende trinn:

run source /opt/aws_neuron_venv_pytorch/bin/activate
pip install jupyterlab
jupyter-lab

En notatbok med alle trinnene for å kompilere og hoste modellen er plassert på GitHub.

La oss se på kompileringstrinnene for en av tekstkoderblokkene. Andre blokker som er en del av den stabile diffusjonsrørledningen kan kompileres på samme måte.

Det første trinnet er å laste den ferdigtrente modellen fra Hugging Face. De StableDiffusionPipeline.from_pretrained metoden laster den forhåndstrente modellen inn i vårt pipeline-objekt, pipe. Vi lager deretter en deepcopy av tekstkoderen fra rørledningen vår, og kloner den effektivt. De del pipe kommandoen brukes deretter til å slette det originale pipeline-objektet, og frigjøre minnet som ble forbrukt av det. Her kvantiserer vi modellen til BF16-vekter:

model_id = "stabilityai/stable-diffusion-2-1-base"
pipe = StableDiffusionPipeline.from_pretrained(model_id, torch_dtype=torch.bfloat16)
text_encoder = copy.deepcopy(pipe.text_encoder)
del pipe

Dette trinnet innebærer å pakke inn tekstkoderen vår med NeuronTextEncoder innpakning. Utdataene fra en kompilert tekstkodermodul vil være av dict. Vi konverterer den til en list skriv med denne innpakningen:

text_encoder = NeuronTextEncoder(text_encoder)

Vi initialiserer PyTorch-tensoren emb med noen verdier. De emb tensor brukes som eksempelinngang for torch_neuronx.trace funksjon. Denne funksjonen sporer tekstkoderen vår og kompilerer den til et format som er optimalisert for Neuron. Katalogbanen for den kompilerte modellen er konstruert ved sammenføyning COMPILER_WORKDIR_ROOT med underkatalogen text_encoder:

emb = torch.tensor([...])
text_encoder_neuron = torch_neuronx.trace(
        text_encoder.neuron_text_encoder,
        emb,
        compiler_workdir=os.path.join(COMPILER_WORKDIR_ROOT, 'text_encoder'),
        )

Den kompilerte tekstkoderen lagres ved hjelp av torch.jit.save. Den er lagret under filnavnet model.pt i text_encoder katalog over kompilatorens arbeidsområde:

text_encoder_filename = os.path.join(COMPILER_WORKDIR_ROOT, 'text_encoder/model.pt')
torch.jit.save(text_encoder_neuron, text_encoder_filename)

De bærbare inkluderer lignende trinn for å kompilere andre komponenter i modellen: UNet, VAE-dekoder og VAE post_quant_conv. Etter at du har kompilert alle modellene, kan du laste inn og kjøre modellen ved å følge disse trinnene:

  1. Definer banene for de kompilerte modellene.
  2. Last inn en forhåndstrent StableDiffusionPipeline modell, med konfigurasjonen spesifisert for å bruke bfloat16-datatypen.
  3. Last UNet-modellen på to Neuron-kjerner ved hjelp av torch_neuronx.DataParallel API. Dette gjør det mulig å utføre parallell inferens av data, noe som kan øke modellens ytelse betydelig.
  4. Last inn de resterende delene av modellen (text_encoder, decoderog post_quant_conv) på en enkelt nevronkjerne.

Du kan deretter kjøre pipelinen ved å gi inndatatekst som ledetekster. Følgende er noen bilder generert av modellen for ledetekstene:

  • Portrett av renaud sechan, penn og blekk, intrikate strektegninger, av craig mullins, ruan jia, kentaro miura, greg rutkowski, loundraw

Maksimer stabil diffusjonsytelse og reduser slutningskostnader med AWS Inferentia2 | Amazon Web Services PlatoBlockchain Data Intelligence. Vertikalt søk. Ai.

  • Portrett av gammel kullgruvearbeider på 19-tallet, vakkert maleri, med svært detaljert ansiktsmaling av greg rutkowski

Maksimer stabil diffusjonsytelse og reduser slutningskostnader med AWS Inferentia2 | Amazon Web Services PlatoBlockchain Data Intelligence. Vertikalt søk. Ai.

  • Et slott midt i en skog

Maksimer stabil diffusjonsytelse og reduser slutningskostnader med AWS Inferentia2 | Amazon Web Services PlatoBlockchain Data Intelligence. Vertikalt søk. Ai.

Host Stable Diffusion 2.1 på AWS Inferentia2 og SageMaker

Å være vert for stabile diffusjonsmodeller med SageMaker krever også kompilering med Neuron SDK. Du kan fullføre kompileringen på forhånd eller under kjøretid ved å bruke Large Model Inference (LMI)-beholdere. Kompilering på forhånd gir raskere modelllastetider og er det foretrukne alternativet.

SageMaker LMI-beholdere gir to måter å distribuere modellen på:

  • Et kodefritt alternativ der vi bare tilbyr en serving.properties fil med de nødvendige konfigurasjonene
  • Ta med ditt eget slutningsmanus

Vi ser på begge løsningene og går over konfigurasjonene og slutningsskriptet (model.py). I dette innlegget demonstrerer vi distribusjonen ved hjelp av en forhåndskompilert modell lagret i en Amazon enkel lagringstjeneste (Amazon S3) bøtte. Du kan bruke denne forhåndskompilerte modellen for distribusjonene dine.

Konfigurer modellen med et medfølgende skript

I denne delen viser vi hvordan du konfigurerer LMI-beholderen til å være vert for de stabile diffusjonsmodellene. SD2.1 bærbar PC tilgjengelig på GitHub. Det første trinnet er å lage modellkonfigurasjonspakken i henhold til følgende katalogstruktur. Målet vårt er å bruke de minimale modellkonfigurasjonene som trengs for å være vert for modellen. Katalogstrukturen som trengs er som følger:

<config-root-directory> / 
    ├── serving.properties
    │   
    └── model.py [OPTIONAL]

Deretter lager vi serveringsegenskaper fil med følgende parametere:

%%writefile code_sd/serving.properties
engine=Python
option.entryPoint=djl_python.transformers-neuronx
option.use_stable_diffusion=True
option.model_id=s3url
option.tensor_parallel_degree=2
option.dtype=bf16

Parametrene spesifiserer følgende:

  • option.model_id – LMI-beholderne bruker s5cmd for å laste modellen fra S3-stedet, og derfor må vi spesifisere plasseringen av hvor våre kompilerte vekter er.
  • option.entryPoint – For å bruke de innebygde behandlerne, spesifiserer vi transformator-neuronx-klassen. Hvis du har et tilpasset slutningsskript, må du oppgi det i stedet.
  • option.dtype – Dette spesifiserer å laste vektene i en bestemt størrelse. For dette innlegget bruker vi BF16, som ytterligere reduserer minnekravene vs. FP32 og senker latensen vår på grunn av det.
  • option.tensor_parallel_degree – Denne parameteren spesifiserer antall akseleratorer vi bruker for denne modellen. AWS Inferentia2-brikkeakseleratoren har to nevronkjerner, og å spesifisere en verdi på 2 betyr at vi bruker én akselerator (to kjerner). Dette betyr at vi nå kan opprette flere arbeidere for å øke gjennomstrømningen til endepunktet.
  • alternativ.motor – Dette er satt til Python for å indikere at vi ikke vil bruke andre kompilatorer som DeepSpeed ​​eller Faster Transformer for denne hostingen.

Ta med eget manus

Hvis du vil ta med ditt eget tilpassede slutningsskript, må du fjerne option.entryPoint fra serving.properties. LMI-beholderen vil i så fall se etter en model.py filen på samme sted som serving.properties og bruk det til å kjøre slutningen.

Lag ditt eget slutningsskript (model.py)

Å lage ditt eget slutningsskript er relativt enkelt ved å bruke LMI-beholderen. Beholderen krever din model.py fil for å ha en implementering av følgende metode:

def handle(inputs: Input) which returns an object of type Outputs

La oss undersøke noen av de kritiske områdene i vedlagt notatbok, som demonstrerer funksjonen ta med ditt eget skript.

Bytt ut cross_attention modul med den optimaliserte versjonen:

# Replace original cross-attention module with custom cross-attention module for better performance
    CrossAttention.get_attention_scores = get_attention_scores
Load the compiled weights for the following
text_encoder_filename = os.path.join(COMPILER_WORKDIR_ROOT, 'text_encoder.pt')
decoder_filename = os.path.join(COMPILER_WORKDIR_ROOT, 'vae_decoder.pt')
unet_filename = os.path.join(COMPILER_WORKDIR_ROOT, 'unet.pt')
post_quant_conv_filename =. os.path.join(COMPILER_WORKDIR_ROOT, 'vae_post_quant_conv.pt')

Dette er navnene på den kompilerte vektfilen vi brukte da vi laget kompilasjonene. Endre gjerne filnavnene, men sørg for at filnavnene dine stemmer overens med det du spesifiserer her.

Deretter må vi laste dem ved hjelp av Neuron SDK og sette disse i de faktiske modellvektene. Når du laster de UNet-optimaliserte vektene, merk at vi også spesifiserer antall nevronkjerner vi trenger å laste disse på. Her laster vi til en enkelt akselerator med to kjerner:

# Load the compiled UNet onto two neuron cores.
    pipe.unet = NeuronUNet(UNetWrap(pipe.unet))
    logging.info(f"Loading model: unet:created")
    device_ids = [idx for idx in range(tensor_parallel_degree)]
   
    pipe.unet.unetwrap = torch_neuronx.DataParallel(torch.jit.load(unet_filename), device_ids, set_dynamic_batching=False)
   
 
    # Load other compiled models onto a single neuron core.
 
    # - load encoders
    pipe.text_encoder = NeuronTextEncoder(pipe.text_encoder)
    clip_compiled = torch.jit.load(text_encoder_filename)
    pipe.text_encoder.neuron_text_encoder = clip_compiled
    #- load decoders
    pipe.vae.decoder = torch.jit.load(decoder_filename)
    pipe.vae.post_quant_conv = torch.jit.load(post_quant_conv_filename)

Å kjøre slutningen med en ledetekst påkaller rørobjektet for å generere et bilde.

Opprett SageMaker-endepunktet

Vi bruker Boto3 APIer for å lage et SageMaker-endepunkt. Fullfør følgende trinn:

  1. Lag tarballen med bare serveringen og det valgfrie model.py filer og last den opp til Amazon S3.
  2. Lag modellen ved å bruke bildebeholderen og modelltarballen lastet opp tidligere.
  3. Opprett endepunktkonfigurasjonen ved å bruke følgende nøkkelparametere:
    1. Bruk en ml.inf2.xlarge forekomst.
    2. Sett ContainerStartupHealthCheckTimeoutInSeconds til 240 for å sikre at helsesjekken starter etter at modellen er distribuert.
    3. Sett VolumeInGB til en større verdi, slik at den kan brukes til å laste modellvekter som er 32 GB i størrelse.

Lag en SageMaker-modell

Etter at du har opprettet model.tar.gz-filen og lastet den opp til Amazon S3, må vi lage en SageMaker-modell. Vi bruker LMI-beholderen og modellartefakten fra forrige trinn for å lage SageMaker-modellen. SageMaker lar oss tilpasse og injisere ulike miljøvariabler. For denne arbeidsflyten kan vi la alt være standard. Se følgende kode:

inference_image_uri = (
    f"763104351884.dkr.ecr.{region}.amazonaws.com/djl-inference:0 djl-serving-inf2"
)

Opprett modellobjektet, som i hovedsak skaper en lockdown-beholder som lastes inn på forekomsten og brukes til å konkludere:

model_name = name_from_base(f"inf2-sd")
create_model_response = boto3_sm_client.create_model(
    ModelName=model_name,
    ExecutionRoleArn=role,
    PrimaryContainer={"Image": inference_image_uri, "ModelDataUrl": s3_code_artifact},
)

Opprett et SageMaker-endepunkt

I denne demoen bruker vi en ml.inf2.xlarge-forekomst. Vi må stille inn VolumeSizeInGB parametere for å gi nødvendig diskplass for å laste modellen og vektene. Denne parameteren gjelder for instanser som støtter Amazon Elastic Block Store (Amazon EBS) volumfeste. Vi kan la modellnedlastingstiden og helsesjekken for oppstart av beholderen ligge på en høyere verdi, noe som vil gi tilstrekkelig tid for beholderen til å trekke vektene fra Amazon S3 og laste inn i AWS Inferentia2-akseleratorene. For flere detaljer, se CreateEndpointConfig.

endpoint_config_response = boto3_sm_client.create_endpoint_config( EndpointConfigName=endpoint_config_name,
    ProductionVariants=[
        {
            "VariantName": "variant1",
            "ModelName": model_name,
            "InstanceType": "ml.inf2.xlarge", # - 
            "InitialInstanceCount": 1,
            "ContainerStartupHealthCheckTimeoutInSeconds": 360, 
            "VolumeSizeInGB": 400
        },
    ],
)

Til slutt lager vi et SageMaker-endepunkt:

create_endpoint_response = boto3_sm_client.create_endpoint(
    EndpointName=f"{endpoint_name}", EndpointConfigName=endpoint_config_name
)

Påkall modellens endepunkt

Dette er en generativ modell, så vi sender inn ledeteksten som modellen bruker for å generere bildet. Nyttelasten er av typen JSON:

response_model = boto3_sm_run_client.invoke_endpoint( EndpointName=endpoint_name,
    Body=json.dumps(
        {
            "prompt": "Mountain Landscape", 
            "parameters": {} # 
        }
    ), 
    ContentType="application/json",
)

Benchmarking av den stabile diffusjonsmodellen på Inf2

Vi kjørte noen tester for å benchmarke den stabile diffusjonsmodellen med BF 16-datatypen på Inf2, og vi er i stand til å utlede latenstidstall som konkurrerer med eller overgår noen av de andre akseleratorene for stabil diffusjon. Dette, kombinert med lavere kostnader for AWS Inferentia2-brikker, gjør dette til et ekstremt verdifullt forslag.

Følgende tall er fra den stabile diffusjonsmodellen distribuert på en inf2.xl-forekomst. For mer informasjon om kostnader, se Amazon EC2 Inf2-forekomster.

Modell oppløsning Data-type Iterasjoner P95-forsinkelse (ms) Inf2.xl On-Demand kostnad per time Inf2.xl (kostnad per bilde)
Stabil diffusjon 1.5 512 × 512 bf16 50 2,427.4 $0.76 $0.0005125
Stabil diffusjon 1.5 768 × 768 bf16 50 8,235.9 $0.76 $0.0017387
Stabil diffusjon 1.5 512 × 512 bf16 30 1,456.5 $0.76 $0.0003075
Stabil diffusjon 1.5 768 × 768 bf16 30 4,941.6 $0.76 $0.0010432
Stabil diffusjon 2.1 512 × 512 bf16 50 1,976.9 $0.76 $0.0004174
Stabil diffusjon 2.1 768 × 768 bf16 50 6,836.3 $0.76 $0.0014432
Stabil diffusjon 2.1 512 × 512 bf16 30 1,186.2 $0.76 $0.0002504
Stabil diffusjon 2.1 768 × 768 bf16 30 4,101.8 $0.76 $0.0008659

konklusjonen

I dette innlegget dykket vi dypt inn i kompileringen, optimaliseringen og distribusjonen av Stable Diffusion 2.1-modellen ved å bruke Inf2-forekomster. Vi demonstrerte også distribusjon av stabile diffusjonsmodeller ved hjelp av SageMaker. Inf2-forekomster leverer også god prisytelse for Stable Diffusion 1.5. For å lære mer om hvorfor Inf2-forekomster er gode for generativ AI og store språkmodeller, se Amazon EC2 Inf2-forekomster for lavkostnadsgenerativ AI-inferens med høy ytelse er nå generelt tilgjengelig. For ytelsesdetaljer, se Inf2 ytelse. Sjekk ut flere eksempler på GitHub repo.

Spesiell takk til Matthew Mcclain, Beni Hegedus, Kamran Khan, Shruti Koparkar og Qing Lan for gjennomgang og verdifulle innspill.


Om forfatterne

Maksimer stabil diffusjonsytelse og reduser slutningskostnader med AWS Inferentia2 | Amazon Web Services PlatoBlockchain Data Intelligence. Vertikalt søk. Ai.Vivek Gangasani er Senior Machine Learning Solutions Architect hos Amazon Web Services. Han jobber med oppstart av maskinlæring for å bygge og distribuere AI/ML-applikasjoner på AWS. Han er for tiden fokusert på å levere løsninger for MLOps, ML-inferens og lavkode-ML. Han har jobbet med prosjekter innen forskjellige domener, inkludert naturlig språkbehandling og datasyn.

Maksimer stabil diffusjonsytelse og reduser slutningskostnader med AWS Inferentia2 | Amazon Web Services PlatoBlockchain Data Intelligence. Vertikalt søk. Ai.KC Tung er senior løsningsarkitekt i AWS Annapurna Labs. Han spesialiserer seg på opplæring og implementering av store dyplæringsmodeller i skyen. Han har en Ph.D. i molekylær biofysikk fra University of Texas Southwestern Medical Center i Dallas. Han har talt på AWS Summits og AWS Reinvent. I dag hjelper han kunder med å trene og distribuere store PyTorch- og TensorFlow-modeller i AWS-skyen. Han er forfatter av to bøker: Lær TensorFlow Enterprise og TensorFlow 2 Pocket Reference.

Maksimer stabil diffusjonsytelse og reduser slutningskostnader med AWS Inferentia2 | Amazon Web Services PlatoBlockchain Data Intelligence. Vertikalt søk. Ai.Rupinder Grewal er en Sr Ai/ML spesialistløsningsarkitekt med AWS. Han fokuserer for tiden på servering av modeller og MLOps på SageMaker. Før denne rollen har han jobbet som maskinlæringsingeniør med å bygge og hoste modeller. Utenom jobben liker han å spille tennis og sykle på fjellstier.

Tidstempel:

Mer fra AWS maskinlæring