Збільште продуктивність Stable Diffusion і зменште витрати на логічні висновки за допомогою AWS Inferentia2 | Веб-сервіси Amazon

Збільште продуктивність Stable Diffusion і зменште витрати на логічні висновки за допомогою AWS Inferentia2 | Веб-сервіси Amazon

Останніми місяцями генеративні моделі штучного інтелекту стрімко розвиваються завдяки своїм вражаючим можливостям у створенні реалістичного тексту, зображень, коду та аудіо. Серед цих моделей моделі Stable Diffusion виділяються своєю унікальною силою у створенні високоякісних зображень на основі текстових підказок. Stable Diffusion може створювати різноманітні високоякісні зображення, включаючи реалістичні портрети, пейзажі та навіть абстрактне мистецтво. Як і інші генеративні моделі штучного інтелекту, моделі стабільної дифузії потребують потужних обчислень, щоб забезпечити висновки з низькою затримкою.

У цьому дописі ми покажемо, як запустити моделі стабільної дифузії та досягти високої продуктивності за найнижчих витрат у Обчислювальна хмара Amazon Elastic (Amazon EC2) за допомогою Екземпляри Amazon EC2 Inf2 живлення від AWS Inferentia2. Ми розглянемо архітектуру моделі стабільної дифузії та пройдемо кроки компіляції моделі стабільної дифузії за допомогою AWS нейрон і розгортання його на примірнику Inf2. Ми також обговорюємо оптимізацію, яку Neuron SDK автоматично здійснює для підвищення продуктивності. Ви можете запустити обидві версії Stable Diffusion 2.1 і 1.5 на AWS Inferentia2 без витрат. Нарешті, ми показуємо, як можна розгорнути модель Stable Diffusion в екземплярі Inf2 за допомогою Amazon SageMaker.

Розмір моделі Stable Diffusion 2.1 у форматі з плаваючою комою 32 (FP32) становить 5 ГБ і 2.5 ГБ у bfoat16 (BF16). Один екземпляр inf2.xlarge має один прискорювач AWS Inferentia2 із 32 ГБ пам’яті HBM. Модель Stable Diffusion 2.1 може поміститися в один екземпляр inf2.xlarge. Stable Diffusion — це модель перетворення тексту в зображення, яку можна використовувати для створення зображень різних стилів і вмісту, просто надаючи текстову підказку як вхідні дані. Щоб дізнатися більше про архітектуру моделі Stable Diffusion, див Створюйте високоякісні зображення за допомогою моделей Stable Diffusion і рентабельно розгортайте їх за допомогою Amazon SageMaker.

Як Neuron SDK оптимізує продуктивність Stable Diffusion

Перш ніж ми зможемо розгорнути модель Stable Diffusion 2.1 на примірниках AWS Inferentia2, нам потрібно скомпілювати компоненти моделі за допомогою Neuron SDK. Neuron SDK, який включає компілятор глибокого навчання, середовище виконання та інструменти, компілює та автоматично оптимізує моделі глибокого навчання, щоб вони могли ефективно працювати на екземплярах Inf2 і отримати повну продуктивність прискорювача AWS Inferentia2. У нас є доступні приклади для моделі Stable Diffusion 2.1 на GitHub репо. Цей блокнот представляє наскрізний приклад того, як скомпілювати модель Stable Diffusion, зберегти скомпільовані моделі Neuron і завантажити їх у середовище виконання для висновків.

Ми використовуємо StableDiffusionPipeline від Hugging Face diffusers бібліотека для завантаження та компіляції моделі. Потім ми компілюємо всі компоненти моделі для використання Neuron torch_neuronx.trace() і збережіть оптимізовану модель як TorchScript. Процеси компіляції можуть займати досить інтенсивну пам'ять, вимагаючи значного обсягу оперативної пам'яті. Щоб уникнути цього, перед трасуванням кожної моделі ми створюємо a deepcopy частини трубопроводу, яка трасується. Після цього ми видаляємо об’єкт конвеєра з пам’яті за допомогою del pipe. Ця техніка особливо корисна під час компіляції на екземплярах із малим обсягом оперативної пам’яті.

