Skip to main content

fastText inference with one loaded model and native C++ batch parallelism

Project description

fasttext-threaded

fasttext-threaded is a Python package for running fastText supervised model inference with one model loaded in memory and a native C++ thread pool doing parallel batch prediction.

The package is designed to preserve the official Python fastText predict interface while fixing the high-throughput inference case where Python threads do not provide useful model-level parallelism and Python processes multiply model memory.

Install

Install from PyPI:

pip install fasttext-threaded

For local development:

uv sync --all-extras
uv run pre-commit install

You need a C++17 compiler and CMake.

Usage

from fasttext_threaded import load_model

model = load_model("model.bin", threads=16)

labels, probs = model.predict("some text", k=1, threshold=0.0)
batch_labels, batch_probs = model.predict(
    ["first document", "second document"],
    k=1,
    threshold=0.0,
)

The public prediction signature intentionally matches official fastText:

predict(text, k=1, threshold=0.0, on_unicode_error="strict")

predict(list[str], ...) is the high-throughput path. It sends one batch into C++, releases the GIL, and partitions rows across native worker threads while using one loaded model.

predict_batch(texts, k=1, threshold=0.0, on_unicode_error="strict") is also available as a convenience alias for predict(texts, ...). It does not have different semantics.

Compatibility

The goal is API and behavior parity with official Python fastText for prediction:

  • predict(str) returns (tuple[str, ...], numpy.ndarray).
  • predict(list[str]) returns (list[list[str]], list[numpy.ndarray]).
  • newline-containing inputs are rejected with the same message shape as official fastText.
  • k, threshold, and labels/probabilities are tested against official fastText.

Why This Exists

Official fastText supports predict(list[str]), but the binding processes that batch with a serial C++ loop. Python-side ThreadPoolExecutor is not a reliable solution for throughput, and Python-side ProcessPoolExecutor loads one model copy per process.

This package targets the common production inference shape:

  • one model object in one Python process
  • one native C++ thread pool
  • large batches passed through predict(list[str], ...)
  • no TCP, pickle, JSON, or multiprocessing serialization on the hot path

Error Handling

The package exposes custom exceptions:

from fasttext_threaded import (
    FastTextThreadedError,
    InvalidInputError,
    ModelLoadError,
    PredictionError,
)

Input validation errors happen before worker threads are launched where possible. If a C++ worker fails during batch prediction, the first exception is captured, already-running workers finish, and the entire batch raises a Python exception. Partial predictions are not returned silently.

Benchmarks

Prepare a realistic language-identification benchmark using the official fastText lid.176.bin supervised model:

uv run python benchmarks/prepare_lid_benchmark.py --model-kind bin --repeat 5000

This downloads the 126 MB lid.176.bin model into .cache/ and writes a multilingual input corpus. The compressed lid.176.ftz model is also supported for quick smoke checks, but lid.176.bin is the meaningful default for performance measurements.

Run:

uv run python benchmarks/benchmark_inference.py \
  --model .cache/fasttext-threaded/lid/lid.176.bin \
  --input .cache/fasttext-threaded/lid/lid_input.txt \
  --threads 16 \
  --batch-size 4096

The benchmark compares:

  • official fastText single-thread predict(str) loop
  • official fastText predict(list[str])
  • official fastText with ThreadPoolExecutor
  • official fastText with ProcessPoolExecutor
  • fasttext_threaded.predict(list[str])

Reported metrics include throughput, latency percentiles, model load time, RSS memory, model-copy count, worker count, and a small parity sample.

For scaling plots across native threads, Python threads, and Python processes:

uv run python benchmarks/benchmark_scaling.py \
  --model .cache/fasttext-threaded/lid/lid.176.bin \
  --input .cache/fasttext-threaded/lid/lid_input.txt \
  --workers 1,2,4,8,16 \
  --process-workers 1,2,4 \
  --batch-size 4096 \
  --repeat 3

This writes:

  • .cache/fasttext-threaded/scaling/scaling_results.csv
  • .cache/fasttext-threaded/scaling/scaling_metadata.json
  • .cache/fasttext-threaded/scaling/scaling_plot.png

The scaling benchmark records wall time, parent-plus-child CPU time, RSS, model-copy count, machine metadata, and a four-panel plot. Each measured scenario runs in a fresh subprocess, and RSS is captured as peak parent-plus-child memory for that scenario.

