Байки Neuradeep #1
Раз уж мы тут с Валерой @neuraldeep договорились немножечко ИИнфоцыганить, ловите технарский пост с ретроспективой сложностей NeuralDeep, о проблеме на движках vLLM, на которую наши пользователи жаловались последний месяц и которую мы никак не могли впоймать, ещё про драйверы и про телеметрию, но обо всё по порядку.
Qwen 3.8 на RTX 4090 48Гб вставал колом на картинках
Где-то с конца сентября начала октября движки Qwen3.8-27B малого лейна NeuralDeep (это наш второй московский ДЦ) на парах RTX 4090 время от времени замирали, только на одном московском сервере сторож за сутки перезапускал их 11 раз. Полезли в логи, видим на входе движка висят запросы, часть ждёт в очереди с причиной capacity, KV-кеш заполнен от силы на пятую часть, а карта показывает 0% утилизации при 20 ваттах потребления.
При этом самое занятное, что процесс vLLM жив, /health отвечает 200, в логе ядра ни Xid, ни AER, просто перестают расти счётчики токенов и баста. Клиенты с картинками в запросах ловили 502 или ждали ответ по 10-15 минут. Такой же движок в другом ДЦ на другом железе флапал точно так же, так что железо мы исключили быстро.
Оказалось, в vLLM 0.27.1 кеш энкодера жёстко равен шагу планировщика (encoder_cache_size = max_num_batched_tokens), шаг у нас был 4096 токенов, а картинка около 2 Мпикс занимает примерно 2048, то есть на весь движок в кеш влезают две картинки.
И вот приходит запрос с 3-4 картинками, у которого попадание в префиксный кеш обрывается посреди картинки, её надо перекодировать целиком, места нет, и планировщик выдаёт запросу ноль токенов, пока место не освободится. Освобождать некому, соседи держат свои картинки и ждут того же, и движок крутит пустые шаги. Патч одной строки в scheduler.py берёт кеш энкодера как максимум из шага и VLLM_NDT_ENCODER_CACHE_TOKENS, по четыре картинки на слот выходит 32768 токенов. Заодно по всему парку выставили --limit-mm-per-prompt в четыре картинки и одно видео, теперь пятая сразу получает 400.
Если у вас мультимодальная модель на vLLM с префиксным кешем, посчитайте, сколько картинок максимального размера влезает в кеш энкодера при вашем --max-num-batched-tokens, и сравните с числом слотов, умноженным на лимит картинок в запросе. Кеш меньше - вы в зоне риска.
По метрикам проблему можно заметить сразу, запросы копятся в waiting при почти пустом KV-кеше и простаивающей карте, и смотреть тогда надо в планировщик. Держите рядом с движком py-spy (профайлер питоновского кода), у нас его не было, а с ним пустые шаги планировщика видны в первом же дампе. Восемь минут ожидания до перезапуска движка сторожем тоже многовато, порог лучше держать в районе двух трёх минут. И фикс должен жить в рецепте образа и в спеке движка, иначе первое же пересоздание из старой спеки молча его откатит.
Про 580 драйвер от Nvidia
На некоторых серверах экспортеры переставали выгружать данные о состоянии GPU.
Симптоматика была такая, всё работало отлично, vLLM загружался, скорость в порядке, и в какой-то момент ядро теряло GSP одной из карт (Xid 119, затем Xid 154 с требованием ресета), сброс не помогал, а карту возвращала только полная перезагрузка сервера. При этом у нас были серверы, установленные раньше всех, у которых проблем не было.
Решили провести аудит и сравнить, чем полностью исправные серверы отличаются от неисправных, помимо версий некоторых пакетов и ядра заметили, что очень сильно отличается версия драйверов Nvidia. На стабильных серверах были драйверы 580 и ниже, на неисправных 605 и выше.
Далее всё было просто, делаем даунгрейд до нужной версии, фиксируем в политиках APT чтобы пакетный менеджер даже не помышлял об обновлении драйверов.
Судя по всему модифицированные 4090 в следствии модификации плохо работают на более свежих дровах.
Очень нужная и полезная телеметрия
Проводя в очередной раз аудит на одном из московских ДЦ увидели в логах заблокированные запросы на stats.vllm.ai, меня это очень сильно удивило, так как ранее мы в настройках движков vLLM создавали файл do_not_track, которым мы выключали отправку телеметрии раньше. Логи появились аккурат после обновления до новой версии vLLM. Разница была лишь в том, что раньше движки мы ставили прямо в ОС, а теперь решили использовать docker композиции и по всей видимости забыли cоздать нужные файлы при переносе.
При этом движки пересоздали из нового образа без VLLM_NO_USAGE_STATS=1 и DO_NOT_TRACK=1, файл do_not_track, которым их глушили раньше, остался в старых инсталляциях, и vLLM снова начал слать на stats.vllm.ai отчёт о железе и модели плюс heartbeat каждые 10 минут. Сейчас переключатели прописаны и в образе, и в спеке, и на уровне файрвола блокировка стоит.
И учтите, vLLM понимает только DO_NOT_TRACK=1, с true он продолжает отправлять статистику, статистика эта включает в себя время запуска, информацию о железе, в том числе и видеокартах, запущенную модель, количество токенов и многое многое другое.
Кстати, между делом прокачал мой скил gpu-server-setup, добавил туда подсказки для агента, чтобы он не забывал эту самую телеметрию отключать при установке.
Послесловие
Такое вот небольшое ретро получилось, есть ещё очень много нюансов с которыми сталкиваемся каждый день и которые стараемся по-всякому решать, если рубрика зайдёт буду и дальше травить всякие инженерные байки, stay tuned.