Крім того, ми також виконуємо оптимізацію моделей стабільної дифузії. UNet має найбільш обчислювально інтенсивний аспект висновку. Компонент UNet працює з вхідними тензорами, які мають розмір партії, що дорівнює двом, генеруючи відповідний вихідний тензор також із розміром партії, що дорівнює двом, для отримання єдиного зображення. Елементи в цих пакетах повністю незалежні один від одного. Ми можемо скористатися цією поведінкою, щоб отримати оптимальну затримку, запустивши одну партію на кожному ядрі Neuron. Ми компілюємо UNet для одного пакету (за допомогою тензорів введення з одним пакетом), а потім використовуємо torch_neuronx.DataParallel API для завантаження цієї єдиної пакетної моделі в кожне ядро. Результатом цього API є безшовний двопакетний модуль: ми можемо передати в UNet вхідні дані двох пакетів, і повертається двопакетний вихід, але внутрішньо дві однопакетні моделі працюють на двох ядрах Neuron . Ця стратегія оптимізує використання ресурсів і зменшує затримку.

Скомпілюйте та розгорніть модель Stable Diffusion на примірнику Inf2 EC2

Щоб скомпілювати та розгорнути модель Stable Diffusion на примірнику Inf2 EC2, підпишіться на Консоль управління AWS і створіть екземпляр inf2.8xlarge. Зауважте, що екземпляр inf2.8xlarge потрібен лише для компіляції моделі, оскільки для компіляції потрібна більша пам’ять хоста. Модель Stable Diffusion можна розмістити на примірнику inf2.xlarge. Ви можете знайти найновіші AMI з бібліотеками Neuron за допомогою наступного Інтерфейс командного рядка AWS (AWS CLI) команда:

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

Для цього прикладу ми створили екземпляр EC2 за допомогою Deep Learning AMI Neuron PyTorch 1.13 (Ubuntu 20.04). Потім ви можете створити лабораторне середовище JupyterLab, підключившись до примірника та виконавши такі кроки:

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

Блокнот з усіма кроками для складання та розміщення моделі розташований на GitHub.

Давайте розглянемо кроки компіляції для одного з блоків текстового кодувальника. Інші блоки, які є частиною конвеєра Stable Diffusion, можна скомпілювати подібним чином.

Першим кроком є ​​завантаження попередньо підготовленої моделі з Hugging Face. The StableDiffusionPipeline.from_pretrained метод завантажує попередньо навчену модель у наш конвеєрний об’єкт, pipe. Потім ми створюємо a deepcopy текстового кодувальника з нашого конвеєра, фактично клонуючи його. The del pipe Потім команда використовується для видалення оригінального об’єкта конвеєра, звільняючи пам’ять, яку він споживав. Тут ми квантуємо модель до ваг BF16:

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

Цей крок передбачає обгортання нашого кодувальника тексту за допомогою NeuronTextEncoder обгортка. Вихід скомпільованого модуля кодувальника тексту буде з dict. Ми перетворюємо його на a list введіть за допомогою цієї оболонки:

text_encoder = NeuronTextEncoder(text_encoder)

Ми ініціалізуємо тензор PyTorch emb з деякими значеннями. The emb tensor використовується як приклад введення для torch_neuronx.trace функція. Ця функція відстежує наш текстовий кодувальник і компілює його у формат, оптимізований для Neuron. Шлях до каталогу для скомпільованої моделі створюється шляхом об’єднання COMPILER_WORKDIR_ROOT з підкаталогом 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'),
        )

Зібраний текстовий кодувальник зберігається за допомогою torch.jit.save. Він зберігається під назвою файлу model.pt у text_encoder каталог робочої області нашого компілятора:

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

Команда ноутбук містить аналогічні кроки для компіляції інших компонентів моделі: UNet, декодера VAE та VAE post_quant_conv. Після компіляції всіх моделей ви можете завантажити та запустити модель, виконавши такі дії:

  1. Визначте шляхи для скомпільованих моделей.
  2. Завантажте попередньо підготовлену StableDiffusionPipeline моделі, у конфігурації якої вказано використання типу даних bfloat16.
  3. Завантажте модель UNet на два ядра Neuron за допомогою torch_neuronx.DataParallel API. Це дозволяє виконувати паралельний висновок даних, що може значно прискорити роботу моделі.
  4. Завантажте інші частини моделі (text_encoder, decoder та post_quant_conv) на одне ядро ​​нейрона.

