Повысьте производительность моделей Falcon с помощью Amazon SageMaker | Веб-сервисы Amazon

Повысьте производительность моделей Falcon с помощью Amazon SageMaker | Веб-сервисы Amazon

Какова оптимальная структура и конфигурация для размещения больших языковых моделей (LLM) для генеративных приложений искусственного интеллекта, генерирующих текст? Несмотря на обилие вариантов обслуживания LLM, на этот вопрос сложно ответить из-за размера моделей, различной архитектуры моделей, требований к производительности приложений и многого другого. Создатель мудреца Амазонки Контейнер вывода больших моделей (LMI) упрощает обслуживание LLM, объединяя множество различных структур и методов, которые оптимизируют развертывание LLM. Контейнер LMI имеет мощный стек обслуживания, называемый DJL-сервировка это не зависит от основного LLM. Он предоставляет параметры конфигурации на уровне системы, которые можно настроить для достижения наилучшей производительности инфраструктуры хостинга для данного LLM. Он также поддерживает последние оптимизации, такие как непрерывная пакетная обработка, также известная как итеративная пакетная обработка или скользящая пакетная обработка, которая обеспечивает значительное повышение производительности.

В более раннем послемы показали, как можно использовать контейнер LMI для развертывания моделей семейства Falcon в SageMaker. В этом посте мы демонстрируем, как улучшить пропускную способность и задержку обслуживания Falcon-40B с помощью таких методов, как непрерывная пакетная обработка. Мы также обеспечиваем интуитивное понимание параметров конфигурации, предоставляемых контейнером SageMaker LMI, что может помочь вам найти лучшую конфигурацию для вашего реального приложения.

Основы текстогенерирующего вывода для LLM

Давайте сначала рассмотрим несколько основных принципов выполнения логических выводов для LLM для генерации текста.

Прямой проход, активации и кэш KV

Учитывая входную последовательность токенов, они запускаются в forward pass по всем уровням LLM (например, Falcon) для генерации следующего токена. А forward pass относится к процессу передачи входных данных через нейронную сеть для получения выходных данных. В случае генерации текста прямой проход включает в себя передачу начального начального значения или контекста в языковую модель и генерацию следующего символа или токена в последовательности. Чтобы сгенерировать последовательность текста, процесс часто выполняется итеративно, то есть он повторяется для каждого шага или позиции в выходной последовательности. На каждой итерации модель генерирует следующий символ или токен, который становится частью сгенерированного текста, и этот процесс продолжается до тех пор, пока не будет сгенерирован текст желаемой длины.

Генерация текста с использованием таких языковых моделей, как Falcon или GPT. autoregressive. Это означает, что модель генерирует по одному токену за раз, при этом учитывая ранее сгенерированные токены. Другими словами, на каждой итерации модель принимает ранее сгенерированный текст в качестве входных данных и прогнозирует следующий токен на основе этого контекста. Как упоминалось в vLLM: простое, быстрое и дешевое обслуживание LLM с помощью PagedAttentionВ этом процессе авторегрессионного декодирования все входные токены в LLM создают свои тензоры ключа внимания и значений, и эти тензоры сохраняются в памяти графического процессора для генерации следующих токенов. Эти кэшированные тензоры ключей и значений часто называют KV cache.

Фазы предварительного заполнения и декодирования

В процессе авторегрессионного декодирования, подобном тому, который используется при генерации текста с помощью языковых моделей, таких как Falcon, обычно выделяются две основные фазы: prefill фаза и decode фаза. Эти этапы имеют решающее значение для создания связного и контекстуально релевантного текста.

Фаза предварительного заполнения включает в себя следующее:

  • Исходный контекст – Фаза предварительного заполнения начинается с начального контекста или начального текста, предоставленного пользователем. Этим начальным контекстом может быть предложение, фраза или даже одно слово. Он задает отправную точку для генерации текста и обеспечивает контекст для дальнейших действий.
  • Кондиционирование модели – Предоставленный контекст используется для определения языковой модели. Модель принимает этот контекст в качестве входных данных и генерирует следующий токен (слово или символ) в последовательности на основе понимания контекста.
  • Генерация токенов – Модель генерирует по одному токену за раз, предсказывая, что должно быть дальше в тексте. Этот токен добавляется к контексту, эффективно расширяя его.
  • Итерационный процесс – Процесс генерации токенов повторяется итеративно. На каждом этапе модель генерирует токен с учетом обновленного контекста, который теперь включает токены, созданные на предыдущих шагах.

