Глубокое погружение в масштабный инференс LLM — Харшул Джайн (Audible) и Танмай Сах (Независимый исследователь ИИ)

AAI Engineer
컴퓨터/소프트웨어경제 뉴스AI/미래기술

스크립트

00:00:00Итак, всем добрый день. Меня зовут Харшал Джайн, а это Танмиш. И мы
00:00:21хотели бы поприветствовать всех на этом двухчасовом воркшопе по инференсу LLM.
00:00:26Цель этого воркшопа — понять эту область с базовых
00:00:33принципов, погрузиться в нее глубже и разобраться, что происходит во всей
00:00:39индустрии. Немного предыстории о нас. Я старший разработчик ПО в
00:00:47Audible. Последние пять лет я занимаюсь созданием платформ данных ML/AI, а
00:00:53помимо этого пишу открытое руководство по инференсу LLM. И
00:00:59Танмай — старший специалист по количественному моделированию в Xi'an's Bank Corporation. Он
00:01:06недавно защитил докторскую и ведет активные исследования в области агентных
00:01:12верификаторов и моделей мира. Давайте быстро поднимем руки. Кто здесь впервые сталкивается с инференсом LLM?
00:01:24Хорошо, отлично. А кто уже развертывал такие модели в продакшене? Кто
00:01:33занимался их тюнингом и обслуживанием продакшн-трафика? Отлично. Этот
00:01:42воркшоп рассчитан на начинающих и тех, кто уже имеет средний уровень. Все
00:01:48слайды и упражнения находятся в репозитории, я скоро им поделюсь. Вот краткая
00:01:56повестка дня нашего воркшопа. Мы начнем с постановки проблемы. Попробуем
00:02:01понять основные болевые точки, связанные с инференсом LLM. Затем разберем причины
00:02:08возникновения этих проблем и выстроим фундамент. После этого мы перейдем к двум
00:02:14видам оптимизации: оптимизации самих моделей и оптимизации
00:02:19сервиинга. Затем мы познакомимся с различными серверами для инференса,
00:02:25которые доступны для развертывания решений LLM в продакшене. Покажем результаты
00:02:32бенчмарков и схему принятия решений о том, какой движок выбрать.
00:02:39Отлично. Чтобы понять болевые точки, сначала нужно узнать, что такое инференс LLM. Ну,
00:02:47многие из нас, наверное, уже знают это. Но в общем, всё, что вы просите сделать ваш ИИ,
00:02:55будь то генерация видео, аудио, анализ текста, медицинских отчетов или
00:03:02налоговых счетов, всё это представляет собой инференс LLM. И сегодня этот рынок оценивается примерно в 23 миллиарда долларов.
00:03:12Недавно в Semi-analysis сообщили, что если обрабатывать поисковые запросы Google с помощью LLM, потребуется колоссальная сумма в 36 миллиардов долларов.
00:03:25При этом стоимость одного запроса должна быть меньше 0,5 цента, чтобы поисковый бизнес оставался прибыльным.
00:03:33С другой стороны, Business Insider отмечает, что ИИ нужно внедрять грамотно, и каждому придется начать аудит и учет использования токенов.
00:03:43И всё это происходит почему? Потому что аппаратные ресурсы ограничены, вычисления обходятся дорого, а инференс дорог.
00:03:50И по мере роста потребности в использовании ИИ стоимость этого инференса растет всё больше и больше.
00:04:03Эта статистика старая, от OpenAI, но она все еще актуальна.
00:04:11Если посмотреть на затраты на обучение GPT-3, они составили около 4,6 миллиона долларов. Это были разовые расходы.
00:04:19Но если вы посмотрите на расходы на инференс, они носят постоянный характер, поскольку это операционные затраты, которые масштабируются с каждым новым пользователем, с каждым токеном и с каждой сессией, запускаемой в ИИ.
00:04:36И с этим можно бороться лишь двумя способами. Первый способ — сократить использование токенов.
00:04:47Альтернатива — попытаться оптимизировать решения для инференса как поставщик услуг инференса для ваших клиентов и для себя самого.
00:04:58И из-за этого мы видим, как постоянно появляется всё больше и больше новых решений.
00:05:06Поэтому идея заключается в том, чтобы заложить те основы, которые помогут нам понимать и оценивать любые новинки.
00:05:18Итак, для начала мы проведем короткую демонстрацию различных болевых точек, связанных с инференсом.
00:05:28У нас есть репозиторий.
00:05:31Вы можете клонировать его или открыть прямо на GitHub.
00:05:36Он называется «LLM inference at scale».
00:05:39Немного предыстории: около четырех месяцев назад, когда я ничего не знал об инференсе LLM, я начал его изучать.
00:05:46Я заметил, что множество ресурсов разбросано повсюду.
00:05:49Поэтому мы начали собирать всё вместе в одном месте, чтобы это принесло пользу людям.
00:05:55Давайте я выйду из режима слайд-шоу и перейду в расширенный режим.
00:06:11Да, в этом репозитории, если вы посмотрите на файл README, там есть ссылка на слайды.
00:06:27Это будет папка, где лежит файл PPTX и отчет по бенчмаркам.
00:06:34Вы всегда можете скачать их, а для демонстрации у нас есть пара блокнотов Jupyter.
00:06:43Мы сотрудничаем с Molab, альтернативой Google Colab, которая предоставляет бесплатный графический процессор RTX 6000.
00:06:54Это видеокарта со 100 ГБ оперативной памяти, и мы уже настроили эти блокноты, чтобы вам было удобно экспериментировать, а все ресурсы и настройки уже подготовлены заранее.
00:07:09Мы начнем с простой демонстрации А.
00:07:16Пожалуй, сейчас я посмотрю.
00:07:31Да, когда дело доходит до инференса, вам нужно запустить его на определенной модели, верно?
00:07:40Поэтому для нашего воркшопа мы используем простую модель Mistral 7B.
00:07:45Это небольшая модель размером около 15 ГБ.
00:07:49Мы собираемся загрузить ее в графический процессор.
00:07:53И также посмотрим на некоторые характеристики GPU.
00:07:58Видим, что мы работаем на 6000 Blackwell.
00:08:01И вы можете подумать, что я не запускаю ячейки, потому что не доверяю конференции по Wi-Fi.
00:08:08Да, поэтому я просто пройдусь по результатам, которые мы получили ранее.
00:08:18У нас есть GPU с объемом памяти 102 ГБ.
00:08:22Теперь первое, что приходит мне в голову: как выглядит потребление памяти при выполнении инференса LLM?
00:08:31Я загружаю эту модель и вижу: так, здесь занято 15 ГБ.
00:08:37То есть у меня остается примерно 87,5 ГБ.
00:08:40И теперь, когда я делаю инференс, я замечаю, что чем больше входных данных я передаю, тем больше памяти мне требуется.
00:08:52Она растет медленно, но все же растет.
00:08:56Представьте, если длина контекста составляет около 4 000, 16 000 или 32 000 токенов.
00:09:03В таком случае объем памяти может значительно увеличиться, и вы можете столкнуться с проблемами нехватки памяти (OOM).
00:09:12Безусловно, это ваша первая проблема — рост памяти с увеличением количества токенов.
00:09:18В виде простой визуализации это выглядит следующим образом.
00:09:24Вторая проблема, с которой вы столкнетесь, — время генерации первого токена очень, очень велико.
00:09:32Мы измеряем это метрикой под названием TTFT.
00:09:35Это сокращение.
00:09:37И когда вы пытаетесь измерить TTFT в зависимости от размера входа, вы увидите, что чем длиннее контекст, тем выше задержка TTFT.
00:09:52Итак, у нас есть две проблемы.
00:09:54Память растет вместе с размером токенов.
00:09:56TTFT увеличивается вместе с размером токенов.
00:09:59Правда, не токенов, а контекста.
00:10:07И третье — это пропускная способность.
00:10:09Пропускная способность — это то, сколько токенов вы можете обслужить в секунду.
00:10:13И сколько пользователей вы можете обслужить в секунду.
00:10:16Если вы возьмете самую простую, ванильную реализацию на своей локальной машине, она будет работать очень последовательно.
00:10:24Поэтому, если вы отправите пять запросов, все они будут обрабатываться последовательно, а не параллельно.
00:10:31И из-за этого выполнение вашего запроса занимает больше времени, если у вас много пользователей.
00:10:40Вот эти три проблемы.
00:10:43Есть и четвертая.
00:10:44Я здесь о ней не рассказывал.
00:10:45Наверное, мы придем к этому пониманию по мере продвижения вперед.
00:10:48Но давайте запомним эти три проблемы: память, TTFT и пропускная способность.
00:10:55Отлично.
00:10:56Я вернусь к слайдам.
00:11:02Хорошо.
00:11:03Идеально.
00:11:04Так что должно быть это.
00:11:17Видно?
00:11:18Да.
00:11:19Видно.
00:11:20Видно.
00:11:21Да.
00:11:22Видно.
00:11:23Видно.
00:11:24Видно.
00:11:25Да.
00:11:26Видно.
00:11:27Видно.
00:11:28Да.
00:11:29Видно.
00:11:30Да.
00:11:31Видно.
00:11:32Да.
00:11:33Видно.
00:11:34Да.
00:11:35Видно.
00:11:36Видно.
00:11:37Да.
00:11:38Видно.
00:11:39Да.
00:11:40Видно.
00:11:41Да.
00:11:42Видно.
00:11:43Да.
00:11:44Видно.
00:11:45Да.
00:11:46Да.
00:11:47Итак, в этом репозитории, если вы посмотрите на папку воркшопа, то увидите файл README, а в самом README
00:11:55содержатся все ссылки, слайды и демоверсии.
00:12:01Это работает?
00:12:06Хорошо.
00:12:07Идеально.
00:12:09Хорошо.
00:12:10Идеально.
00:12:16Хорошо.
00:12:17Давайте начнем разбираться с основами.
00:12:19Давайте начнем понимать причины, стоящие за этими болевыми точками.
00:12:25И для этого нам нужно взглянуть на этот пайплайн инференса.
00:12:32Итак, у нас есть входной текст.
00:12:35В этом тексте может быть любое количество слов.
00:12:38Вы преобразуете их в токены.
00:12:41Для простоты можно считать, что одно слово равно одному токену.
00:12:46Затем вы преобразуете их в эмбеддинги и отправляете в трансформеры.
00:12:53Там 32 слоя трансформера, но это специфично для Mistral 7.
00:12:58У разных моделей разное количество слоев.
00:13:01И затем вы генерируете новый токен.
00:13:04И этот токен по сути возвращается на вход.
00:13:06Затем вы генерируете следующий токен, и это продолжается.
00:13:09Теперь во всей этой конвейерной обработке вы увидите, что 95% вычислений уходит на эти слои трансформера.
00:13:18Поэтому стоит посмотреть на то, что происходит внутри этого слоя трансформера.
00:13:24Внутри этого слоя трансформера есть и другие слои.
00:13:28У вас есть слой нормализации.
00:13:30У вас есть слой внимания.
00:13:32У вас есть полносвязный слой и так далее.
00:13:35И слой внимания, я думаю, стал очень и очень известным.
00:13:40Все знают работу “Attention is all you need”.
00:13:42Думаю, это всем хорошо известно.
00:13:44Итак, внимание — это наиболее ресурсоемкий слой.
00:13:48И нам нужно понять, что происходит внутри этого слоя внимания.
00:13:53Итак, что делает внимание?
00:13:56Если у вас есть входной текст, ему нужно найти оценки внимания каждого токена по отношению ко всем предыдущим токенам.
00:14:05И чтобы сделать это, ему нужно спроецировать каждый токен в пространство ключей, запросов и значений.
00:14:14Так что проще говоря, поймите вот что.
00:14:20Если у вас 10 токенов, то ему нужно 10 разных векторов запросов, ключей и значений.
00:14:26Если токенов 100, вам понадобятся 100 векторов ключей и значений.
00:14:31Если токенов 1000, вам понадобятся 1000 векторов ключей и значений.
00:14:35И таким образом количество векторов ключей и значений увеличивается с ростом размера входа.
00:14:45И если вы рассчитаете размер KV на токен для Mistral 7B, он составит 131 KV.
00:14:54Это потому, что у вас есть два вектора: K и V.
00:14:59Вам нужно умножить размер.
00:15:02Один вектор имеет размерность 128.
00:15:04Вам нужно умножить это на 32 слоя трансформера.
00:15:08И затем вам нужно умножить это на головы KV.
00:15:11Для Mistral 7b это головы KV.
00:15:15Это не 32, потому что он использует другой тип механизма внимания, о котором мы обязательно поговорим.
00:15:23Но да, размер KV на один токен составляет около 131 KV.
00:15:30Теперь представьте, что у вас контекст на 4K, тогда этот размер становится равным примерно половине гигабайта.
00:15:37Если сделать контекст на 16K, этот размер составит 2,1 ГБ.
00:15:42Теперь умножьте это на количество пользователей.
00:15:45Допустим, вы можете обслуживать нескольких пользователей одновременно.
00:15:49В то же время на этом GPU у вас может получиться 42 ГБ с контекстом 4K и 80 пользователями.
00:15:58И если ваш GPU имеет объем всего, скажем, 24 ГБ, у вас уже заканчивается память.
00:16:04Поэтому вы не можете обслуживать столько пользователей с таким контекстом.
00:16:11Чтобы визуализировать это, посмотрите на память GPU.
00:16:14В памяти GPU хранятся веса модели, которые являются довольно фиксированными.
00:16:19Это предварительно обученные веса.
00:16:21Есть также фиксированные накладные расходы.
00:16:24Они тоже меняются, но не так сильно.
00:16:29В целом можно считать их фиксированными.
00:16:32И есть оставшаяся память.
00:16:35Эта оставленная память используется вашей KV-памятью, то есть векторами ключей и значений.
00:16:41Допустим, у вас один пользователь.
00:16:46Вы можете обслуживать только такое количество векторов ключей и значений или токенов, которое помещается во всю эту оставшуюся память в 80 ГБ.
00:17:00Мы можем показать это и на простом примере.
00:17:07Хорошо, отлично.
00:17:08Хорошо, отлично.
00:17:08Дайте посмотреть, смогу ли я это запустить.
00:17:14Хорошо, отлично.
00:17:15Дайте посмотреть, смогу ли я это запустить.
00:17:15Куда это делось?
00:17:15Хорошо, отлично.
00:17:16Дайте посмотреть, смогу ли я это запустить.
00:17:21Куда это делось?
00:17:22Хорошо, отлично.
00:17:23Хорошо, отлично.
00:17:24Да.
00:17:25Да.
00:17:25Итак, вы увидите... дайте посмотреть, смогу ли я это запустить.
00:17:31Дайте посмотреть, смогу ли я это запустить.
00:17:33Дайте посмотреть, смогу ли я это запустить.
00:17:34Дайте посмотреть, смогу ли я это запустить.
00:17:35Дайте посмотреть, смогу ли я это запустить.
00:17:36Дайте посмотреть, смогу ли я это запустить.
00:17:37Хорошо, отлично.
00:17:38Да.
00:17:39Итак, вы увидите, что GPU подключен.
00:17:43Хорошо, отлично.
00:17:44Да.
00:17:45Итак, вы увидите, что GPU подключен.
00:17:56Итак, здесь мы просто пытаемся подтвердить объем памяти на основе расчетов и нашей интуиции.
00:18:13которую мы выстроили.
00:18:14Память модели составляет, скажем, если у вас 7 миллиардов параметров и вы используете
00:18:1916-битную точность,
00:18:20ваш общий объем памяти составит 14,6 ГБ.
00:18:23Вы можете проверить это с помощью математических расчетов.
00:18:27Итак, если сделать все эти расчеты, получается 14,6 ГБ.
00:18:33Теперь переходим к KV и размеру KV.
00:18:37Итак, этот размер KV составляет примерно 131 KV на токен.
00:18:42И если вы произведете эти расчеты и попытаетесь это визуализировать...
00:18:47О, конечно.
00:18:52Подождите.
00:18:53Хорошо.
00:18:54И давайте просто визуализируем это.
00:19:07Хорошо, отлично.
00:19:10Отлично.
00:19:11Да.
00:19:12Итак, это график использования памяти.
00:19:15Как видите, по мере увеличения контекста потребление памяти растет.
00:19:21Другой важный момент заключается в том, что с ростом числа пользователей память также увеличивается.
00:19:28Поэтому, если вы хотите обслуживать 160 пользователей на одном GPU, вы можете поддерживать
00:19:37лишь меньшую длину контекста.
00:19:40Всегда существует компромисс между длиной контекста, которую вы можете обслуживать, и тем, сколько затрат
00:19:47вы можете сэкономить, разместив нескольких пользователей или одновременных пользователей на одном GPU.
00:19:54Так что вам всегда приходится идти на этот компромисс.
00:19:57И мы разберем это на следующих слайдах.
00:20:06Не могли бы вы повторить, пожалуйста?
00:20:10Прошу прощения.
00:20:11Я вас не слышу.
00:20:12Видите ли вы другой пул с разной длиной контекста, чтобы можно было обслуживать нужную память
00:20:25для правильного...?
00:20:26Да.
00:20:27Круто.
00:20:28Круто.
00:20:29Хорошо.
00:20:30Хорошо.
00:20:31Итак, вернемся назад.
00:20:32Итак, это была память.
00:20:33Нам нужно понять, почему у нас было большее время до первого токена при увеличении длины контекста.
00:20:53ов.
00:20:54Для этого нам нужно понять две фазы инференса.
00:20:58Эти фазы называются фазой предварительного заполнения (pre-fill) и фазой декодирования.
00:21:01Думаю, вы все видели много статей, но мы просто хотели это объяснить.
00:21:06Итак, когда вы отправляете множество входных токенов, вы хотите построить упомянутые ключи и векторы значений для всех токенов.
00:21:20Затем вы хотите вычислить оценки внимания каждого токена по отношению к предыдущим.
00:21:27Вся эта операция очень сильно завязана на матричные вычисления.
00:21:31Это очень ресурсоемкая вычислительная операция.
00:21:34И мы все знаем, что GPU отлично подходят для тяжелых вычислительных нагрузок.
00:21:41Поэтому мы называем фазу префилла ограниченной вычислительной мощностью (compute-bound).
00:21:46И ее выполнение занимает некоторое время.
00:21:49Время, необходимое для завершения этой фазы, и есть время до первого токена (TTFT).
00:21:55Так что если у вас больше входных токенов, вам нужно генерировать больше векторов ключ-значение.
00:22:02Вам нужно выполнять гораздо больше вычислений внимания.
00:22:05И из-за этого время TTFT становится все более медленным.
00:22:12В то время как при генерации одного токена вам нужно продолжать делать это для других токенов, последовательно, один за другим.
00:22:20Но в этом процессе каждый раз приходится выстраивать векторы ключей и значений для всех предыдущих токенов, что аналогично этапу пре-филла.
00:22:30То есть вы формировали векторы ключей и значений там, и делаете это здесь.
00:22:34Но на этапе декодирования вы вычисляете матрицу внимания только для нового токена.
00:22:40И именно поэтому он требует гораздо меньше вычислительных ресурсов.
00:22:45Кроме того, его называют ограниченным по пропускной способности памяти.
00:22:48Чуть позже мы разберем, почему его так называют.
00:22:54Итак, на классической временной шкале фазы пре-филла и декодирования выглядят следующим образом.
00:22:59Время, затрачиваемое на пре-филл, — это время до получения первого токена.
00:23:03А время, затрачиваемое на каждый шаг декодирования, — это, по сути, ваша задержка между токенами.
00:23:12Это четвертая метрика, о которой вам нужно беспокоиться.
00:23:18Сколько времени уходит на шаг декодирования?
00:23:21Хорошо.
00:23:22Ладно.
00:23:23Отлично.
00:23:24Теперь почему шаг декодирования или само декодирование занимает время?
00:23:34И почему эту операцию называют ограниченной по памяти?
00:23:38Давайте попробуем разобраться в этом.
00:23:40Чтобы понять это, нам нужно посмотреть, как в общих чертах устроена работа с матрицами на GPU.
00:23:47Итак, у графического процессора есть два типа памяти.
00:23:50У вас есть память с высокой пропускной способностью.
00:23:52И у вас есть разделяемая память.
00:23:55Память с высокой пропускной способностью имеет больший объем, но меньшую скорость передачи.
00:24:01Под меньшей пропускной способностью я имею в виду, что данные из нее передаются с меньшей скоростью.
00:24:06По сравнению с разделяемой памятью: она меньше по размеру, но обладает очень и очень высокой пропускной способностью.
00:24:13Это значит, что вы можете передавать данные в нее и обратно с огромной скоростью.
00:24:19Поэтому, когда вам нужно выполнить матричные вычисления, вы должны извлекать данные кусками из памяти с высокой пропускной способностью.
00:24:27Загрузить их в разделяемую память.
00:24:30Выполнить вычисления.
00:24:32И записать результат обратно в память с высокой пропускной способностью.
00:24:38На этапе пре-филла эту матричную операцию требуется выполнить всего один раз.
00:24:46Но на этапе декодирования вам приходится делать такие вычисления снова и снова, поскольку каждый отдельный токен генерируется последовательно.
00:24:59И в результате неважно, насколько быстро идет декодирование, ведь вы можете переносить данные из основной памяти в разделяемую только с определенной скоростью.
00:25:14Потому что вы ограничены пропускной способностью основной памяти.
00:25:18И именно это определяет предел генерации токенов — с какой скоростью вы реально можете выдавать токены на этапе декодирования.
00:25:32Если посмотреть на график производительности (Roofline), то слева находится область, ограниченная пропускной способностью памяти.
00:25:42Математически она определяется арифметической интенсивностью.
00:25:47Арифметическая интенсивность — это количество операций с плавающей точкой, выполняемых на один байт передаваемых данных.
00:25:55На этапе декодирования, поскольку вы передаете много данных — например, векторы ключей и значений всех предыдущих токенов, веса модели,
00:26:08но выполняете при этом меньше вычислений, так как считаете внимание только для одного токена,
00:26:13арифметическая интенсивность оказывается очень низкой.
00:26:18А на этапе пре-филла вы передаете данные один раз, но затем выполняете огромный объем вычислений.
00:26:27Поэтому его арифметическая интенсивность очень высока.
00:26:30Теперь вам с математической точки зрения понятно, почему арифметическая интенсивность пре-филла намного выше, чем у декодирования.
00:26:44Хорошо.
00:26:46Это еще одна небольшая демонстрация.
00:26:51Так.
00:26:52Каждый раз мне нужно...
00:26:53Хорошо.
00:26:54Ладно.
00:26:55Отлично.
00:26:56Надеюсь, с этим все понятно.
00:26:58Итак, да.
00:26:59Мы снова загружаем модель.
00:27:04Теперь перейдем к затратам на пре-филл.
00:27:09По сути, мы берем входной текст и пытаемся оценить время, которое требуется на выполнение шага пре-филла.
00:27:22Мы видим, что с увеличением размера входных токенов время пре-филла возрастает.
00:27:28И именно по этой причине увеличивается время до первого токена.
00:27:33Затем переходим ко времени декодирования.
00:27:36Время декодирования в среднем остается примерно на одном уровне.
00:27:41И если не учитывать холодный старт, время декодирования находится примерно на уровне средней линии.
00:27:50Хотя оно по-прежнему зависит от размера входных данных.
00:27:57Нельзя сказать, что это константа.
00:28:00Это происходит потому, что по-прежнему нужно вытягивать из памяти векторы ключей и значений для всех предыдущих токенов.
00:28:07Поэтому на шаге декодирования все равно наблюдается небольшой рост времени.
00:28:15И перед нами классический график производительности (Roofline).
00:28:20Так.
00:28:22Хорошо.
00:28:23Презентация.
00:28:24Ладно.
00:28:25Хорошо.
00:28:26Понятно.
00:28:27А теперь давайте разберем аспект пропускной способности.
00:28:43Вам нужно понять, скольких пользователей вы реально сможете обслуживать.
00:28:48Мы уже видели схему памяти GPU, где показано, что часть памяти остается свободной для роста векторов ключей и значений.
00:28:56Хорошо.
00:28:57Допустим, у вас всего один пользователь.
00:29:01Каков суммарный объем кэша KV, который вы можете поддержать?
00:29:09Он определяется лимитом контекста.
00:29:11Максимальное число пользователей, которое вы можете обслужить — это доступный объем памяти GPU, деленный на размер KV-данных на одного пользователя.
00:29:25В результате вычислений мы получаем количество одновременных пользователей.
00:29:32Теперь предположим, что GPU и модель зафиксированы, поэтому размер KV на один токен является постоянным.
00:29:46Остаются только два изменяющихся параметра: контекст и число одновременных пользователей.
00:29:53Если вы хотите обслуживать больше пользователей одновременно, вам придется уменьшить длину контекста.
00:29:57А уменьшение длины контекста может ухудшить качество.
00:30:02Таким образом, это два параметра, между которыми приходится искать баланс.
00:30:09Но можете ли вы на практике обслужить максимальное число одновременных пользователей?
00:30:17В идеальном мире — пожалуй, нет, поскольку у каждого бизнеса есть соглашение об уровне обслуживания (SLO) по задержке.
00:30:27Помните, я говорил, что время декодирования возрастает при увеличении объема входных данных.
00:30:37Оно также растет при увеличении числа пользователей.
00:30:40В конечном итоге ваша задержка между токенами тоже увеличивается при большем размере батча.
00:30:51Время до первого токена (TTFT) также страдает.
00:30:53Появляется третий параметр, о котором нужно беспокоиться — это задержка.
00:30:58Итак, у нас есть три измерения: качество, задержка и пропускная способность.
00:31:04Получается такой треугольник компромиссов, где приходится выбирать между ними.
00:31:11Для премиального чат-приложения вы, безусловно, захотите поставить на первое место качество и задержку.
00:31:21Вы не захотите заставлять пользователей ждать слишком долго, по крайней мере, минимизируя задержки.
00:31:30Вы можете пожертвовать количеством поддерживаемых на GPU пользователей и взять эти расходы на себя, проявляя заботу о клиентах.
00:31:39А если речь идет об асинхронных задачах агентов, то здесь приоритетом будут качество и пропускная способность.
00:31:53Поскольку это долго выполняющиеся задачи.
00:31:56И вам захочется выполнять как можно больше задач параллельно, но с очень высоким качеством.
00:32:06И часто нам кажется: если GPU очень дорогая, значит, она нам не подходит.
00:32:19Но оказывается, что именно она может обеспечить наименьшую стоимость за миллион токенов.
00:32:27Однако нужно уметь доверять своим расчетам максимального числа пользователей и делать эти оценки правильно.
00:32:40У нас есть... сейчас я... отлично.
00:32:55Что касается калькулятора емкости, здесь есть ссылка на Colab, так как я с ним работал.
00:33:01Мне пришлось уходить от всей библиотеки виджетов, а времени не было.
00:33:16Поэтому из лени я просто взял Colab.
00:33:20Прошу прощения у моего лаба.
00:33:23Итак, моя видеопамять подключена.
00:33:34Хорошо.
00:33:45Видимо, Wi-Fi.
00:33:46Ладно, отлично.
00:34:02Здесь мы указали различные видеокарты, их объем VRAM, пропускную способность, операции с плавающей точкой и стоимость в час.
00:34:11Затем мы создали простой калькулятор емкости.
00:34:19Это визуализатор KV, где при увеличении количества токенов видно, как растет размер кэша KV.
00:34:29А при увеличении числа пользователей размер увеличивается гораздо быстрее.
00:34:37Давайте запустим этот калькулятор емкости.
00:34:47Мы выбрали модель с 7 миллиардами параметров.
00:34:56Установили точность FP16.
00:35:01При выборе GPU нужно сначала зафиксировать тот параметр, который волнует вас больше всего.
00:35:15Для премиального чата, как я упоминал, это определенно задержка.
00:35:21А для асинхронных задач вторым параметром является минимальный размер батча, который нужно обрабатывать на одной GPU.
00:35:31Сначала нужно зафиксировать эти значения.
00:35:34Итак, я рассуждаю применительно к премиальному чат-приложению.
00:35:39Я могу ориентироваться на задержку в 10 миллисекунд.
00:35:44Минимальный размер батча меня не особо волнует.
00:35:46То есть меня устроит, пожалуй, двойка.
00:35:53Хорошо.
00:35:54Пусть будет около семи одновременных пользователей на одной GPU.
00:35:59Лимит контекста также очень важен для меня, поскольку я хочу заботиться и о качестве.
00:36:07И я вижу определенные варианты среди GPU.
00:36:10Например, H100 на 80 ГБ стоит около 8 долларов в час.
00:36:15А как насчет RTX 3090?
00:36:19Или нет?
00:36:20Да.
00:36:21То есть это примерно 10 долларов в час.
00:36:24Итак, если проделать все те вычисления пропускной способности, о которых мы говорили ранее, вы сможете узнать стоимость миллиона токенов.
00:36:34Это может быть очень-очень, это может быть меньше.
00:36:37Поэтому вам нужно проводить такие расчеты, фиксируя эти параметры, и выбирать GPU так, чтобы снизить расходы на инференс.
00:36:49Так что это хотя бы первый шаг, который можно сделать для оптимизации инференса.
00:36:56Хорошо.
00:37:01Итак, следующий слайд.
00:37:04Позвольте мне.
00:37:08Ладно, отлично.
00:37:10И теперь следующий пункт — оптимизация моделей.
00:37:15Мы в основном заложили фундамент, поняв некоторые болевые точки, причины их возникновения и почему это происходило.
00:37:23Как мы можем решить проблему с емкостью GPU.
00:37:29Нам нужно понять, что мы можем сделать, что еще мы можем с этим поделать.
00:37:33Речь пойдет об оптимизации моделей, и я бы хотел пригласить Танмая.
00:37:39Он может рассказать об оптимизации моделей подробнее, учитывая, что он работал над этим во время своих исследований.
00:37:47Ладно.
00:37:48Хорошо.
00:37:49Я могу управлять.
00:37:50Я могу управлять.
00:37:54Да.
00:37:55Сюда.
00:37:56Так.
00:37:57Всем привет.
00:37:58Проверка связи.
00:37:59Меня наконец-то слышно?
00:38:00Да.
00:38:01Хорошо.
00:38:02Итак, привет.
00:38:03Я Танмай Шах.
00:38:04Я работаю старшим квант-моделлером, а также исследователем в области ИИ.
00:38:08Основное внимание я уделяю верификации агентов, а сейчас строю модели мира.
00:38:13Итак, вернемся к оптимизации моделей.
00:38:16Прежде чем мы начнем, я создал исследовательский шаблон, чтобы нам было проще понять все эти сложные вещи.
00:38:25Наш шаблон прост.
00:38:28Сначала мы определяем проблему.
00:38:30Второй шаг — решаем проблему с помощью двух алгоритмов.
00:38:34Это шуточные алгоритмы.
00:38:35Итак, первый алгоритм называется «алгоритм страуса».
00:38:39Всякий раз, когда мы видим проблему, прямо как страус, мы прячем голову в песок.
00:38:46Мы поступим точно так же.
00:38:47Всякий раз, сталкиваясь с проблемой, мы будем просто игнорировать ее.
00:38:51Так что это важный алгоритм, которому нам следует следовать.
00:38:55Второй созданный алгоритм называется «алгоритм чемпионата мира».
00:38:59Например, мы не знаем, кто выиграет этот чемпионат мира по футболу.
00:39:03Поэтому организаторы разбили 48 команд на 12 групп.
00:39:11Затем раунд 32 команды, и сейчас как раз идет этот этап.
00:39:16Затем 1/8 финала, четвертьфиналы, полуфиналы и финал.
00:39:21Таким образом, они разбивают задачу на более мелкие подзадачи, и полезные результаты продвигаются дальше.
00:39:30Ту же самую аналогию или тот же алгоритм мы используем, чтобы понять оптимизацию моделей и все остальное.
00:39:38Ну что же, давайте начнем.
00:39:41Допустим, у меня есть один GPU H100.
00:39:46Мне нужно использовать эту открытую модель под названием GPT OSS со 120 миллиардами параметров.
00:39:54И сейчас, кажется, она обучена в формате BF16, а вес ее составляет 240 гигабайт.
00:40:02Что мне делать?
00:40:04Вот такая у нас проблема.
00:40:07Первое, с чем приходится иметь дело: 240 гигабайт и 80-гигабайтная H100.
00:40:16При этом модель должна поместиться всего на одном GPU, а не на нескольких.
00:40:21Что же мы можем сделать?
00:40:22Думаю, простейший шаг — просто сжать ее.
00:40:27Но как ее сжать?
00:40:29Это еще одна задача.
00:40:30Если сжать формат BF16 до FP8, размер составит около 120 гигабайт.
00:40:38Но наш GPU H100 по-прежнему имеет емкость 80 гигабайт.
00:40:42Поэтому, полагаю, они сжали ее еще сильнее до MXFP4.
00:40:49И размер, кажется, составляет около 65 гигабайт.
00:40:53Это то, что мы можем сделать — сжатие, но возникает вопрос.
00:40:59И здесь мы используем наш «алгоритм страуса».
00:41:03Мы предполагаем, что при сжатии большой модели до меньшего размера потери качества отсутствуют.
00:41:10Второе — в этом случае, ладно, да.
00:41:16Итак, в данном случае на этом слайде мы использовали Mistral 7B.
00:41:20То есть 7 миллиардов параметров.
00:41:22Это небольшая модель, 7 миллиардов параметров.
00:41:25Если умножить это на два байта, вес получается около...
00:41:3114,5 гигабайт, что легко поместится в H100 или даже в A40.
00:41:38Затем, что мы можем сделать с Mistral 7B — вместо сжатия до FP16 мы можем применить другие методы, такие как int8, int4 или nf4.
00:41:53По сути, нам нужно просто применить «алгоритм страуса» и верить, что потери качества как таковой не происходит.
00:42:01Но нам также необходимо доказать это математически путем тестирования на каком-нибудь внешнем бенчмарке, чтобы понять, работает это или нет.
00:42:10И это относится к посттренировочной квантизации.
00:42:16Эту процедуру также можно проводить во время дообучения.
00:42:20Такого рода квантизацию можно выполнять и тогда.
00:42:22Это относится к квантизации с учетом обучения.
00:42:25Итак, давайте перейдем к нашей следующей проблеме.
00:42:31У нас есть огромные матрицы.
00:42:37Просто представьте матрицу A размерностью 1000 на 1000 и другую матрицу 1000 на 1000.
00:42:51Если перемножить эти две матрицы, количество операций будет равно 1000 в кубе.
00:43:00И с точки зрения вычислений это определенная проблема.
00:43:06Поэтому нам бы хотелось, чтобы матричное умножение происходило быстро и экономило память.
00:43:13Что же нам делать?
00:43:15У нас гигантская матрица.
00:43:17Хорошо, давайте возьмем эту: 4096 на 4096.
00:43:23Что нам предпринять для решения проблемы ускорения работы и экономии памяти при размере 4096 на 4096?
00:43:33Итак, первое — мы воспользуемся нашим алгоритмом кубка мира.
00:43:37Мы можем выбрать произвольное число и разбить блок по вертикали.
00:43:42Не имеет особого значения, что именно вы выбираете.
00:43:45Допустим, у нас 4096 столбцов.
00:43:51Мы разобьем их на группы по 128 столбцов в каждой.
00:43:57То есть 128, 128, 128, 128, 128 по вертикали.
00:44:03В результате деления 4096 мы получим 32 блока.
00:44:09Что же произойдет благодаря этому?
00:44:13Если мы разделим матрицу по вертикали, мы сможем использовать несколько GPU для ускорения процесса.
00:44:21Такой подход называется многоголовым вниманием (Multi-Head Attention).
00:44:26Что еще мы можем сделать?
00:44:29У нас есть большая матрица, как я уже упоминал, используя «алгоритм страуса».
00:44:36Наша главная проблема — размерность.
00:44:39Мы можем сделать следующее: вместо того чтобы держать все 31 вертикальный блок, мы просто отбросим 31 блок.
00:44:49И предположим, что одного блока вполне достаточно для обработки всех запросов.
00:44:57Наши потери будут практически ничтожными.
00:45:00И в итоге мы приходим к такому алгоритму.
00:45:04Этот алгоритм называется вниманием с одним запросом (Multi-Query Attention).
00:45:08Как мы видим, сейчас мы находимся на двух разных полюсах.
00:45:12Один из них — многоголовое внимание, где мы разделяем данные на 32 блока и используем разные GPU или параллельную обработку.
00:45:22А одновременно с этим мы просто отбрасываем 31 блок.
00:45:26И называем это вниманием с одним запросом.
00:45:31Поэтому для обеих крайностей нам следует найти какой-то компромиссный вариант.
00:45:38Можно сказать, что вместо выбрасывания всех 31 блоков мы, возможно, сгруппируем некоторые из них вместе.
00:45:49И предположим, что похожие блоки будут обрабатывать схожие типы запросов.
00:45:58Этот метод относится к вниманию с группированными запросами (GQA), которое сейчас очень популярно.
00:46:04Группированное внимание применяется даже в Mistral и других моделях.
00:46:11Итак, теперь мы понимаем, что у нас есть большая матрица.
00:46:16Мы можем делить ее так, как хотим, и с помощью математических расчетов
00:46:19доказать, что потери практически несущественны.
00:46:23Что же еще мы можем сделать?
00:46:25Затем, после этого внимания с группированными запросами...
00:46:34Посмотрите, у нас есть большая матрица.
00:46:38Одна часть — ключи, другая — значения.
00:46:42Давайте сожмем эту матрицу в скрытый вектор (latent vector).
00:46:47А затем разработаем алгоритм восстановления исходной матрицы из этого скрытого вектора.
00:46:55Подобная стратегия относится к следующему направлению.
00:46:59Многоголовое скрытое внимание (MLA).
00:47:02Но опять же, здесь возникают проблемы с RoPE, так как RoPE зависит от позиций, а этот подход — нет.
00:47:10Поэтому нужно также добавить индексы для ключей, чтобы их можно было сопоставлять.
00:47:16И снова главный вопрос: зачем мы перемножаем все эти огромные матрицы?
00:47:25Потому что так устроен механизм внимания: каждый токен обращает внимание на каждый токен.
00:47:33Так что насчет того, чтобы не обращать внимание на все предыдущие токены, а фокусироваться только на тех, которые действительно важны для нас?
00:47:42Итак, эта сфера сейчас активно развивается.
00:47:46Это относится к разреженному вниманию DeepSeek.
00:47:51Да-да.
00:47:53И, да, в общем, понятно.
00:47:56Дальше.
00:47:59Да, следующий пункт — Flash Attention.
00:48:02В Flash Attention основная проблема заключается в том, что...
00:48:09сейчас, вернее, не сейчас, а прямо сейчас почти все используют Flash Attention, но так было и в 2022 или 2023 году.
00:48:20В общем, это работает следующим образом.
00:48:23Это работает так: матрицы Q и K, запросов и ключей, находились в памяти HBM.
00:48:34Они сначала загружаются в тензорное ядро, выполняются некие вычисления, а затем результаты записываются обратно в HBM.
00:48:47И этот процесс повторяется многократно.
00:48:51Поэтому в Flash Attention сделали следующее: вместо умножения целых матриц...
00:48:59они разделили их, подобно алгоритму World Cup, разбив большие матрицы на небольшие блоки,
00:49:05и помещают в SBM только эти мелкие блоки, чтобы ускорить процесс умножения,
00:49:13при этом отслеживая три переменные для вычисления онлайн-softmax.
00:49:20Да, это чистая математика: если у нас есть многоголовое внимание с 524 ключами и значениями,
00:49:34то все зависит от желаемой группировки: если вместо 32 голов KV мы хотим использовать только 8 голов KV,
00:49:47мы получаем четырехкратное сжатие в этом многоголовом латентном внимании.
00:49:54Эта формула зависит от конкретной модели и количества слоев в ней.
00:50:00В оригинальной статье DeepSeek, кажется, использовалась размерность 128, точнее, я не помню точную размерность, но...
00:50:11согласно ей, они использовали один латентный вектор размерностью 512 и около 64 для индекса RoPE,
00:50:23после чего показали, что это в 56 раз сильнее сжато по сравнению с многоголовым вниманием.
00:50:32Хорошо.
00:50:33Да, итак, это диаграмма компромиссов; здесь мы, кажется, еще не говорили о линейном внимании или Mamba.
00:50:50Главная проблема заключается во всех этих матричных умножениях, сейчас все используют внимание.
00:50:56Допустим, в будущем мы не захотим использовать внимание и вместо последовательной генерации токенов перейдем к диффузионным моделям,
00:51:07где все генерируется одновременно — тогда изменятся и все эти алгоритмы.
00:51:14Но здесь у них есть еще два варианта: линейное внимание и Mamba.
00:51:19Судя по этому слайду, если мы ничего не сжимаем, то MHA просто распараллеливает процесс.
00:51:29Потерь качества нет, это хорошо, а затем идет групповое внимание с запросами (GQA) и DSA — то, что используют практически все модели.
00:51:42Да.
00:51:43Думаю, то же самое мы приводим в сводной таблице внимания: качество MHA хорошее, пропускная способность — нормальная.
00:51:56Что касается группового внимания с запросами, оно зависит от вашего сценария использования: качество почти как у многоголового внимания, но контекст тоже очень важен.
00:52:10Многозапросное внимание — это одна из крайностей.
00:52:13Мы почему-то предполагаем, что нам нужен всего один блок, и все запросы будут соотноситься с этими меньшими блоками.
00:52:24Поэтому качество у MQA не такое уж высокое.
00:52:29А многоголовое латентное внимание... Если вы пробовали модели DeepSeek, они отлично справляются с качеством, не говоря уже о скользящем окне.
00:52:44Все это такие техники, как настройка окон и т. д. Линейное внимание предлагает сначала все суммировать, а затем выполнять поиск, а Mamba — это просто модель в пространстве состояний, да.
00:53:09Для оптимизации моделей у нас также есть два блокнота.
00:53:28Так, мне нужно перейти к этому.
00:53:35Хорошо, что насчет квантования, например, демо — оно уже запущено? Нет.
00:53:51Позвольте мне запустить его.
00:53:54Итак, мы загружаем модель, например, Mistral 7B.
00:54:10Этот вариант — с базовым показателем FP16.
00:54:20Подождите.
00:54:21Оно запустилось?
00:54:21Подождите.
00:54:22Оно запустилось?
00:54:23Так.
00:54:24Выполнение заняло две миллисекунды.
00:54:27Это выполнилось?
00:54:28Хорошо.
00:54:29Да, на этот раз модель загружается с точностью FP16.
00:54:35Хорошо.
00:54:36Выполнение заняло две миллисекунды.
00:54:40Это выполнилось?
00:54:41Хорошо.
00:54:42Да, на этот раз модель загружается с точностью FP16.
00:54:47Wi-Fi.
00:54:58Это займет время.
00:55:03Ладно.
00:55:08Да, потому что веса скачиваются из Hugging Face.
00:55:14А?
00:55:17Да, Colab работает онлайн.
00:55:22Да.
00:55:23Потому что ему нужно сделать сетевой запрос к Hugging Face и выполнить скачивание.
00:55:30Не знаю, но загрузка, похоже, занимает время.
00:55:35Хорошо.
00:55:36Окей.
00:55:37Ладно.
00:55:38Хорошо.
00:55:39Окей.
00:55:40Здесь мы видим, что объем памяти составляет около 15 ГБ при точности FP16.
00:56:00Мы пытаемся сделать двукратное сжатие с помощью int8, как говорил Талмуд.
00:56:15Хорошо.
00:56:16Мы видим, что объем памяти теперь составляет около 0,7, 0,5 ГБ.
00:56:21Это значит, что теперь у вас больше памяти для роста вашего кэша KV.
00:56:27Это означает, что вы можете либо работать с большим лимитом контекста, либо обслуживать больше одновременных пользователей.
00:56:36Если использовать int4, вы по сути выполняете четырехкратное сжатие.
00:56:41При таком четырехкратном сжатии объем будет еще меньше.
00:56:45Думаю, около 3-4 ГБ.
00:56:50Да, 4,5 ГБ.
00:56:51И да.
00:56:52Так что это, подождите.
00:56:53Это просто базовый график с теоретическими цифрами.
00:57:09Мы не проводим здесь никаких тестов пропускной способности.
00:57:12Но обычно можно заметить рост доступной памяти.
00:57:15Соответственно, у вас будет и немного более высокая пропускная способность.
00:57:21Судя по изученным нами бенчмаркам, сжатие int8 имеет...
00:57:26да, оно обеспечивает меньшую пропускную способность.
00:57:32Хорошо.
00:57:33Затем идет демо, посвященное механизмам внимания.
00:57:42Итак, что касается внимания, хорошо.
00:57:45Мне нужно это запустить.
00:57:58Хорошо.
00:57:59Итак, оно выполнилось.
00:58:02О.
00:58:03Подождите.
00:58:04Почему написано, что GPU не обнаружен?
00:58:09По идее, GPU должен обнаруживаться.
00:58:18О.
00:58:19Ладно.
00:58:29Подождите.
00:58:30Секунду.
00:58:30Подождите.
00:58:50Это удивляет.
00:58:57Кажется, по какой-то причине он не может обнаружить GPU.
00:59:05У нас ведь есть здесь GPU.
00:59:11Ладно.
00:59:12Неважно.
00:59:14Да.
00:59:14Но основная идея здесь заключалась в том, что по мере перехода к сжатию вычислений с использованием различных механизмов внимания...
00:59:26от многоголового к групповому вниманию с запросами, а затем к MLA,
00:59:33вы начнете замечать определенные оптимизации.
00:59:38Кажется, вчера вечером мы проводили бенчмаркинг.
00:59:43Я хотел исправить этот момент.
00:59:45Там было не 56 раз.
00:59:48А 14 раз.
00:59:50В общем, в демо была допущена ошибка в расчетах, где не было умножения на количество слоев.
01:00:02Да.
01:00:03Так что приношу извинения за это.
01:00:04Таким образом, экономия от MLA составляет около 14 раз по сравнению с многоголовым вниманием.
01:00:15Теперь, когда мы понимаем болевые точки, основы и одну сторону оптимизаций — оптимизацию моделей, — мы хотим поговорить о том, что можно сделать со стороны обслуживания.
01:00:31Первое: мы видели, что при выполнении простого шага декодирования вы подтягиваете веса модели, а затем пересчитываете векторы ключей и значений для всех предыдущих токенов,
01:00:50хотя вы уже вычислили эти векторы для всех токенов.
01:00:55Так что здесь определенно имеет место большая трата вычислений.
01:01:02Если проанализировать временную сложность этого процесса, она окажется равной O от N в квадрате.
01:01:07Способ решения этой проблемы — классический компромисс в пользу памяти.
01:01:12Вы можете хранить историю этих векторов для токенов и обращаться к ней.
01:01:19Эта память получила название KV Cache.
01:01:24И сам процесс выглядит примерно так.
01:01:27Исходя из этого кэша KV, реально стали возможны четыре оптимизации.
01:01:35Первая касается постраничного внимания (PagedAttention).
01:01:42В чем же разница и в чем проблема сегодня?
01:01:45Итак, когда вы отправляете несколько запросов на вход в GPU, эти запросы объединяются в батч.
01:01:52Каждому запросу выделяется непрерывное хранилище памяти.
01:01:58Допустим, я просто привожу пример, скажем, 2 КБ.
01:02:05Однако вашему запросу требовалось, скажем, только 1 КБ.
01:02:11Таким образом, возникает примерно 50% фрагментации памяти.
01:02:19И эта фрагментация в основном приводит к пустой трате памяти.
01:02:24Это значит, что в памяти было пространство, где можно было бы обслужить больше запросов, но вы не могли этого сделать, потому что искали непрерывный блок памяти.
01:02:36Поэтому вдохновение было почерпнуто из того, как работает ОС.
01:02:41Например, вы поддерживаете логическую память и у вас есть физическая память.
01:02:47В логической памяти все равно будет казаться, что KV-вектор для каждого токена является непрерывным.
01:02:59Но он будет сопоставляться с другим физическим адресом.
01:03:06Так что это действительно помогло сэкономить много памяти.
01:03:11И это стало возможным только потому, что они рассматривают память как набор блоков.
01:03:18И вы будете динамически выделять эти блоки по мере необходимости для запросов.
01:03:22По мере того как поступают новые токены и им требуется такой объем памяти.
01:03:27Другой рычаг заключается в том, что когда вы отправляете несколько запросов в батче,
01:03:39GPU обрабатывает эти запросы.
01:03:42Но он не принимает новый батч, пока все запросы в этом батче не будут выполнены.
01:03:49Так что диаграмма больше похожа на постраничное внимание.
01:03:52Но здесь речь идет скорее о том, когда GPU доступен для приема следующего батча.
01:03:59Существует период времени, когда GPU простаивает.
01:04:04И вы хотите как-то решить эту проблему.
01:04:08Идея заключалась в том, чтобы использовать непрерывную батчизацию.
01:04:17Таким образом, непрерывная батчизация также очень помогла с пропускной способностью, потому что теперь можно отправлять больше запросов довольно быстро.
01:04:24Заботясь о том, чтобы GPU всегда был занят и не простаивал.
01:04:33Таким образом, вы экономите вычисления.
01:04:36Третье — это префиксное кэширование.
01:04:39Помните, KV-кэш помог вам сэкономить вычисления для одного запроса по всем токенам.
01:04:46Но что, если у вас одинаковые токены в разных запросах?
01:04:53Как с этим бороться?
01:04:55Префиксное кэширование, представленное в VLLM, борется именно с этим.
01:05:04И затем третье — вернее, мы уже говорили о четвертом.
01:05:10Мы говорили о квантовании модели, но вы также можете квантовать веса KV.
01:05:21Это значит, что теперь вам требуется меньше места для векторов ключей и значений.
01:05:28А значит, вы можете хранить больше ключей и векторов значений в памяти.
01:05:32И это значит, что вы можете обслуживать больше токенов.
01:05:34Это значит, что вы можете работать с большим лимитом контекста.
01:05:37И это значит, что вы можете поддерживать более высокое качество модели.
01:05:41И все это уже реализовано в VLLM.
01:05:51Вам не нужно заново изобретать велосипед.
01:05:56Вы можете развернуть VLLM в продакшене и увидеть этот рост.
01:06:03Далее у нас есть бенчмарк, который мы провели.
01:06:08Этот бенчмарк... сейчас посмотрю, есть ли он у меня.
01:06:14Вот.
01:06:17Демонстрации.
01:06:22Запуск этого бенчмарка занимает около часа, потому что приходится постоянно останавливать и перезапускать серверы VLLM, загружать модели и все такое.
01:06:35Тестирование занимает много времени, но я могу вкратце рассказать, что именно мы делаем.
01:06:41Мы оставили модель прежней, это Mistral 7B.
01:06:46Затем у нас есть набор входящих вопросов, которые мы отправляем.
01:06:53Считайте их промптами.
01:06:56Затем здесь есть вспомогательные функции, например, проверка того, запущен ли сервер.
01:07:01Этот сервер — сервер VLLM.
01:07:04Затем есть вспомогательные функции для получения метрик VLLM.
01:07:09И я расскажу о том, что это за метрики.
01:07:14Потом здесь есть множество бенчмарков и все такое.
01:07:17И еще нужно измерять использование KV и прочее.
01:07:22Так что это вспомогательные функции.
01:07:24Базовый вариант очень прост.
01:07:26У нас есть базовый вариант Hugging Face.
01:07:29Это простой способ отправки текста в LLM и получения ответа.
01:07:36Здесь мы видим некоторые результаты.
01:07:38Мы увидели, что пропускная способность Hugging Face составляет около 51 токена в секунду.
01:07:44Время до первого токена составило 54.
01:07:46А задержка между токенами — 19.
01:07:49Все это запускалось на H100.
01:07:56Затем мы запускаем сервер VLLM с настройками по умолчанию.
01:08:00По умолчанию VLLM предоставляет постраничное внимание, непрерывную батчизацию и KV-кэширование.
01:08:08Итак, три вещи присутствуют по умолчанию.
01:08:13И когда вы пытаетесь сравнить эти бенчмарки, вы видите, что пропускная способность возрастает почти в 15 раз.
01:08:21Вы можете обрабатывать больше токенов в секунду.
01:08:24Время до первого токена тоже увеличивается.
01:08:34А задержка между токенами снижается.
01:08:38Использование KV-кэша по отношению к пользователям и контексту, безусловно, возрастает.
01:08:43Теперь, когда вы применяете к этому префиксное кэширование.
01:08:51С префиксным кэшированием вы видите, что пропускная способность увеличивается еще сильнее.
01:08:57TTFT уменьшается.
01:08:59Задержка между токенами примерно такая же.
01:09:02Использование KV-кэша по отношению к пользователям начинает снижаться.
01:09:09По отношению к контексту оно не падает.
01:09:12Оно примерно такое же.
01:09:14Думаю, это тоже примерно то же самое.
01:09:16Это не так уж и важно.
01:09:19Когда вы применяете поверх этого квантование KV.
01:09:25Пропускная способность остается практически прежней.
01:09:33Время до первого токена не меняется.
01:09:36Задержка токенов остается прежней.
01:09:39Но использование KV действительно уменьшается.
01:09:42Это происходит потому, что вы квантовали пространство ключей и значений.
01:09:49Существует концепция спекулятивного декодирования, о которой расскажет Танмай.
01:09:54При тестировании этих методов также заметно некоторое снижение использования KV-памяти.
01:10:06Хотя результаты примерно одинаковые.
01:10:08В общем, это основные метрики.
01:10:21Наверное, мне стоит уменьшить масштаб.
01:10:25Ладно.
01:10:26Не получается.
01:10:27Уменьшить масштаб.
01:10:28Не работает.
01:10:29Отлично.
01:10:30В общем, это бенчмарки VLLM.
01:10:35Между прочим, это стандарт для продакшена.
01:10:38Мы также поделимся этим деревом решений, когда будем говорить о других движках.
01:10:48Давайте поговорим о том, какие еще оптимизации инференса мы можем сделать поверх этого.
01:10:58И какие еще решения появились.
01:11:02Я бы хотел снова пригласить Танмая.
01:11:07Он расскажет о некоторых из этих оптимизаций.
01:11:11Ой, простите.
01:11:12Большое извинение.
01:11:13Я не включил слайды.
01:11:26Какое было...
01:11:27Так.
01:11:28Отлично.
01:11:29Идеально.
01:11:30Какое именно?
01:11:31Спекулятивное декодирование.
01:11:32Да.
01:11:33Спасибо, Харшал.
01:11:34Да.
01:11:35Все это — спекулятивное декодирование.
01:11:40Все это, как бы сказать, разные вкусы одной и той же газировки.
01:11:46Эта техника относится к ускорителям декодирования.
01:11:51Первое — мы говорим только об этом спекулятивном декодировании, но есть и другие варианты, такие как self-speculative, Eagle, Medusa.
01:12:01Мне нравится, кажется, только этот, алгоритм Eagle.
01:12:05Итак, начнем со спекулятивного декодирования.
01:12:06Ладно.
01:12:07Хорошо.
01:12:08Давайте начнем с того, что такое спекулятивное декодирование.
01:12:09Главная проблема заключается в том, что в архитектуре трансформера все эти токены генерируются последовательно, один за другим.
01:12:26Что если использовать модель поменьше и позволить ей сгенерировать, скажем, четыре или пять токенов?
01:12:37И эта модель-учитель, или, как мы можем сказать, согласно нашему алгоритму Кубка мира — судья.
01:12:43Рефери решит, сколько токенов он принимает.
01:12:48И этот цикл продолжает повторяться.
01:12:51И мы предполагаем, что существуют определенные области, где такой подход будет работать.
01:12:59Например, в написании кода, где почти нет творчества.
01:13:05Каждый код или синтаксис почти одинаков.
01:13:08Так что, возможно, это поможет.
01:13:10Но, основываясь на личном опыте, я вообще не нашел спекулятивное декодирование полезным.
01:13:18Но другие методы, такие как самоспекулятивное декодирование, где у модели-учителя также есть одна вспомогательная голова, делают нечто похожее на то, что делает базовая или небольшая модель.
01:13:35Но затем появился EGLE — EGLE 1, 2, 3, не знаю, сколько там версий, но суть в том, что вместо генерации токенов давайте обучим небольшую модель и возьмем признаки из одного из слоев основных моделей, чтобы вместо генерации токенов она генерировала эти признаки.
01:14:02Так что EGLE лучше по сравнению с технологиями такого рода.
01:14:10И еще одна — MEDUSA, которая просто предлагает генерировать все эти токены параллельно.
01:14:17Хорошо, вот здесь, вот на этом слайде.
01:14:21Да.
01:14:22Следующий слайд.
01:14:24Ладно.
01:14:25Хорошо.
01:14:26Ладно, да.
01:14:27Хорошо.
01:14:28Теперь мы перейдем к кешированию префиксов.
01:14:34Не знаю, используют ли люди статическое кеширование префиксов.
01:14:39Но дело в том, что основная проблема кеширования префиксов заключается в том, что иногда мы делаем небольшую опечатку при вводе.
01:14:47И стандартное статическое кеширование префиксов берет промпт и выполняет хеширование.
01:14:53И в следующий раз, когда пользователь задает похожий вопрос, система пытается сопоставить хеш.
01:14:58Поэтому, если хеши совпадают, вместо повторного вычисления всех ключей и значений она просто берет их из хранилища.
01:15:09Но вы же знаете, что иногда мы ошибаемся или можем изменить слово или букву.
01:15:15Тогда мы получаем высокий процент промахов кеша.
01:15:21Именно поэтому дерево Радикса...
01:15:25Дерево Радикса становится очень популярным, в том числе из-за агентов.
01:15:30Думаю, почти все используют агентов, и большая часть вычислений происходит во время тестирования и инференса.
01:15:38Когда мы продолжаем задавать одни и те же вопросы и промпты.
01:15:42Например: «Ты эксперт в разработке ПО», повторенное 200 раз.
01:15:48Такие циклы постоянно происходят внутри агентских систем.
01:15:55Где необходимо сохранять или хранить подобные вещи в дереве Радикса.
01:16:03Так что дерево Радикса — это просто продвинутая версия префиксного дерева, где мы сворачиваем узел, если у него нет ответвлений.
01:16:17И для такой работы, где мы постоянно повторяем одно и то же,
01:16:24дерево Радикса очень помогает, и sglang использует алгоритм такого типа для кеширования префиксов.
01:16:35Ой, да, затем есть еще кое-что.
01:16:38Во-первых, TensorRT-LLM.
01:16:41Это очень запутанно.
01:16:42Когда я только начинал, я был просто сбит с толку.
01:16:46Что такое TensorRT-LLM?
01:16:49Ну да, TensorRT — это просто стандартный SDK.
01:16:55TensorRT-LLM — это просто движок инференса.
01:16:59Прямо как vLLM, sglang.
01:17:01Но проблема в том, что он связан с NVIDIA.
01:17:05Они оптимизировали каждый слой и каждую проблему.
01:17:10Как я упоминал в нашем алгоритме для Чемпионата мира, они просто переработали всё и оптимизировали на аппаратном уровне тоже.
01:17:18Так что да, ладно, дальше.
01:17:23Да, для этого воркшопа мы также провели бенчмаркинг, чтобы выяснить, что лучше.
01:17:33Наш сетап выглядел примерно так.
01:17:36Мы провели два вида тестирования.
01:17:39Первое — без агентского тестирования, где мы просто...
01:17:44Мы использовали набор данных ShareGPT и просто задавали эти вопросы с помощью vLLM и sglang.
01:17:57Хорошо.
01:18:05Да, хорошо.
01:18:07Позвольте мне приблизить.
01:18:12Отлично.
01:18:13Да, для этого воркшопа мы использовали H100, и наше первое тестирование заключалось в том, что мы просто...
01:18:23Мы брали вопросы из ShareGPT и передавали их в vLLM и sglang, и обнаружили, что статистической разницы в производительности нет.
01:18:34То есть у обоих примерно одинаковые...
01:18:37Оба обрабатывают схожее количество запросов в секунду, показывают одинаковое время до первого токена и задержку.
01:18:43Единственную разницу мы заметили при агентском ветвлении.
01:18:50Мы задали похожий вопрос: «Ты лучший инженер-программист в мире».
01:18:59«Реши проблему пробок на дорогах в городе».
01:19:04Затем мы передали это в LLM.
01:19:08LLM сгенерировала результат.
01:19:10После этого мы провели второй раунд.
01:19:13Когда LLM сгенерировала этот ответ, во втором раунде мы специально указали...
01:19:22проанализируй предложение и поставь оценку от одного до десяти.
01:19:28Это были два шага, которые мы сделали, и этот цикл постоянно повторялся.
01:19:35Мы выяснили, что для рабочего процесса такого типа, где все стандартно, в игру вступают промпты и контекстная инженерия.
01:19:47Если выполнять правильное агентское ветвление, то, на мой взгляд, SGLang работает в три-четыре раза лучше.
01:19:54Но опять же, это зависит от конкретного сетапа.
01:19:58Если вы запустите его, результаты могут отличаться.
01:20:02Понятно.
01:20:03Да.
01:20:04Думаю...
01:20:06Мы загрузили это на GitHub?
01:20:08Да.
01:20:09Хорошо.
01:20:10Да.
01:20:11PDF-файл также лежит на Диске.
01:20:15Там та же ссылка, что и на слайды.
01:20:18Итак, краткое резюме.
01:20:22Для стандартной рабочей нагрузки API пропускная способность vLLM и SGLang будет одинаковой.
01:20:31Поэтому, если у вас нет...
01:20:33Если у вас стандартная рабочая нагрузка, определенно выбирайте vLLM.
01:20:36Это в любом случае стандарт для продакшена.
01:20:38Но, как говорил Танмай, когда вы пытаетесь использовать агентские рабочие нагрузки, вот тут SGLang действительно раскрывает себя.
01:20:50И он приносит вам все эти преимущества.
01:20:55Так что да.
01:20:58Используйте vLLM по умолчанию.
01:21:00Но если у вас агентские нагрузки, попробуйте перейти на SGLang.
01:21:05Если вас не устраивает производительность vLLM.
01:21:09Ладно.
01:21:10Позвольте мне...
01:21:15Погодите.
01:21:18Хорошо.
01:21:21А затем здесь есть...
01:21:29Сравнение, выполненное для модели на 120 миллиардов параметров.
01:21:33Для GPT OSS 120B.
01:21:36Это бенчмарк, подготовленный PlayPy.
01:21:42Здесь есть ссылка на блог.
01:21:46О, отлично.
01:21:48Хорошо.
01:21:49Да.
01:21:50Они провели аналогичный бенчмарк и включили в него TensorRT-LLM.
01:21:57Вы всегда можете изучить эти бенчмарки и понять, что лучше всего подходит под ваши задачи.
01:22:05Как мы уже упоминали, TensorRT старается оптимизировать и аппаратную сторону для достижения пиковой производительности железа.
01:22:16И когда вы выбираете движки после сравнения vLLM, SGLang и TensorRT, появляются некоторые новые движки.
01:22:29NVIDIA Dynamo, безусловно.
01:22:43Они также предназначены для маршрутизации агентских сессий.
01:22:49Hugging Face тоже всегда здесь.
01:22:51Это простой инструмент.
01:22:53Затем есть движок MSTAR, недавно предложенный Стэнфордом.
01:23:00NVIDIA Dynamo для мультимодальных задач.
01:23:05Вы вполне можете их изучить.
01:23:08И подводя короткий итог: мы начинаем с базовой линии.
01:23:15Мы пытаемся найти модель, которая подойдет для наших задач.
01:23:22Вы можете выбрать DeepSeek.
01:23:27Только не выбирайте Mistral 7B.
01:23:30В общем, она не очень хороша.
01:23:32Но да.
01:23:35Итак, вы выбираете модель, хотите использовать меньше памяти и уместить большую модель в меньший объем памяти.
01:23:44Чтобы сэкономить на затратах на GPU.
01:23:47Для этого можно использовать квантование.
01:23:51Затем вы можете применить оптимизации сервиса, используя правильный движок под капотом.
01:23:58Это действительно обеспечит нужную вам пропускную способность.
01:24:07А теперь то, что вы можете сделать по возвращении домой — поскольку мы не можем охватить весь материал здесь, — это почитать об исходной информации: различных механизмах внимания и этих движках.
01:24:27Попробуйте ознакомиться с различными бенчмарками, доступными в интернете.
01:24:34Изучите множество глубоких руководств или следующих этапов, таких как стратегии вытеснения KV-кеша.
01:24:45Сейчас мир движется в сторону выделения отдельной области инженерии KV-кеша.
01:24:50Вам нужно понимать, что там происходит.
01:24:52Это вытеснение KV, сжатие кеша, гибридная память.
01:24:57Вокруг этого появляется множество решений.
01:25:01Поэтому всегда старайтесь опираться на эти основы и фундаментальные принципы.
01:25:08И оценивайте, какое решение какую проблему решает и нужно ли вообще решать эту проблему для вашего кейса.
01:25:17Затем есть распределенный инференс LLM, что представляет собой совершенно другую сложную задачу.
01:25:26Для этого, вероятно, понадобится двухчасовой воркшоп, чтобы разобрать всю «начинку» и попрактиковаться.
01:25:40Да, и это то, что мы пытаемся предложить для сессии AI Engineer в Нью-Йорке, то есть углубиться в продвинутые разделы инференса LLM.
01:25:51Этот же воркшоп больше подходил для начинающего и среднего уровней.
01:25:55Так что в этой форме у нас есть отзывы, а также интерес.
01:26:02Если вы считаете, что в определенных разделах нужны улучшения, обязательно оставьте свой отзыв.
01:26:09И если вы хотите увидеть этот семинар, например, на New York Fair, обязательно выразите свой интерес.
01:26:22А?
01:26:24О, как это возможно?
01:26:27Бум.
01:26:32Дайте-ка проверить.
01:26:37Ладно.
01:26:38А?
01:26:39Да.
01:26:40URL работает, верно?
01:26:41Да.
01:26:42Не QR-код?
01:26:43Ладно.
01:26:44Наверное, я забыл их связать.
01:26:45Ладно.
01:26:46Отлично.
01:26:46Да.
01:26:47Так что, если вы можете это предоставить.
01:26:49Ладно.
01:26:50Отлично.
01:26:51Да.
01:26:52Так что, если вы можете это предоставить.
01:26:53Ладно.
01:26:54Да.
01:26:55Ладно.
01:26:56Отлично.
01:26:57Да.
01:26:58Так что, если вы можете это предоставить.
01:26:59Позвольте мне просто.
01:27:00Ладно.
01:27:00Ладно.
01:27:01Отлично.
01:27:02Да.
01:27:02Так что, если вы можете это предоставить.
01:27:03Позвольте мне просто.
01:27:04Ладно.
01:27:05Так будет нормально.
01:27:06Эм, и да, думаю, на этом мы бы хотели завершить этот семинар.
01:27:13И я уверен, у многих из вас накопилось много вопросов.
01:27:14Так что мы можем обсудить их вне эфира.
01:27:15Эм, мы можем встретиться, эм, и мы сможем поговорить об этих вопросах.
01:27:16Да.
01:27:17Конечно.
01:27:18Конечно.
01:27:19Эм, спасибо всем.
01:27:20Спасибо, что присоединились.
01:27:21Эм, думаю, это было действительно.
01:27:22Эм, спасибо всем.
01:27:23Эм, спасибо всем.
01:27:24Спасибо, что присоединились.
01:27:25Эм, спасибо всем.
01:27:26Спасибо, что присоединились.
01:27:27Эм, думаю, это было действительно.
01:27:28О, ладно.
01:27:29Эм, ладно.
01:27:30Так будет нормально.
01:27:31Эм, и да, думаю, на этом мы бы хотели завершить этот семинар.
01:27:33Эм, и да, думаю, на этом мы бы хотели завершить этот семинар.
01:27:36И я уверен, у многих из вас накопилось много вопросов.
01:27:39Так что мы можем обсудить их вне эфира.
01:27:41Эм, мы можем встретиться, эм, и мы сможем, эм, поговорить об этих вопросах.
01:27:42Да, конечно.
01:27:43Эм, спасибо всем.
01:27:44Эм, думаю, это было очень содержательно, и все вы пришли сюда.
01:27:49Эм, большое спасибо.
01:27:50Да, спасибо.