Потім ви можете запустити конвеєр, надавши вхідний текст як підказки. Нижче наведено кілька зображень, створених моделлю для підказок:

  • Портрет Рено Сечана, перо та чорнило, складні штрихові малюнки, художники Крейг Маллінс, Руан Цзя, Кентаро Міура, Грег Рутковскі, Лаундро

Збільште продуктивність Stable Diffusion і зменште витрати на логічні висновки за допомогою AWS Inferentia2 | Amazon Web Services PlatoBlockchain Data Intelligence. Вертикальний пошук. Ai.

  • Портрет старого вугільного шахтаря в 19 столітті, гарна картина з дуже деталізованим малюнком обличчя від Грега Рутковскі

Збільште продуктивність Stable Diffusion і зменште витрати на логічні висновки за допомогою AWS Inferentia2 | Amazon Web Services PlatoBlockchain Data Intelligence. Вертикальний пошук. Ai.

  • Замок посеред лісу

Збільште продуктивність Stable Diffusion і зменште витрати на логічні висновки за допомогою AWS Inferentia2 | Amazon Web Services PlatoBlockchain Data Intelligence. Вертикальний пошук. Ai.

Розмістіть Stable Diffusion 2.1 на AWS Inferentia2 і SageMaker

Розміщення моделей Stable Diffusion за допомогою SageMaker також потребує компіляції за допомогою Neuron SDK. Ви можете завершити компіляцію заздалегідь або під час виконання, використовуючи контейнери Large Model Inference (LMI). Попередня компіляція дозволяє швидше завантажувати модель і є кращим варіантом.

Контейнери SageMaker LMI пропонують два способи розгортання моделі:

  • Варіант без коду, де ми просто надаємо a serving.properties файл з необхідними конфігураціями
  • Принесіть власний сценарій висновків

Ми розглядаємо обидва рішення та переглядаємо конфігурації та сценарій висновку (model.py). У цій публікації ми демонструємо розгортання за допомогою попередньо скомпільованої моделі, що зберігається в Служба простого зберігання Amazon (Amazon S3) відро. Ви можете використовувати цю попередньо скомпільовану модель для своїх розгортань.

Налаштуйте модель за допомогою наданого сценарію

У цьому розділі ми покажемо, як налаштувати контейнер LMI для розміщення моделей Stable Diffusion. Ноутбук SD2.1 доступний на GitHub. Першим кроком є ​​створення пакета конфігурації моделі відповідно до наведеної нижче структури каталогів. Наша мета — використовувати мінімальні конфігурації моделі, необхідні для розміщення моделі. Потрібна структура каталогу така:

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

Далі створюємо обслуговуючі.властивості файл із такими параметрами:

%%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

Параметри визначають наступне:

  • option.model_id – Контейнери LMI використовують s5cmd для завантаження моделі з розташування S3, тому нам потрібно вказати місце, де знаходяться наші скомпільовані ваги.
  • option.entryPoint – Для використання вбудованих обробників ми вказуємо клас transformers-neuronx. Якщо у вас є спеціальний сценарій висновку, вам потрібно надати його замість цього.
  • option.dtype – Це вказує на завантаження ваг певного розміру. Для цієї публікації ми використовуємо BF16, який додатково зменшує наші вимоги до пам’яті порівняно з FP32 і завдяки цьому зменшує нашу затримку.
  • option.tensor_parallel_degree – Цей параметр визначає кількість прискорювачів, які ми використовуємо для цієї моделі. Прискорювач мікросхеми AWS Inferentia2 має два ядра Neuron, тому вказівка ​​значення 2 означає, що ми використовуємо один прискорювач (два ядра). Це означає, що тепер ми можемо створити кілька робітників, щоб збільшити пропускну здатність кінцевої точки.
  • option.engine – Тут встановлено значення Python, щоб вказати, що ми не будемо використовувати інші компілятори, такі як DeepSpeed ​​або Faster Transformer, для цього хостингу.