Фаза предварительного заполнения продолжается до тех пор, пока не будет выполнено заранее определенное условие остановки. Этим условием может быть максимальная длина сгенерированного текста, конкретный токен, сигнализирующий об окончании текста, или любой другой критерий, установленный пользователем или приложением.

Фаза декодирования включает в себя следующее:

  • Завершение – После этапа предварительного заполнения у вас есть частично сгенерированный текст, который может быть неполным или обрезанным в какой-то момент. Фаза декодирования отвечает за завершение текста, чтобы сделать его связным и грамматически правильным.
  • Продолжение с последнего жетона – На этапе декодирования модель начинается с последнего токена, сгенерированного на этапе предварительного заполнения. Он использует этот токен в качестве начального контекста и генерирует следующий токен для продолжения текста.
  • Итеративное завершение – Как и на этапе предварительного заполнения, процесс генерации токенов снова является итеративным. Модель генерирует по одному токену за раз, учитывая предыдущие токены в последовательности.
  • Условия остановки – Фаза декодирования также имеет условие остановки, которое может быть таким же, как и на этапе предварительного заполнения, например, достижение максимальной длины или обнаружение маркера конца текста. При выполнении этого условия процесс генерации останавливается.

Сочетание фаз предварительного заполнения и декодирования позволяет моделям авторегрессии генерировать текст, который основывается на исходном контексте и создает последовательные, контекстуально релевантные и контекстуально согласованные последовательности текста.

Обратитесь к Распределенная система обслуживания для генеративных моделей на основе трансформаторов для подробного объяснения процесса.

Оптимизация пропускной способности с помощью динамической пакетной обработки

До сих пор мы говорили только об одном входе. На практике мы ожидаем, что нам придется иметь дело с несколькими запросами, поступающими случайным образом от клиентов приложений для вывода одновременно или в шахматном порядке. Традиционным способом базовую пакетную обработку можно использовать для увеличения пропускной способности и использования вычислительных ресурсов графического процессора. Пакетная обработка — это эффективное объединение числовых представлений более чем одного запроса в пакете и выполнение параллельных проходов авторегрессии вперед. Это интеллектуальное дозирование осуществляется на стороне обслуживания. Сервер DJLServing SageMaker LMI можно настроить для пакетной обработки нескольких запросов для их параллельной обработки, установив следующие параметры в обслуживающие.свойства:

  • max_batch_delay = 100 – Максимальная задержка пакетной агрегации в миллисекундах. Значение по умолчанию — 100 миллисекунд.
  • размер партии = 32 – Динамический размер пакета. Значение по умолчанию — 1.

По сути, это показывает, что DJLServing ставит запросы в очередь на 100 миллисекунд за раз, или, если количество запросов в очереди достигает указанного размера пакета, пакет будет запланирован для запуска на серверную часть для вывода. Это известно как dynamic batching. Он динамичен, поскольку размер пакета может меняться в зависимости от того, сколько запросов было добавлено за этот период времени. Однако, поскольку запросы могут иметь разные характеристики (например, некоторые запросы могут иметь форму 20 токенов на входе и 500 токенов на выходе, тогда как другие могут быть обратными, с 500 токенами на входе и только 20 токенами на выходе), некоторые запросы могут завершить обработку быстрее, чем другие в той же партии. Это может привести к недостаточному использованию графического процессора при ожидании завершения стадии декодирования всех текущих запросов в пакете, даже если в очереди есть дополнительные запросы, ожидающие обработки. Следующая диаграмма иллюстрирует этот процесс.

Простой визуальный элемент динамического пакетирования

Визуализация динамической пакетной обработки — обратите внимание на окна ожидания в конце запроса 2 и 3.

Оптимизация производительности за счет непрерывного дозирования

Доступно continuous batching, также известная как iterative or rolling При пакетной обработке мы используем преимущества различий между этапами предварительного заполнения и декодирования. Чтобы активировать непрерывную пакетную обработку, DJServing предоставляет следующие дополнительные конфигурации согласно serving.properties:

  • двигатель=MPI – Мы рекомендуем вам использовать механизм MPI для непрерывной пакетной обработки.
  • option.rolling_batch=auto или lmi-dist — мы рекомендуем использовать auto, поскольку он автоматически выберет наиболее подходящий пакетный алгоритм наряду с другими оптимизациями в будущем.
  • option.max_rolling_batch_size=32 – это ограничивает количество одновременных запросов. По умолчанию — 32.

