Skip to content

fix: cap automatic thread counts by OMP_NUM_THREADS - #208

Merged
gouyt13 merged 2 commits into
mainfrom
fix/omp-num-threads
Nov 1, 2026
Merged

gouyt13 merged 2 commits into
mainfrom
fix/omp-num-threads

Conversation

@gouyt13

@gouyt13 gouyt13 commented Nov 1, 2026 •

Copy link
Copy Markdown
Member

Summary

Fixes #207 and prepares the 0.8.1 release (txtai's macOS CI segfaults with 0.8.0, neuml/txtai#1494).

Cause. 0.8.0 changed the default of add to num_threads=0, and 0 resolved to every available CPU, ignoring the OpenMP thread limit. txtai's 0.7-style add(embeddings) therefore started an OpenMP worker team. On macOS, Faiss, PyTorch and rabitqlib each bundle their own libomp. When Faiss and PyTorch are loaded in the same process, starting rabitqlib's workers crashes with OMP: Error #179: Function pthread_mutex_init failed, followed by SIGSEGV. txtai already sets OMP_NUM_THREADS=1 on macOS for Faiss, but rabitqlib ignored it.

Change.

  • num_threads=0 now resolves to min(available CPUs, omp_get_max_threads()), which respects OMP_NUM_THREADS and omp_set_num_threads, like Faiss. This happens in a new compiled default_threads() called by resolve_num_threads(0), so the installed utils/tools.hpp does not pull in omp.h.
  • Explicit positive requests are unchanged: they are still capped only by the CPU count. Without OMP_NUM_THREADS, defaults still use every available CPU.
  • New private binding _default_thread_count for tests and the clustering example, next to _available_cpu_count.
  • Docs: threading contract, the macOS mixed-runtime caveat, the migration note and docstrings (.pyi and runtime kept in sync).

No API signature, saved-index format or dependency changes.

Release (second commit, chore(release): prepare v0.8.1).

  • Version 0.8.1 in pyproject.toml and CMakeLists.txt.
  • Install pins and version text updated in the README, quick start, installation guide, C++ integration guide, docs home page and the Python sample README. The sample README now requires 0.8.1 because the clustering example uses _default_thread_count.
  • docs/docs/releases/0.8.1.md with its navigation entry, and a README news entry.

Merging this into main triggers the automatic release: once Test and Python Wheel succeed for the merge commit, Release wheels tags v0.8.1, publishes to PyPI and creates the GitHub Release.

Testing

Local (Linux x86-64, GCC 14, native optimization OFF):

  • ./scripts/check-format.sh; full ./scripts/check-tidy.sh (clang-tidy 23): pass
  • C++ suite, OMP_NUM_THREADS=2 ctest --no-tests=error: 486 pass, 1 skipped (OpenMP binding test, not applicable on this runtime). The new ThreadCount.AutomaticRequestsRespectOpenMpThreadLimit and the updated assertions fail against the 0.8.0 resolution (96 instead of 1 or 2).
  • Package installed into the project env and the extension verified. pytest tests/python: 976 passed, 18 skipped (C++ example binaries not built; ARM64 and macOS wheel-only tests). Editor, mypy and Pyright checks: pass. check-python.sh: pass.
  • mkdocs build --strict: pass.

macOS arm64 (GitHub macos-15, temporary branch since deleted). A cp311 wheel was built with the release cibuildwheel config, including bundled libomp. Then txtai e5d8d43 was installed as its macOS CI does, and unittest discover -k testann was run:

  • PyPI 0.8.0: segfault in IvfIndex.add during testRabitQ
  • this branch: 72 tests OK (8 skipped), all RaBitQ tests pass
  • Replay of the txtai workload with faiss-cpu and torch imported: passes with OMP_NUM_THREADS=1; still crashes when the variable is unset. That case is documented: set OMP_NUM_THREADS=1 or pass num_threads=1.
  • Release commit: mkdocs build --strict, git diff --check, python -m unittest discover -s .github/scripts -p 'test_*.py' (60 tests): pass

Downstream compatibility

Platform: Intel Xeon Gold 6418H, Ubuntu 22.04.5 (kernel 6.8.0), GCC 14.3. The candidate is a wheel built from 7c74258 (this branch) with RABITQ_ENABLE_NATIVE_OPTIMIZATION=OFF.

txtai master at 379b5a3 (its RaBitQ backend last changed in 4d5e05f), Python 3.13, run in a temporary virtual environment:

python -m pytest test/python/testann/testdense/testrabitq.py
rabitqlib Result
0.8.0 (PyPI) 5 passed, 4 subtests passed
0.8.1 candidate 5 passed, 4 subtests passed; 74 warnings, all DeprecationWarning from txtai's 0.7-style calls (same as 0.8.0)

This covers the backend's IVF and HNSW build, query, save and load, and IVF append and delete. The macOS arm64 run of txtai's testann suite is listed under Testing.

zvec: not run yet. zvec builds core and FastScan with OpenMP off; this release changes only src/utils/thread_count.cpp in those components (a new function whose OpenMP query is compiled out when OpenMP is off) plus the version. CI's "Core and FastScan consumers (OpenMP OFF)" jobs on Linux, macOS and Windows build those components in zvec's configuration. zvec still needs the one-line test change from the 0.8.0 release (kbxsumq → g_kbxsumq).

Not tested: zvec's own build and tests, txtai outside its ANN tests, and native-optimized builds downstream.

num_threads=0 resolved to every available CPU and ignored the OpenMP thread
limit. Since 0.8.0 defaults add() to 0, txtai's 0.7-style add(x) started an
OpenMP worker team on macOS even though txtai sets OMP_NUM_THREADS=1 there.
With Faiss and PyTorch loaded, each bundling its own libomp, starting those
workers crashes (OMP Error #179, then SIGSEGV).

Resolve 0 to min(available CPUs, omp_get_max_threads()) like Faiss does;
explicit positive requests are still capped only by the CPU count. Document
the limit and the macOS mixed-runtime caveat.

Fixes #207
@github-actions github-actions Bot added the release:fixed Release category managed from the PR title label Nov 1, 2026
Bump the version to 0.8.1, update install pins and version text, and add
the 0.8.1 release notes with their navigation entry and a README news
entry. The Python sample README now requires 0.8.1 because the clustering
example uses the new _default_thread_count helper.
@gouyt13
gouyt13 merged commit fcc2b84 into main Nov 1, 2026
49 checks passed
@gouyt13
gouyt13 deleted the fix/omp-num-threads branch November 1, 2026 14:43
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

release:fixed Release category managed from the PR title

Projects

None yet

Development

Successfully merging this pull request may close these issues.

v0.8.0 causing segfault 11 on macOS

1 participant