Принесіть власний сценарій

Якщо ви хочете додати свій власний сценарій висновку, вам потрібно видалити option.entryPoint від serving.properties. У цьому випадку контейнер LMI шукатиме a model.py файл у тому ж місці, що й файл serving.properties і використовуйте це для запуску висновків.

Створіть власний сценарій висновку (model.py)

Створення власного сценарію висновку відносно просте за допомогою контейнера LMI. Контейнер вимагає вашого model.py файл, щоб мати реалізацію такого методу:

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

Давайте розглянемо деякі з критичних областей додається блокнот, який демонструє функцію доведення власного сценарію.

Замініть cross_attention модуль з оптимізованою версією:

# 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')

Це назви скомпільованого файлу ваг, який ми використовували під час створення компіляцій. Не соромтеся змінювати назви файлів, але переконайтеся, що назви файлів ваших ваг відповідають тим, що ви тут вказали.

Потім нам потрібно завантажити їх за допомогою Neuron SDK і встановити їх у фактичних вагах моделі. Під час завантаження оптимізованих вагових коефіцієнтів UNet зверніть увагу, що ми також вказуємо кількість ядер Neuron, на які їх потрібно завантажити. Тут ми завантажуємо один прискорювач з двома ядрами:

# 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)

Запуск висновку з підказкою викликає об’єкт труби для створення зображення.

Створіть кінцеву точку SageMaker

Ми використовуємо Boto3 API для створення кінцевої точки SageMaker. Виконайте наступні дії:

  1. Створіть архів лише з обслуговуванням і необов’язковим model.py файли та завантажте їх на Amazon S3.
  2. Створіть модель за допомогою контейнера зображень і архіву моделі, завантаженого раніше.
  3. Створіть конфігурацію кінцевої точки, використовуючи такі ключові параметри:
    1. Використовуйте a ml.inf2.xlarge екземпляр
    2. Установка ContainerStartupHealthCheckTimeoutInSeconds до 240, щоб переконатися, що перевірка справності починається після розгортання моделі.
    3. Установка VolumeInGB до більшого значення, щоб його можна було використовувати для завантаження ваг моделі розміром 32 ГБ.

Створіть модель SageMaker

Після того як ви створите файл model.tar.gz і завантажите його в Amazon S3, нам потрібно створити модель SageMaker. Ми використовуємо контейнер LMI та артефакт моделі з попереднього кроку для створення моделі SageMaker. SageMaker дозволяє нам налаштовувати та вводити різні змінні середовища. Для цього робочого процесу ми можемо залишити все за замовчуванням. Перегляньте наступний код:

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

Створіть об’єкт моделі, який, по суті, створює контейнер блокування, який завантажується в екземпляр і використовується для висновків:

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},
)

Створіть кінцеву точку SageMaker

У цій демонстрації ми використовуємо екземпляр ml.inf2.xlarge. Нам потрібно встановити VolumeSizeInGB параметри, щоб забезпечити необхідний дисковий простір для завантаження моделі та ваг. Цей параметр застосовний до екземплярів, які підтримують Магазин еластичних блоків Amazon (Amazon EBS) вкладення томів. Ми можемо залишити для тайм-ауту завантаження моделі та перевірки працездатності при запуску контейнера більше значення, що дасть достатньо часу для контейнера, щоб отримати ваги з Amazon S3 і завантажити в прискорювачі AWS Inferentia2. Для отримання додаткової інформації див 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
        },
    ],
)

Нарешті, ми створюємо кінцеву точку SageMaker:

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

Викликати кінцеву точку моделі

Це генеративна модель, тому ми передаємо підказку, яку модель використовує для створення зображення. Корисне навантаження має тип JSON:

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

Порівняльний аналіз моделі Stable Diffusion на Inf2

Ми провели кілька тестів, щоб порівняти модель Stable Diffusion з типом даних BF 16 на Inf2, і ми можемо отримати значення затримки, які конкурують або перевищують деякі інші прискорювачі для Stable Diffusion. Це, у поєднанні з нижчою вартістю мікросхем AWS Inferentia2, робить цю пропозицію надзвичайно цінною.