핵심 요약

Масштабирование инференса LLM требует жесткого баланса между длиной контекста, задержкой и пропускной способностью GPU, который достигается с помощью квантования моделей, оптимизации KV-кэша и специализированных движков вроде vLLM и SGLang.

하이라이트

  • Рынок инференса LLM сегодня оценивается примерно в 23 миллиарда долларов.

  • Обработка поисковых запросов Google с помощью LLM потребует колоссальную сумму в 36 миллиардов долларов при ограничении стоимости запроса менее чем в 0,5 цента.

  • Затраты на обучение GPT-3 составили около 4,6 миллиона долларов, в то время как расходы на инференс носят постоянный операционный характер.

  • Оптимизация VLLM обеспечивает рост пропускной способности почти в 15 раз по сравнению со стандартными решениями за счет постраничного внимания и непрерывной батчизации.

  • Фреймворк SGLang работает в три-четыре раза эффективнее при выполнении сложных агентских рабочих процессов и ветвлений.

타임라인

Постановка проблемы и экономика инференса LLM

  • Объем рынка инференса LLM достигает 23 миллиардов долларов.
  • Затраты на инференс являются постоянными операционными расходами, масштабируемыми с каждым новым пользователем и токеном.
  • Аппаратные ресурсы остаются ограниченными, а вычисления обходятся дорого.

Вводная часть воркшопа посвящена основным экономическим вызовам развертывания языковых моделей в продакшене. Затраты на инференс растут непрерывно в отличие от фиксированных расходов на обучение моделей. Для сохранения рентабельности стоимость отдельного запроса должна оставаться минимальной.

Анализ болевых точек инференса: память, TTFT и пропускная способность

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

На примере модели Mistral 7B демонстрируются ключевые проблемы производительности. По мере роста количества входных токенов увеличивается объем памяти, необходимый для хранения векторов ключей и значений (KV-cache). Это приводит к ограничению числа одновременных пользователей и росту задержки.

Фазы инференса и ограничения аппаратных ресурсов

  • Фаза предварительного заполнения (pre-fill) ограничена вычислительной мощностью GPU и определяет время до первого токена.
  • Фаза декодирования ограничена пропускной способностью памяти из-за последовательной генерации токенов.
  • Выбор графического процессора требует балансировки между допустимой задержкой, качеством и пропускной способностью.

Разбор архитектурных различий между фазой пре-филла и декодирования объясняет природу задержек на уровне железа. Высокая пропускная способность памяти GPU критически важна на этапе декодирования для быстрой передачи векторов и параметров.

Оптимизация моделей: квантование и механизмы внимания

  • Квантование моделей из FP16 в int8 и int4 сокращает объем занимаемой памяти в два и четыре раза соответственно.
  • Механизмы вроде группированного внимания (GQA) и многоголового латентного внимания (MLA) снижают нагрузку на память.
  • Flash Attention оптимизирует матричные вычисления за счет разбиения данных на блоки.

Танмай Шах освещает методы сжатия моделей и модификации архитектуры внимания. Переход от стандартного многоголового внимания к эффективным вариациям позволяет запускать крупные модели на ограниченном числе графических процессоров без критических потерь в качестве.

Оптимизация сервиинга и сравнение движков инференса

  • Постраничное внимание (PagedAttention) устраняет фрагментацию памяти в кэше KV.
  • Движок vLLM увеличивает пропускную способность почти в 15 раз по сравнению со стандартными решениями.
  • SGLang превосходит vLLM в три-четыре раза при выполнении сложных агентских рабочих процессов с ветвлением.

Заключительная часть посвящена программным инструментам развертывания LLM в продакшене. Применение непрерывной батчизации, префиксного кэширования и деревьев Радикса позволяет максимизировать эффективность использования оборудования при обработке стандартных API-запросов и автономных агентских систем.

커뮤니티 글

아직 글이 없습니다. 이 영상에 대한 첫 번째 글을 작성해 보세요!

이 영상에 대해 글쓰기