Hugging Face выпустила tokenizers v1, ускорение в 3, 30 раз

Hugging Face выпустила релиз-кандидат tokenizers v1, новую версию своей библиотеки токенизации на Rust, переписанную с упором на производительность. Команда объясняет мотивацию так: по мере роста моделей и нагрузок токенизация на CPU может стать узким местом и держать GPU простаивающим в ожидании данных.
На десяти семействах моделей, использованных для замера (восемь работают на byte pair encoding, или BPE, ещё два, на WordPiece и Unigram), v1 в однопоточном режиме на Apple M4 Max кодирует текст в 3, 30 раз быстрее v0.23: медленнее всего прирост у t5-base, быстрее всего, у gpt2. Отдельно замерено масштабирование на восьми рабочих потоках, оно достигает 76% от идеального линейного; это другая метрика, и складывать её с однопоточным ускорением источник не даёт оснований. При этом v1 сохраняет полную совместимость: он выдаёт ровно те же ID токенов, тот же API, тот же словарь и те же ранги слияний, что и v0.23, и загружает всё, что грузила прежняя версия, библиотека остаётся общей для разных семейств токенизаторов, а не специализируется только под BPE.
Ускорение собрано из нескольких изменений в разных точках конвейера. Разбиение текста на пре-токены раньше делал движок регулярных выражений; в v1 для распознаваемых токенизаторов (GPT-2, cl100k, o200k, Tekken, DeepSeek) это делает написанный вручную сплиттер bitcannon, он читает байты входа как потоки бит и ищет границы через битовые операции над целыми регистрами процессора (SIMD), обрабатывая по 64 байта за операцию; для токенизаторов с нераспознанным паттерном путь остаётся прежним, регексовым, без этого ускорения. Дальше добавлен потокобезопасный по потоку (thread-local) кэш слов: поскольку BPE всегда даёт для одного и того же пре-токена одни и те же ID, повторные вхождения слова берутся из кэша без повторного прогона слияний, эффект растёт с долей повторов в тексте. Наконец, переработан сам цикл слияний BPE: он переиспользует буфер вызывающей стороны вместо повторных выделений памяти на каждый вызов, хранит символы в плоском массиве со связями по позициям, упаковывает каждую пару-кандидата в одно 64-битное число с рангом слияния в старших битах (что делает сравнение пар обычным сравнением целых чисел без ветвлений) и обрабатывает пачку пре-токенов за один вызов модели вместо одного вызова на каждый.
Релиз-кандидат уже доступен как крейт на crates.io и ставится обычной командой cargo add tokenizers --pre; вызываемый API, тот же, что и раньше. Обучение токенизатора по умолчанию тянет за собой C++-зависимость; чтобы оставить только кодирование, её можно отключить флагами --no-default-features --features http. Python-обвязка использует тот же код, но добавляет накладные расходы на каждый вызов, которые в бенчмарки поста не входят.
Hugging Face благодарит IBM, NVIDIA и команду ExecuTorch за патчи и помощь с тестированием на широком спектре оборудования. Ближайший приоритет, перенести на новый цикл слияний больше семейств моделей до выхода 1.0.0; дата этого релиза в посте не названа, сказано лишь, что он последует после стабилизации релиз-кандидатов. В план на 1.0.0 также входят: единая реализация кодирования, используемая и при обучении, и при инференсе (чтобы они не расходились в результатах); необязательные офсеты и маски, которые считаются только по запросу; переработка нормализаторов; более простая Python-обвязка; инференс-only биндинги на C и C++ для ExecuTorch и llama.cpp, с возможными биндингами для JVM, Swift и Go позже. После 1.0.0 команда собирается исследовать перенос кодирования и пакетного декодирования на GPU, храня текст и ID токенов прямо на устройстве.
Ключевые факты
- Hugging Face выпустила релиз-кандидат tokenizers v1, переписанную под скорость Rust-библиотеку токенизации, уже доступную на crates.io
- На одном потоке, на Apple M4 Max, v1 кодирует текст в 3, 30 раз быстрее v0.23 (от t5-base на нижней границе до gpt2 на верхней); на восьми потоках масштабирование достигает 76% от линейного, это отдельная, не складываемая с первой метрика
- Ключевые изменения: сплиттер bitcannon на битовых потоках и SIMD вместо регулярных выражений (для распознанных семейств токенизаторов), thread-local кэш повторяющихся слов и переработанный цикл слияний BPE без лишних выделений памяти
- v1 полностью совместим: те же ID токенов, тот же API и словарь, что и v0.23; ставится командой cargo add tokenizers --pre
- IBM, NVIDIA и команда ExecuTorch помогли с патчами и тестированием на разном оборудовании; впереди, больше семейств моделей на новом цикле слияний, затем 1.0.0 и в перспективе перенос кодирования на GPU
Почему это важно
Токенизация, обязательный шаг перед тем, как модель увидит текст, и при больших датасетах, множестве одновременных запросов или длинных входах она может не успевать за GPU, оставляя его простаивать в ожидании данных с CPU. tokenizers v1 нацелен ровно на это: убрать токенизацию как узкое место, ускорив однопоточное кодирование в 3, 30 раз при сохранении тех же результатов, что и в v0.23.
Кому это важно
Тем, кто обучает модели на больших корпусах или обслуживает много запросов в продакшене и упирается в CPU-часть конвейера, инженерам инфраструктуры обучения и инференса, использующим библиотеку tokenizers (в том числе через экосистему Hugging Face, включая transformers, куда улучшения придут позже). Прирост зависит от семейства токенизатора: он ощутимее там, где применяется новый bitstream-сплиттер и работает кэш повторяющихся слов.
Как это применить
Релиз-кандидат ставится как обычно, cargo add tokenizers --pre, вызываемый API не меняется. Если нужно только кодирование без обучения токенизатора, можно исключить связанную с обучением C++-зависимость флагами --no-default-features --features http. Python-обвязка работает поверх того же кода, но добавляет накладные расходы на вызов, которые не учтены в приведённых цифрах ускорения.
Можно ли доверять
Это официальный пост команды tokenizers на блоге Hugging Face о собственной библиотеке, источник авторитетный, но не независимый: бенчмарки собраны инструментом того же проекта (tokbench), а обкатку на разном оборудовании обеспечили партнёры IBM, NVIDIA и команда ExecuTorch. Пост сам оговаривает методические тонкости, разница между повторным кодированием одного документа и потоком разных документов, что говорит в пользу аккуратности замеров, но независимой перепроверки цифр в источнике нет.
Риски и подводные камни
Речь о релиз-кандидате, а не о финальном 1.0.0, часть запланированных изменений (переработка нормализаторов, единая реализация кодирования для обучения и инференса, упрощение Python-обвязки) ещё впереди, и дата 1.0.0 не названа. Ускорение через bitstream-сплиттер работает только для токенизаторов с распознанным паттерном (GPT-2, cl100k, o200k, Tekken, DeepSeek), для остальных сохраняется прежний, более медленный путь через регулярные выражения. Выигрыш от кэша слов также зависит от текста: во входе с малым числом повторяющихся слов кэш может не окупать сами обращения к нему.