Наступні цифри взято з моделі Stable Diffusion, розгорнутої на примірнику inf2.xl. Додаткову інформацію про витрати див Примірники Amazon EC2 Inf2.

Model дозвіл Тип даних Ітерації P95 Затримка (мс) Вартість Inf2.xl On-Demand за годину Inf2.xl (ціна за зображення)
Стабільна дифузія 1.5 512 × 512 bf16 50 2,427.4 $0.76 $0.0005125
Стабільна дифузія 1.5 768 × 768 bf16 50 8,235.9 $0.76 $0.0017387
Стабільна дифузія 1.5 512 × 512 bf16 30 1,456.5 $0.76 $0.0003075
Стабільна дифузія 1.5 768 × 768 bf16 30 4,941.6 $0.76 $0.0010432
Стабільна дифузія 2.1 512 × 512 bf16 50 1,976.9 $0.76 $0.0004174
Стабільна дифузія 2.1 768 × 768 bf16 50 6,836.3 $0.76 $0.0014432
Стабільна дифузія 2.1 512 × 512 bf16 30 1,186.2 $0.76 $0.0002504
Стабільна дифузія 2.1 768 × 768 bf16 30 4,101.8 $0.76 $0.0008659

Висновок

У цій публікації ми детально заглибились у компіляцію, оптимізацію та розгортання моделі Stable Diffusion 2.1 за допомогою екземплярів Inf2. Ми також продемонстрували розгортання моделей Stable Diffusion за допомогою SageMaker. Примірники Inf2 також забезпечують чудову цінову ефективність для Stable Diffusion 1.5. Щоб дізнатися більше про те, чому екземпляри Inf2 чудово підходять для генеративного ШІ та великих мовних моделей, див Інстанси Amazon EC2 Inf2 для недорогих, високопродуктивних генеративних висновків AI тепер загальнодоступні. Щоб дізнатися більше про продуктивність, див Продуктивність Inf2. Перегляньте додаткові приклади на GitHub репо.

Особлива подяка Метью Макклейну, Бені Хегедусу, Камрану Хану, Шруті Копаркару та Кінг Лану за перегляд і надання цінних матеріалів.


Про авторів

Збільште продуктивність Stable Diffusion і зменште витрати на логічні висновки за допомогою AWS Inferentia2 | Amazon Web Services PlatoBlockchain Data Intelligence. Вертикальний пошук. Ai.Вівек Гангасані є старшим архітектором рішень машинного навчання в Amazon Web Services. Він працює зі стартапами машинного навчання, створюючи та розгортаючи додатки AI/ML на AWS. Наразі він зосереджений на розробці рішень для MLOps, ML inference та low-code ML. Він працював над проектами в різних областях, включаючи обробку природної мови та комп’ютерне бачення.

Збільште продуктивність Stable Diffusion і зменште витрати на логічні висновки за допомогою AWS Inferentia2 | Amazon Web Services PlatoBlockchain Data Intelligence. Вертикальний пошук. Ai.KC Tung є старшим архітектором рішень в AWS Annapurna Labs. Він спеціалізується на навчанні та розгортанні великої моделі глибокого навчання в хмарі. Має ступінь доктора філософії. доктор молекулярної біофізики в Південно-Західному медичному центрі Техаського університету в Далласі. Він виступав на AWS Summits і AWS Reinvent. Сьогодні він допомагає клієнтам навчати та розгортати великі моделі PyTorch і TensorFlow у хмарі AWS. Він є автором двох книг: Дізнайтеся про TensorFlow Enterprise та Кишеньковий довідник TensorFlow 2.

Збільште продуктивність Stable Diffusion і зменште витрати на логічні висновки за допомогою AWS Inferentia2 | Amazon Web Services PlatoBlockchain Data Intelligence. Вертикальний пошук. Ai.Рупіндер Гревал є старшим архітектором рішень Ai/ML в AWS. Зараз він зосереджується на обслуговуванні моделей і MLO на SageMaker. До цієї посади він працював інженером машинного навчання, створюючи та розміщуючи моделі. Поза роботою він любить грати в теніс і їздити на велосипеді гірськими стежками.

Часова мітка:

Більше від AWS Машинне навчання