Обновить
11
0
Владислав Виноградов@jet-47

Разработчик ПО для ИИ

Отправить сообщение

Спасибо за комментарий!

По моделям - эмбеддинги, реранкеры и модели до 8B мы запускаем на RTX4090, остальные - на H100.

На данный момент мы не разделяем GPU между несколькими моделями, но наша DevOps команда рассматривает варианты для запуска нескольких серверов в рамках одной GPU, в том числе и на 4090 (https://habr.com/ru/articles/913374/, https://github.com/NVIDIA/KAI-Scheduler/blob/main/docs/gpu-sharing/README.md). Данный режим больше рассматривается для небольших моделей эмбеддингов и реранкеров.

Но вот потребление памяти - да, растет и сильно.

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

P.S. да, что-то про "20 инстансов DeepSeek-R1-Distill-Qwen-32B, что один полноценный deepseek-r1 - по скорости и ресурсам должно быть сопоставимо" я хватанул лишку, LLM не так хорошо параллелится, даже если опустить накладные расходы.

Тут ещё дело в том, что один инстанс большой модели обрабатывает один батч за раз. А 20 инстансов малой модели - 20 батчей за раз.

P.P.P.S. у новых Qwen3 контекст в 256K нативный и расширяется до 1M (вот только не помню, где это вычитал).

Да, есть такой механизм (YaRN) - https://qwen.readthedocs.io/en/latest/deployment/vllm.html#context-length. Мы так в Qwen 2.5 контекст с 32k до 128k расширяем. На счёт третьего Qwen'а - пока попробуем дефолтный 256k, это и так уже превышает наш текущий максимум. К тому же эта техника не бесплатна в плане производительности.

Спасибо за комментарий!

На счет новых моделей - мы как раз сейчас тестируем новые Qwen3 и T-pro 2.0 на своих задачах.

По поводу "полная" vs "малая" модель. Во-первых, 20 инстансов обеспечивают большую пропускную способность (throughput) системы, т.к. могут одновременно обрабатывать всходящий запросы. Во-вторых, большая модель будет работать медленнее за счет большей вычислительной сложности, большей нагрузки по работе с памятью и из-за дополнительных накладных расходов на распараллеливание и синхронизацию между GPU и серверами. В-третьих, что касается качества - грубо говоря, модель в 10 раз больше по размеру не даёт в 10 раз лучшее качество. Сейчас небольшие модели всё больше догоняют по результатам тяжелые. Мы, к примеру, у себя внутри экспериментировали с одной модель на 400B параметров в задачах суммаризации и тех.поддержки и там она себя не показала чем то лучше более "скромной" модели на 32B. А по ресурсам и скорости работы естественно проигрывала. В итоге мы решили отказаться от таких больших моделей в пользу более компактных, но лучше масштабируемых.

Одно из решений предложил пользователь социальной сети X под никнеймом shapoco. Он разработал небольшой рычаг, с помощью которого можно нажать на кнопку без переворачивания Mac mini.

Инженер Иван Кулешов показал сразу два решения. Первое — простой пластиковый рычаг-качалка, который устанавливается на стол перед Mac mini. Второе — полноценная подставка с мягкими подушечками. Она позволяет включить устройство нажатием на корпус.

Теперь Apple осталось только запатентовать эти решения и продавать по 1000 баксов за штуку :)

Спасибо за вопросы)

А собственно тензорный компилятор для RISC-V на базе OpenVINO/MLIR/DNNL/llvm, которому посвящена данная статья, - это opensource-проект? Под какой он лицензией?

На данный момент проект не доступен в opensource, но мы планируем это сделать (как для компилятора, так и для библиотеки оптимизированных операций).

Добавляется или свой диалект для RISC-V в рамках тензорного компилятора?

Нет, используются стандартные платформо-независимые диалекты MLIR, такие как vector, arith, math, llvm.

Оптимизации разрабатываемые в MLIR будут работать только для RISC-V или и для x86/arm/mips?

Большая часть компилятора использует платформо-независимые оптимизации. Уже в начале разработки компилятор также работал и на x86 платформе, хотя это больше использовалось для разработки и отладки. На данный момент мы также начинаем более углубленное тестирование на ARM архитектуре.

Верно ли, что для riscv был создан транслятор OpenVINO -> MLIR и ранее MLIR вместе с OpenVINO не использовался?