При непрерывной пакетной обработке стек обслуживания (DJLServing) не ждет, пока все текущие запросы в пакете завершат этап декодирования. Скорее, во время логических перерывов (в конце одной итерации на этапе декодирования) он извлекает дополнительные запросы, ожидающие в очереди, пока текущий пакет все еще обрабатывается (отсюда и название прокатная партия). Он выполняет эту проверку на наличие ожидающих запросов в конце каждой итерации этапа декодирования. Помните, что для каждого запроса нам нужно запустить этап предварительного заполнения, за которым следует этап последовательного декодирования. Поскольку мы можем обрабатывать все токены из начального запроса запроса параллельно на этапе предварительного заполнения, каждый раз, когда поступает новый запрос, мы временно приостанавливаем этап декодирования текущих запросов пакета — мы временно сохраняем его KV-кеш. и активаций в памяти и запустить этап предварительного заполнения новых запросов.

Размер этого кэша можно настроить с помощью следующей опции:

Когда предварительное заполнение завершено, мы объединяем новые запросы и старые приостановленные запросы в новый скользящий пакет, который может параллельно приступить к этапу декодирования. Обратите внимание, что старые приостановленные запросы могут продолжить этап декодирования с того места, где они остановились, а новые запросы начнутся с первого нового токена.

Непрерывное или итеративное визуальное пакетирование

Визуальная непрерывная или итеративная пакетная обработка — обратите внимание, что время простоя заменяется отслеживанием запросов.

Возможно, вы уже поняли, что непрерывная пакетная обработка — это почти аналогичный подход, с помощью которого мы естественным образом распараллеливаем задачи в нашей повседневной жизни. У нас есть сообщения, электронные письма, телефонные уведомления (потенциально новые запросы), поступающие в случайное время (аналогично множеству запросов, поступающих случайным образом в шахматном порядке для графических процессоров). Все это происходит, пока мы выполняем наши текущие задачи — составляем электронные письма, кодируем, участвуем в собраниях (аналогично текущим задачам обработки на графических процессорах). В логических перерывах мы приостанавливаем выполнение текущих задач и проверяем уведомления, чтобы решить, требуются ли какие-либо действия с нашей стороны, и если да, мы добавляем их к нашим текущим задачам (реальный скользящий пакет) или поместите это в список дел (в очередь).

Собираем все вместе: как подумать об использовании памяти графических процессоров

Рекомендуется провести нагрузочное тестирование вашей модели, чтобы определить, какая конфигурация является наиболее экономически эффективной для вашего варианта использования в бизнесе. Чтобы лучше понять, давайте визуализируем объем памяти графических процессоров при загрузке модели и обработке последовательных запросов в скользящем пакете. В этом посте давайте предположим, что мы загружаем модель Falcon-40B в один из экземпляров типа G5, на которых установлены графические процессоры NVIDIA A10G, каждый из которых имеет 24 ГБ памяти. Обратите внимание, что аналогичное понимание применимо к типам экземпляров p3, p4 и p5, которые входят в состав графических процессоров серий V100, A100 и H100.

Ниже приводится обзор приблизительного значения общего объема памяти, необходимого для обслуживания Falcon-40B:

  • Размер модели = Количество параметров модели (40 миллиардов для Falcon-40B) x 4 байта на параметр (для FP32) = 160 ГБ
  • Приблизительный общий объем памяти, необходимый для загрузки Falcon-40B для вывода = Размер модели (= 160 ГБ) + KV-кэш (кэш внимания) (=*20 ГБ) + Дополнительные затраты памяти на ML Frameworks (приблизительно 2 ГБ)
ПамятьВизуальная

Визуализация памяти: понимание объема памяти загруженной модели Falcon-40B.

Для Falcon-40B, если мы сжимаем модель путем квантования модели до типа данных bfloat16 (2 байта), размер модели станет примерно 80 ГБ. Как видите, это все же больше, чем объем памяти, поддерживаемый одним ускорителем, поэтому нам необходимо принять метод разделения модели (шардинг) со специальным тензорный параллелизм (TP) подход и разделение модели на несколько ускорительных устройств. Предположим, мы выбрали g5.24xlarge, который имеет 4 графических процессора A10G. Если мы настроим DJLServing (serving.properties) следующим образом, мы можем ожидать, что 80 ГБ веса модели будут поровну разделены между всеми 4 графическими процессорами:

Доступно tensor_parallel_degree Если установлено значение 4, около 20 ГБ из 24 ГБ памяти графического процессора (приблизительно 84%) уже используются еще до того, как будет обработан один запрос. Остальные 16% графического процессора будут использоваться для кэша KV входящих запросов. Вполне возможно, что для вашего бизнес-сценария с его требованиями к задержке и пропускной способности 2–3 ГБ оставшейся памяти будет более чем достаточно. Если нет, вы можете увеличить размер экземпляра до g5.48xlarge, который имеет 8 графических процессоров и использует значение tensor_parallel_grade, равное 8. В таком случае только примерно 10 ГБ из доступных 24 ГБ памяти каждого графического процессора используется для весов модели, и мы есть около 60% оставшегося графического процессора для активаций и кеша KV. Интуитивно мы видим, что эта конфигурация может позволить нам иметь более высокую пропускную способность. Кроме того, поскольку теперь у нас есть больший буфер, мы можем увеличить max_rolling_batch_prefill_tokens и max_rolling_batch_size параметры для дальнейшей оптимизации пропускной способности. Вместе эти два параметра будут управлять предварительным распределением предзаполнений активации и кэша KV для модели. Большее число для этих двух параметров будет соотноситься с большей пропускной способностью, при условии, что у вас достаточно буфера для кэша KV в памяти графического процессора.

Непрерывная пакетная обработка с помощью PagedAttention

PagedAttention — это новый алгоритм оптимизации, разработанный Калифорнийским университетом в Беркли, который улучшает процесс непрерывной пакетной обработки, позволяя сделать кэш внимания (кэш KV) несмежным за счет выделения памяти в страницах или блоках фиксированного размера. Это вдохновлено концепциями виртуальной памяти и подкачки, используемыми операционными системами.

В соответствии с vLLM В документе кэш внимания каждой последовательности токенов разделен на блоки и сопоставлен с физическими блоками через таблицу блоков. Во время вычисления внимания ядро ​​PagedAttention может использовать таблицу блоков для эффективного извлечения блоков из физической памяти. Это приводит к значительному сокращению потерь памяти и позволяет увеличить размер пакета, повысить загрузку графического процессора и повысить пропускную способность.

Сравнение производительности

Чтобы обеспечить эффективное нагрузочное тестирование конфигурации развертывания, рекомендуется начать с рассмотрения бизнес-сценария и четкого определения характеристик ввода и вывода для приложения на основе LLM. Например, если вы работаете над вариантом использования сводных данных в колл-центре, входные данные могут состоять из более крупного текста, например стенограммы разговора из 500 токенов между агентом службы поддержки клиентов и клиентом, но выходные данные могут быть относительно меньшими, около 100. жетоны, представляющие собой краткое изложение стенограммы. С другой стороны, если вы работаете над сценарием генерации кода, входные данные могут содержать всего 15 токенов, например «написать эффективную реализацию на Python для описания всех ресурсов EC2, включая разбиение на страницы», но выходные данные могут быть гораздо короче. больше, достигая 500 токенов. Также важно учитывать, является ли достижение более низкой задержки или максимизация пропускной способности главным приоритетом для вашего конкретного сценария.

Получив полное представление о бизнес-сценарии, вы можете проанализировать и определить оптимальную конфигурацию для вашей среды хостинга. В этом контексте среда хостинга включает в себя различные ключевые элементы, включая тип экземпляра и другие параметры конфигурации, такие как tensor_parallel_grade, max_rolling_batch_size, max_rolling_batch_prefill_tokens, и более. Наша цель — определить наиболее эффективную настройку, соответствующую нашим требованиям ко времени отклика, пропускной способности и качеству выходных данных модели.

В нашем анализе мы сравнили производительность, чтобы проиллюстрировать преимущества непрерывной пакетной обработки по сравнению с традиционной динамической пакетной обработкой. Мы использовали конфигурации, подробно описанные в следующей таблице, в файлеserving.properties для динамической и итеративной пакетной обработки, используя контейнер LMI в SageMaker.

Динамическое пакетирование Непрерывное дозирование Непрерывная пакетная обработка с помощью PagedAttention

движок = Питон

option.model_id=tiiuae/falcon-40b

option.tensor_parallel_grade=8

option.dtype=fp16

пакетный_размер=4

max_batch_delay=100

option.trust_remote_code = правда

двигатель = MPI

option.model_id = {{s3_url}}

option.trust_remote_code = правда

option.tensor_parallel_grade = 8

option.max_rolling_batch_size = 32

option.rolling_batch = авто

option.dtype = fp16

option.max_rolling_batch_prefill_tokens = 1024

option.paged_attention = Ложь

двигатель = MPI

option.model_id = {{s3_url}}

option.trust_remote_code = правда

option.tensor_parallel_grade = 8

option.max_rolling_batch_size = 32

option.rolling_batch = авто

option.dtype = fp16

option.max_rolling_batch_prefill_tokens = 1024

option.paged_attention = Истина