Example result from a local Apple Silicon run with lid.176.bin, 54k documents, batch size 2048, and 5 repeats:

Method Workers Model copies Docs/s Peak RSS
official fastText batch 1 1 284,996 192 MB
official fastText + Python threads 16 1 178,204 200 MB
fasttext_threaded native threads 8 1 815,628 194 MB
fasttext_threaded native threads 16 1 880,588 196 MB
official fastText + Python processes 4 4 998,273 811 MB
official fastText + Python processes 8 8 1,298,549 1,544 MB
official fastText + Python processes 16 16 685,018 2,993 MB

The important tradeoff is that multiprocessing can win peak throughput at 8 processes on this machine, but it does so by loading many model copies. The native-thread path keeps one model copy and has a much smaller memory footprint.

Stress Test

Run:

uv run python stress/stress_inference.py \
  --model /path/to/model.bin \
  --input /path/to/input.txt \
  --threads 16 \
  --callers 32 \
  --duration 60

The stress test repeatedly calls one shared model from many Python threads and checks for crashes, exceptions, output count mismatches, order corruption, and RSS growth.

Development

uv sync --all-extras
uv run pre-commit run --all-files
uv run pytest

Native C++ tests can be run with:

uv run cmake -S . -B build -DFASTTEXT_THREADED_BUILD_TESTS=ON -DCMAKE_BUILD_TYPE=Release
uv run cmake --build build
uv run ctest --test-dir build --output-on-failure

Runtime-safety checks are available through sanitizer builds:

uv run cmake -S . -B build-asan \
  -DFASTTEXT_THREADED_BUILD_TESTS=ON \
  -DFASTTEXT_THREADED_ENABLE_ASAN=ON \
  -DCMAKE_BUILD_TYPE=Debug
uv run cmake --build build-asan
uv run ctest --test-dir build-asan --output-on-failure

Use FASTTEXT_THREADED_ENABLE_TSAN=ON instead of ASAN for ThreadSanitizer. Run the full stress tool locally for concurrency and memory-pressure testing.

Ruff and mypy are mandatory quality gates.

Release

Releases are published by GitHub Actions using PyPI Trusted Publishing. No long-lived PyPI token is required.

  1. Configure the PyPI project trusted publisher for this repository, .github/workflows/release.yaml, and the pypi GitHub environment.
  2. Require manual approval on the pypi environment.
  3. Push a SemVer tag:
git tag v0.1.0
git push origin v0.1.0

The release workflow builds the source distribution plus Linux and macOS wheels with cibuildwheel, validates all artifacts, and publishes them with PyPI Trusted Publishing.

Limitations

  • v1 targets Linux and macOS.
  • Windows wheels are not part of the initial release.
  • The primary speedup comes from batching. Per-row calls still pay Python call overhead and should not be used for throughput measurements.

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

fasttext_threaded-0.1.0.tar.gz (176.6 kB view details)

Uploaded Source

Built Distributions

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

fasttext_threaded-0.1.0-cp312-cp312-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl (241.0 kB view details)

Uploaded CPython 3.12manylinux: glibc 2.27+ x86-64manylinux: glibc 2.28+ x86-64

fasttext_threaded-0.1.0-cp312-cp312-macosx_11_0_arm64.whl (202.8 kB view details)

Uploaded CPython 3.12macOS 11.0+ ARM64

fasttext_threaded-0.1.0-cp312-cp312-macosx_10_13_x86_64.whl (215.0 kB view details)

Uploaded CPython 3.12macOS 10.13+ x86-64

fasttext_threaded-0.1.0-cp311-cp311-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl (236.8 kB view details)

Uploaded CPython 3.11manylinux: glibc 2.27+ x86-64manylinux: glibc 2.28+ x86-64

fasttext_threaded-0.1.0-cp311-cp311-macosx_11_0_arm64.whl (198.8 kB view details)

Uploaded CPython 3.11macOS 11.0+ ARM64

fasttext_threaded-0.1.0-cp311-cp311-macosx_10_9_x86_64.whl (211.8 kB view details)

Uploaded CPython 3.11macOS 10.9+ x86-64