Да, был разработан свой транслятор OpenVINO -> MLIR и свой OV диалект для представления OpenVINO модели в терминах MLIR. Сам OpenVINO на данные момент не использует MLIR ни в каком виде, но есть отдельный плагин (https://github.com/openvinotoolkit/npu_plugin) для NPU устройств, который также использует MLIR для реализации собственного тензорного компилятора.

Упоминаемых 6 абстракций - это по аналогии с gcc/llvm 6 pass'ов, которые постепенно выполняют lowering от входных операций к выходным операциям? Выполнили lowering для циклов, выполнили lowering для call'ов и т.д., попутно выполняя некоторые арх.-независимые оптимизации? И все это на представлении MLIR, причем после очередного lowering-pass'а получаемое состояние называется диалектом MLIR?

В MLIR диалектом называется коллекция операций (а также типов и атрибутов), объединённых общим доменом. Например, диалект для OpenVINO модели, диалект для взаимодействия с GPU и т.п. Уровни абстракция - это скорее логическое разделение этапов работы компилятора. При этом тут нет однозначной 1-к-1 связи между диалектами и уровнями абстракций. Диалекты могут комбинироваться в рамках одного уровня, некоторые диалекты могут существовать на протяжении нескольких этапов компиляции. В данной статье указаны ключевые диалекты для каждого уровня, на самом деле на каждом уровне используются несколько диалектов. Так, например, диалекты linalg, affine, scf описывают итерации по тензорам на разном уровне абстракций, а для описания самих операций используются диалекты arith/math/vector. При lowering'е мы трансформируем linalg в affine, а затем affine в scf. При этом тело "цикла" не меняется. Векторизация происходит на этапе linalg диалекта.

Спасибо за интересные вопросы! Постараюсь ответить по порядку.

Правильно ли я понимаю, что есть две версии библиотеки: одна использует только скалярный код, вторая RVV 0.7.1?

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

интересно какой эффект дает использование векторных инструкций.

Т.к. скалярные версии операций в библиотеки не были специально оптимизированы, сравнение с ними было не особо интересно. Вместо этого нашей командой было произведено сравнение с библиотекой XNNPACK. Это достаточно известная библиотека оптимизированных операций, применяемая в основном для ARM устройств. Она также работает и на RISC-V, но в данный момент в ней нет отдельных векторных реализация для этой архитектуры, только оптимизированный скалярный код.

Сравнение делалось на другом наборе моделей и на другой плате (LicheePI - https://sipeed.com/licheepi4a), замерялось число инференсов-в-cекунду (FPS, больше-лучше). Наши RVV оптимизации показали 2х и больше преимущество по сравнению с инференсом через связку TfLite+XNNPACK.

|      Model     | Our Library RVV, FPS | XNNPACK scalar, FPS |
| face_mesh      | 73,3                 | 28                  |
| face_detection | 84,8                 | 40,6                |
| selfie         | 38,3                 | 15,8                |
| mobilefacenet  | 14,4                 | 5,4                 |
| anti-spoof-mn3 | 25,3                 | 12,3                |

Есть ли вас или еще кого-то у планы по добавлению поддержки RVV 0.7.1 в LLVM?

В рамках другой активности (тестирование Halide под RISC-V - https://github.com/dkurt/halide_riscv) были осуществлены некоторые наработки для поддержки RVV 0.7.1 в LLVM (https://github.com/dkurt/llvm-rvv-071). С полноценной реализацией поддержки RVV 0.7.1 в LLVM есть ряд нюансов:

  1. Мейнтейнеры LLVM не особо настроены видеть эту поддержку в официальной версии LLVM. В интернете можно найти обсуждения по этой теме. Основной посыл от разработчиков LLVM - он поддерживает только официально ратифицированные версии расширений, что не относится к RVV 0.7.

  2. Одновременная поддержка нескольких версий может быть не тривиальна. Лично мне тут трудно судить, ибо я плохо знаком с устройством бекендов в LLVM.

  3. Есть вероятность, что в ближайшее время на рынке появятся устройства с поддержкой RVV 1.0 и эта задача потеряет актуальность.

каким образом у вас вычисляются функции вроде exp и log в векторной реализации библиотеки?

log пока не реализован из-за отсутствия необходимости, exp реализована через аппроксимацию полиномом.

Информация

В рейтинге
Не участвует
Откуда
Нижний Новгород, Нижегородская обл., Россия
Работает в
Дата рождения
Зарегистрирован
Активность

Специализация

Десктоп разработчик, Бэкенд разработчик
Ведущий
Git
C++
Разработка программного обеспечения
ООП
Linux
Python
Bash
CI/CD