Две конфигурации были протестированы для Falcon-40B с типом данных FP16, развернутым на ml.g5.48xlarge, в нескольких различных сценариях, которые представляют собой реальные приложения:

  • Небольшое количество входных токенов при большом количестве генерируемых токенов – В этом сценарии количество входных токенов было зафиксировано на уровне 32, и было создано 128 новых токенов.
Стратегия пакетной обработки Пропускная способность (токенов/сек) Задержка p90 (сек)
Динамическое пакетирование 5.53 58.34
Непрерывное дозирование 56.04 4.74
Непрерывная пакетная обработка с помощью PagedAttention 59.18 4.76
  • Большой ввод с небольшим количеством генерируемых токенов – Здесь мы фиксируем количество входных токенов на уровне 256 и предлагаем LLM суммировать входные данные до 32 токенов.
Стратегия пакетной обработки Пропускная способность (токенов/сек) Задержка p90 (сек)
Динамическое пакетирование 19.96 59.31
Непрерывное дозирование 46.69 3.88
Непрерывная пакетная обработка с помощью PagedAttention 44.75 2.67

Мы видим, что непрерывная пакетная обработка с помощью PagedAttention обеспечивает повышение пропускной способности в 10 раз в сценарии 1 и в 2.3 раза в сценарии 2 по сравнению с использованием динамической пакетной обработки в SageMaker при использовании контейнера LMI.

Заключение

В этом посте мы рассмотрели, как LLM используют память, и объяснили, как непрерывная пакетная обработка повышает пропускную способность с помощью контейнера LMI в SageMaker. Мы продемонстрировали преимущества непрерывного пакетирования для Falcon-40B с использованием контейнера LMI в SageMaker, продемонстрировав результаты тестов. Вы можете найти код на Репо GitHub.


Об авторах

Абхигян ШивадитьяАбхи Шивадитья — старший архитектор решений в AWS, работающий со стратегическими глобальными корпоративными организациями, чтобы облегчить внедрение сервисов AWS в таких областях, как искусственный интеллект, распределенные вычисления, сети и хранилища. Его опыт заключается в глубоком обучении в областях обработки естественного языка (NLP) и компьютерного зрения. Abhi помогает клиентам эффективно развертывать высокопроизводительные модели машинного обучения в экосистеме AWS.

Повысьте производительность моделей Falcon с помощью Amazon SageMaker | Веб-сервисы Amazon PlatoBlockchain Data Intelligence. Вертикальный поиск. Ай.Дхавал Патель является главным архитектором машинного обучения в AWS. Он работал с организациями, начиная от крупных предприятий и заканчивая стартапами среднего размера, над проблемами, связанными с распределенными вычислениями и искусственным интеллектом. Он специализируется на глубоком обучении, включая домены NLP и Computer Vision. Он помогает клиентам добиться высокопроизводительного логического вывода модели в SageMaker.

Повысьте производительность моделей Falcon с помощью Amazon SageMaker | Веб-сервисы Amazon PlatoBlockchain Data Intelligence. Вертикальный поиск. Ай.Пинак Паниграхи работает с клиентами над созданием решений на основе машинного обучения для решения стратегических бизнес-задач на AWS. Когда он не занят машинным обучением, его можно найти в походе, читающим книгу или смотрящим спортивные состязания.

Повысьте производительность моделей Falcon с помощью Amazon SageMaker | Веб-сервисы Amazon PlatoBlockchain Data Intelligence. Вертикальный поиск. Ай.Абхи Содхани занимает должность старшего архитектора решений AI/ML в AWS, где он специализируется на предоставлении клиентам технических знаний и рекомендаций по генеративным решениям AI и ML. Его основная задача — помочь цифровым предприятиям реализовать весь потенциал технологий генеративного искусственного интеллекта и машинного обучения, что позволит им эффективно достигать своих бизнес-целей. Помимо своих профессиональных усилий, Абхи проявляет сильную страсть к интеллектуальным занятиям, таким как чтение, а также к занятиям, способствующим физическому и психическому благополучию, таким как йога и медитация.

Повысьте производительность моделей Falcon с помощью Amazon SageMaker | Веб-сервисы Amazon PlatoBlockchain Data Intelligence. Вертикальный поиск. Ай.Цин Лан является инженером-разработчиком программного обеспечения в AWS. Он работал над несколькими сложными продуктами в Amazon, включая высокопроизводительные решения для логического вывода машинного обучения и высокопроизводительную систему ведения журналов. Команда Цин успешно запустила первую модель с миллиардом параметров в Amazon Advertising с очень низкой задержкой. Цин обладает глубокими знаниями по оптимизации инфраструктуры и ускорению глубокого обучения.

Отметка времени:

Больше от Машинное обучение AWS