fasttext_threaded-0.1.0-cp310-cp310-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl (236.4 kB view details)

Uploaded CPython 3.10manylinux: glibc 2.27+ x86-64manylinux: glibc 2.28+ x86-64

fasttext_threaded-0.1.0-cp310-cp310-macosx_11_0_arm64.whl (197.7 kB view details)

Uploaded CPython 3.10macOS 11.0+ ARM64

fasttext_threaded-0.1.0-cp310-cp310-macosx_10_9_x86_64.whl (210.6 kB view details)

Uploaded CPython 3.10macOS 10.9+ x86-64

File details

Details for the file fasttext_threaded-0.1.0.tar.gz.

File metadata

  • Download URL: fasttext_threaded-0.1.0.tar.gz
  • Upload date:
  • Size: 176.6 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.12

File hashes

Hashes for fasttext_threaded-0.1.0.tar.gz
Algorithm Hash digest
SHA256 6b784f1c668a2f680875fdb2cbac7a65944fd4137e8cfd9b76e86274a8f72997
MD5 9cd598f37c07d755992d5fcd85562372
BLAKE2b-256 0ce588bde8b12b17ccea551ce015501931fefdb110bbf46fb26c0ed1fea5ce5f

See more details on using hashes here.

Provenance

The following attestation bundles were made for fasttext_threaded-0.1.0.tar.gz:

Publisher: release.yaml on dkajtoch/fasttext-threaded

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file fasttext_threaded-0.1.0-cp312-cp312-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl.

File metadata

File hashes

Hashes for fasttext_threaded-0.1.0-cp312-cp312-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl
Algorithm Hash digest
SHA256 88f7debaeca4c8c47d79e663561f2f1c1d4a90c64c42b7ee8f7d798fed54a9cb
MD5 878b11c54e3868fcc3cb184258211617
BLAKE2b-256 bf17dca321513f371f7161933f11fd7d32eb78babe6f8fa202302553a64cc730

See more details on using hashes here.

Provenance

The following attestation bundles were made for fasttext_threaded-0.1.0-cp312-cp312-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl:

Publisher: release.yaml on dkajtoch/fasttext-threaded

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file fasttext_threaded-0.1.0-cp312-cp312-macosx_11_0_arm64.whl.

File metadata

File hashes

Hashes for fasttext_threaded-0.1.0-cp312-cp312-macosx_11_0_arm64.whl
Algorithm Hash digest
SHA256 cf4ab774ed9990fb3b6c98005b172a7e61512cbda79c685948719d2b14463151
MD5 dc88892c883a1a9024f3231b015e4d41
BLAKE2b-256 a2c9172f03d029661c8c0f32074124dfde019781deb31042210192b9023697ca

See more details on using hashes here.

Provenance

The following attestation bundles were made for fasttext_threaded-0.1.0-cp312-cp312-macosx_11_0_arm64.whl:

Publisher: release.yaml on dkajtoch/fasttext-threaded

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file fasttext_threaded-0.1.0-cp312-cp312-macosx_10_13_x86_64.whl.

File metadata

File hashes

Hashes for fasttext_threaded-0.1.0-cp312-cp312-macosx_10_13_x86_64.whl
Algorithm Hash digest
SHA256 317cac8965b450ce54a73ed200f8c3689a31d44e38b1d2b6e70d833e1ee59c0b
MD5 c9308a9610c1dd5aa010e880339848bc
BLAKE2b-256 4407362998c159d52c1654aaf5598883c7037001b58441f3335426cde03fbec4

See more details on using hashes here.

Provenance

The following attestation bundles were made for fasttext_threaded-0.1.0-cp312-cp312-macosx_10_13_x86_64.whl:

Publisher: release.yaml on dkajtoch/fasttext-threaded

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file fasttext_threaded-0.1.0-cp311-cp311-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl.

File metadata

File hashes

Hashes for fasttext_threaded-0.1.0-cp311-cp311-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl
Algorithm Hash digest
SHA256 d20d050511625ef213b821462cc08194a55c159dc238e10f3385b1f5c1ae9664
MD5 8b64d980e4dd3c4d8e268378ac641f87
BLAKE2b-256 26d5bdf1bd9b7eb963cca78d536c92a222ead59927bc768126fb3934a1d2bd69

See more details on using hashes here.

Provenance

The following attestation bundles were made for fasttext_threaded-0.1.0-cp311-cp311-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl:

Publisher: release.yaml on dkajtoch/fasttext-threaded

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file fasttext_threaded-0.1.0-cp311-cp311-macosx_11_0_arm64.whl.

File metadata

File hashes

Hashes for fasttext_threaded-0.1.0-cp311-cp311-macosx_11_0_arm64.whl
Algorithm Hash digest
SHA256 f542d9471f236b34b4fdb97d6a9a6118d20d1cc7ffa65cc523e0f855f42b6d6e
MD5 40e36674490c7fb6674553d413b9d4db
BLAKE2b-256 ecb15098b956f0d4a81cf7db730b6a57681e3c8ce5013341dd54e8e4862e27ed

See more details on using hashes here.

Provenance

The following attestation bundles were made for fasttext_threaded-0.1.0-cp311-cp311-macosx_11_0_arm64.whl:

Publisher: release.yaml on dkajtoch/fasttext-threaded

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file fasttext_threaded-0.1.0-cp311-cp311-macosx_10_9_x86_64.whl.

File metadata

File hashes

Hashes for fasttext_threaded-0.1.0-cp311-cp311-macosx_10_9_x86_64.whl
Algorithm Hash digest
SHA256 edab6e957a7ca35e963c909b0a071b6389028e7981a2a72cdbdddd6d62802fb6
MD5 4fc0e5338dd9e6ae9401730d21444239
BLAKE2b-256 e021480feac3d8c418b8286db89fb70790829f8abbd9e4e1155a741c3b9af2b9

See more details on using hashes here.

Provenance

The following attestation bundles were made for fasttext_threaded-0.1.0-cp311-cp311-macosx_10_9_x86_64.whl:

Publisher: release.yaml on dkajtoch/fasttext-threaded

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file fasttext_threaded-0.1.0-cp310-cp310-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl.

File metadata

File hashes

Hashes for fasttext_threaded-0.1.0-cp310-cp310-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl
Algorithm Hash digest
SHA256 1618434e82f513fd8fc51a5ea372a5ee30e0acfd7f38c0a199e228cadb86848c
MD5 fcb46bca48f19e2239acc507d256d89d
BLAKE2b-256 e9be307b3ce95fcbbd6f327e86ad57ee815f128ffd9e7f39c7c7ac574888dcc4

See more details on using hashes here.

Provenance

The following attestation bundles were made for fasttext_threaded-0.1.0-cp310-cp310-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl:

Publisher: release.yaml on dkajtoch/fasttext-threaded

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file fasttext_threaded-0.1.0-cp310-cp310-macosx_11_0_arm64.whl.

File metadata

File hashes

Hashes for fasttext_threaded-0.1.0-cp310-cp310-macosx_11_0_arm64.whl
Algorithm Hash digest
SHA256 dba860a54c2a4d326847000bdd9ab55e32394c49db961bcab43d7bb471d8744c
MD5 2abfe3236e3590f93e02159bd3e02757
BLAKE2b-256 aaf58304f715fd023a6bfd58bfdd096c3b0cc5499cc9dee68a65ec07c3e32878

See more details on using hashes here.

Provenance

The following attestation bundles were made for fasttext_threaded-0.1.0-cp310-cp310-macosx_11_0_arm64.whl:

Publisher: release.yaml on dkajtoch/fasttext-threaded

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file fasttext_threaded-0.1.0-cp310-cp310-macosx_10_9_x86_64.whl.

File metadata

File hashes

Hashes for fasttext_threaded-0.1.0-cp310-cp310-macosx_10_9_x86_64.whl
Algorithm Hash digest
SHA256 10fa8788488bee94d8c1c16e8d88baef9bdcb3eddbf8b599a0bdc1d1aa38c8d1
MD5 822b68f9240cd48c05395d39149da17f
BLAKE2b-256 eab28bd322dc85f6ae4d871847fd9393c9a64ac5ed029fe10f61b9beb63713fd

See more details on using hashes here.

Provenance

The following attestation bundles were made for fasttext_threaded-0.1.0-cp310-cp310-macosx_10_9_x86_64.whl:

Publisher: release.yaml on dkajtoch/fasttext-threaded

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

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