add faster BPE learning method: O(N) -> O(log N) per merge. 10x - 20x speedup or more (on large settings)#1208
Merged
Merged
Conversation
fix: improve logging in RunFastBPEMerges for better traceability refactor: remove unnecessary goto statement in RunFastBPEMerges refactor: adjust TrainAndGetPieces function signature for consistency
taku910
reviewed
Apr 14, 2026
taku910
left a comment
Collaborator
There was a problem hiding this comment.
This is a great achievement. However, since the integration into the current codebase is quite ad-hoc, we would like to treat this as a "contrib" feature for the time being.
- third_party/nlcodec is not the appropriate location, as that directory is reserved for external third-party libraries. Please create a contrib/ directory and move your code and related files there.
- Please create a #define macro to enable this feature, ensuring it is only built when that macro is defined.
- Make sure it can be enabled via a CMake build option.
While we can't promise a specific timeline, I hope to thoroughly verify the code under contrib/ and eventually merge it.
Contributor
Author
|
@taku910 Thanks for the review! I have revised the code as per your comments. |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Pull Request Details
third_party/nlcodec/bpe_model_trainer_nlcodec_test.ccRefer to third_party/nlcodec/README.md for additional details
NLCodec: Fast BPE Training for SentencePiece
A drop-in replacement for SentencePiece's BPE merge loop that achieves ~10× speedup by using a max-heap with lazy deletion instead of periodic linear scans.
Enabled via the
--nlcodec_bpeflag — everything else (sentence loading, normalization, whitespace handling, model serialization) uses SentencePiece's native code paths.Algorithm
SentencePiece's default BPE trainer scans an "active set" of bigrams linearly every iteration, with a full rescan every 100 steps — O(N) per merge.
NLCodec uses three data structures to achieve O(log N) per merge:
Reference: Gowda et al., "Many-to-English Machine Translation Tools, Data, and Pretrained Models", ACL 2021.
Usage
# Train with the fast BPE algorithm spm_train --input=data.txt --model_prefix=model \ --vocab_size=32000 --model_type=bpe \ --nlcodec_bpeThe output
.modeland.vocabfiles are identical in format to the default path.Files
bpe_model_trainer_nlcodec.hRunFastBPEMerges()declarationbpe_model_trainer_nlcodec.cc--nlcodec_bpeflag definitionbpe_model_trainer_nlcodec_test.ccbenchmark.shBenchmark
Run the benchmark (auto-downloads multilingual CC-100 data and builds SentencePiece):
Results: 200k multilingual sentences (en, de, zh, ar, hi), 32k vocab --> 10x speedup
The two paths produce nearly identical vocabularies (99% overlap) and equivalent compression. The small differences come from tie-breaking in pair frequency ordering.
Results: 1M multilingual sentences (en, de, zh, ar, hi), 64k vocab --> 24x speedup
The two paths produce nearly identical vocabularies (99.5% overlap) and equivalent compression. The small differences come from tie-breaking in pair frequency ordering.
Tests
Four test cases in
bpe_model_trainer_nlcodec_test.ccverify correctness:NlcodecBPETest.ProducesValidModelNlcodecBPETest.VocabSizeMatchesDefaultNlcodecBPETest.EncodesDecodesCorrectlyNlcodecBPETest.VocabOverlapsWithDefaultTo build and run: