Skip to main content

FlashBertTokenizer implementation with C++ backend

Project description

FlashTokenizer

Tokenizer Library for LLM Serving

EFFICIENT AND OPTIMIZED TOKENIZER ENGINE FOR LLM INFERENCE SERVING

FlashTokenizer is a high-performance tokenizer implementation in C++ of the BertTokenizer used for LLM inference. It has the highest speed and accuracy of any tokenizer, such as FlashAttention and FlashInfer, and is 4-5 times faster than BertTokenizerFast in transformers.



FlashTokenizer includes the following core features

  • Implemented in C++17 and is fastest when built with LLVM.
  • Equally fast in Python via pybind11.
  • Blingfire was difficult to use in practice due to its low accuracy, but FlashBertTokenizer has both high accuracy and high speed.

News

  • [Mar 9 2025] Completed development of flash-tokenizer for BertTokenizer.

1. Installation

Requirements

  • clang++
  • g++
  • MSVC
  • python3.8 ~ 3.12

Install from PIP

pip install -U flash-tokenizer

2. Usage

from flash_tokenizer import FlashBertTokenizer
tokenizer = FlashBertTokenizer("path/to/vocab.txt", do_lower_case=True)
# Tokenize text
ids = tokenizer("Hello, world!")
print(ids)

3. Other Implementations

Most BERT-based models use the WordPiece Tokenizer, whose code can be found here. (A simple implementation of Huggingface can be found here).

Since the BertTokenizer is a CPU intensive algorithm, inference can be a bottleneck, and unoptimized tokenizers can be severely slow. A good example is the BidirectionalWordpieceTokenizer introduced in KR-BERT. Most of the code is the same, but the algorithm traverses the sub token backwards and writes a larger value compared to the forward traversal. The paper claims accuracy improvements, but it's hard to find other quantitative metrics, and the accuracy improvements aren't significant, and the tokenizer is seriously slowed down.

  • transformers (Rust Impl, PyO3)
  • paddlenlp (C++ Impl, pybind)
  • tensorflow-text (C++ Impl, pybind)
  • blingfire (C++ Impl, Native binary call)

Most developers will either use transformers.BertTokenizer or transformers.AutoTokenizer, but using AutoTokenizer will return transformers.BertTokenizerFast.

Naturally, it's faster than BertTokenizer, but the results aren't exactly the same, which means you're already giving up 100% accuracy starting with the tokenizer.

BertTokenizer is not only provided by transformers. PaddleNLP and tensorflow-text also provide BertTokenizer.

Then there's Blingfire, which is developed by Microsoft and is being abandoned.

PaddleNLP requires PaddlePaddle and provides tokenizer functionality starting with version 3.0rc. You can install it as follows

##### Install PaddlePaddle, PaddleNLP
python -m pip install paddlepaddle==3.0.0b1 -i https://www.paddlepaddle.org.cn/packages/stable/cpu/
pip install --upgrade paddlenlp==3.0.0b3

##### Install transformers
pip install transformers==4.47.1

##### Install tf-text
pip install tensorflow-text==2.18.1

##### Install blingfire
pip install blingfire

With the exception of blingfire, vocab.txt is all you need to run the tokenizer right away. (blingfire also requires only vocab.txt and can be used after 8 hours of learning).

The implementations we'll look at in detail are PaddleNLP's BertTokenizerFast and blingfire.

  • blingfire: Uses a Deterministic Finite State Machine (DFSM) to eliminate one linear scan and unnecessary comparisons, resulting in a time of O(n), which is impressive.
    • Advantages: 5-10x faster than other implementations.
    • Disadvantages: Long training time (8 hours) and lower accuracy than other implementations. (+Difficult to get help due to de facto development hiatus).
  • PaddleNLP: As shown in the experiments below, PaddleNLP is always faster than BertTokenizerFast (HF) to the same number of decimal places, and is always faster on any OS, whether X86 or Arm.
    • Advantages: Internal implementation is in C++ Compared to transformers.BertTokenizerFast implemented in Rust, it is 1.2x faster while outputting exactly the same values.
      • You can't specify pt(pytorch tensor) in return_tensors, but this is not a problem.[^1]
    • Disadvantages: none, other than the need to install PaddlePaddle and PaddleNLP.

4. Performance test

4.1 Performance test (Batch text encoding)

The graph below compares transformers.BertTokenizerFast and paddlenlp.transformers.bert.tokenizer_fast.BertTokenizerFast for batch size.

Both libraries are faster to return as np.ndarray. Perhaps the implementations have logic to convert to pt or pd at the end, which takes longer.

batchtest

BatchSize transformers(pt) paddlenlp(pd) transformers(np) paddlenlp(np)
1 2.32744 1.74695 1.87685 1.56597
2 1.87427 1.53865 1.50911 1.45918
4 1.54254 1.13622 1.12902 1.07593
8 1.25432 0.821463 0.850269 0.798163
16 1.09129 0.640243 0.67293 0.617309
32 0.994335 0.528553 0.587379 0.519887
64 0.971175 0.476652 0.537753 0.471145
128 0.952003 0.478113 0.531592 0.451384

[^1]: As you can see in the graph above, returning to pt(pytorch tensor)' becomes very slow.

4.2 Performance test (Single text encoding)

Accuracy is the result of measuring transformers.BertTokenizer as a baseline. If even one of the input_ids is incorrect, the answer is considered incorrect. Surprisingly, the performance of tensorflow-text is much faster than before. However, there is still no advantage for `tensorflow-text' when comparing the four libraries.

Tokenizer Elapsed Time (s) titles Accuracy (%)
BertTokenizer(Huggingface) 255.651 404,464 100 (Baseline)
FlashBertTokenizer 19.1325 ➡️ 16.526 🔺 404,464 99.3248 ➡️ 99.8442 🔺
BertTokenizerFast(HF) 73.3019 404,464 99.8615
BertTokenizerFast(PP) 64.0603 404,464 99.8615
FastBertTokenizer(TF) 77.6923 404,464 99.8507
Blingfire 11.5904 404,464 96.8979

For both single text and batch text, PaddleNLP's implementation is always faster than HuggingFace's implementation, and the results are exactly the same, so there is no unique advantage of HuggingFace's transformers.BertTokenizerFast.

Now you may have to make a decision between speed (blingfire) vs balance (PaddleNLP).

BertTokenizer requires a fast single-core CPU to get fast results.

The flash-tokenizer, which I implemented because I didn't like the other tokenizers, has a clear advantage in both speed and accuracy.

FlashTokenizer

FlashTokenizer

%%{ init: { "er" : { "layoutDirection" : "LR" } } }%%
erDiagram
    Text ||--o{ Preprocess : tokenize
    Preprocess o{--|| Inference : memcpy_h2d
    Inference o{--|| Postprocess : memcpy_d2h

TODO

Acknowledgement

FlashTokenizer is inspired by FlashAttention, FlashInfer, FastBertTokenizer and tokenizers-cpp projects.

References

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

flash_tokenizer-0.8.0.tar.gz (2.8 MB view details)

Uploaded Source

Built Distributions

If you're not sure about the file name format, learn more about wheel file names.

flash_tokenizer-0.8.0-cp312-cp312-win_amd64.whl (6.1 kB view details)

Uploaded CPython 3.12Windows x86-64

flash_tokenizer-0.8.0-cp312-cp312-macosx_15_0_arm64.whl (6.1 kB view details)

Uploaded CPython 3.12macOS 15.0+ ARM64

File details

Details for the file flash_tokenizer-0.8.0.tar.gz.

File metadata

  • Download URL: flash_tokenizer-0.8.0.tar.gz
  • Upload date:
  • Size: 2.8 MB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.1.0 CPython/3.12.2

File hashes

Hashes for flash_tokenizer-0.8.0.tar.gz
Algorithm Hash digest
SHA256 9bd829bab78e079c387fdba0d1b62fa2aad1b20aaea20dbd09c63b66119a65ed
MD5 4bc18869815e5a6d09897049077c2b35
BLAKE2b-256 cf2e3c39640011ee56c6fde3c54e7aeaaae1e48f521b9507fede2a200bbb4599

See more details on using hashes here.

File details

Details for the file flash_tokenizer-0.8.0-cp312-cp312-win_amd64.whl.

File metadata

File hashes

Hashes for flash_tokenizer-0.8.0-cp312-cp312-win_amd64.whl
Algorithm Hash digest
SHA256 d058968f402f13489d04aaa4401c5e224ce4f0d146bfe93401ef861935e97c09
MD5 7dd68cc4fb095258c238b6f759dba94c
BLAKE2b-256 4c0a1c2c9b40257f4a5cb262e7a414dfab38452893fe892d5a621f9dec2631b8

See more details on using hashes here.

File details

Details for the file flash_tokenizer-0.8.0-cp312-cp312-macosx_15_0_arm64.whl.

File metadata

File hashes

Hashes for flash_tokenizer-0.8.0-cp312-cp312-macosx_15_0_arm64.whl
Algorithm Hash digest
SHA256 dd208c4b9eb1a4f507ef8b31d675c6bebac1862e2d8fbca589318a6ceab50fca
MD5 7738863aa17f8b532332a096179ba930
BLAKE2b-256 30c90ee34d4e39256aba5b8ebda2afdccb3190a6917ecd2ff88b8abad8ec16bb

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page