macOS Python 3.14 CPU backend: intra_threads=0 aborts on 4.7.2 and oversubscribes on 4.8.0
Nobody has claimed this yet.
- Dominant language
- C++
- Stars
- 4.7k
- Forks
- 536
- Avg merge
- 12h 12m
- Merged PRs (30d)
- 4
Description
Summary
On macOS arm64 with Python 3.14.5, the no-OpenMP CTranslate2 CPU backend behaves poorly when intra_threads=0 is used through Argos Translate. In 4.7.2 it produced a native abort during a sustained translation workload. In 4.8.0 the same workload no longer aborted in my test, but the automatic backend threading path was still pathologically slow and CPU-heavy compared with intra_threads=1.
Environment
macOS 26.5.1 arm64
Python 3.14.5
CTranslate2 4.7.2 and 4.8.0 wheels
Argos Translate / argostranslate-lt 1.12.1
English -> Russian Argos model
4.7.2 crash
With CTranslate2 4.7.2 and Argos' default ARGOS_INTRA_THREADS=0, a sustained Markdown translation workload aborted after several hundred translation calls:
libc++abi: terminating due to uncaught exception of type std::__1::system_error:
condition_variable wait failed: Invalid argument
Crash report showed the faulting thread inside the vendored CPU backend thread pool:
BS::thread_pool_light::worker()
std::__1::condition_variable::wait(...)
The main thread was waiting in:
ctranslate2::python::wait_on_futures<ctranslate2::TranslationResult>(...)
ctranslate2::python::TranslatorWrapper::translate_batch(...)
4.8.0 performance problem
I upgraded the same environment to CTranslate2 4.8.0. The crash-adjacent segment completed, and a full sustained run completed when using intra_threads=1.
However, with the unpatched default intra_threads=0, the process became extremely CPU-heavy and slow:
CPU: ~1470%
Hot path: ctranslate2::TranslatorWrapper::translate_batch
ctranslate2::ops::Gemm::compute
ruy::ThreadPool::ExecuteImpl
ruy::BlockingCounter::Wait
BS::thread_pool...
Benchmark on the same 30-unit Markdown slice with CTranslate2 4.8.0:
intra=0 TIMEOUT >60s
intra=1 elapsed=31.012s user=36.103s sys=0.120s
intra=2 elapsed=48.529s user=84.297s sys=19.564s
intra=4 elapsed=38.526s user=139.771s sys=28.153s
intra=8 elapsed=37.895s user=275.805s sys=28.084s
For this workload, intra_threads=1 is both fastest and most stable.
Notes
Argos Translate is mitigating this by defaulting ARGOS_INTRA_THREADS to 1 on Darwin while preserving explicit user overrides:
https://github.com/argosopentech/argos-translate/pull/528
I am filing this here because the 4.7.2 abort and 4.8.0 oversubscription both appear to originate in the CTranslate2 macOS no-OpenMP CPU backend path when the backend default thread count is selected.
Contributor guide
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Research direction
Start by reproducing the macOS arm64 workload with CTranslate2 4.8.0, comparing intra_threads=0 with 1, and inspect TranslatorWrapper::translate_batch, the vendored BS::thread_pool, and ruy::ThreadPool::ExecuteImpl. Done means explaining and correcting the abort or oversubscription path while preserving explicit thread-count overrides, then validating the sustained translation benchmark.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- cpp, macos, python
- Domain
- backend, operating-systems, performance
- Issue type
- Bug
- Difficulty
- 4/5
- Estimated time
- 3-5 days
- Activity status
- Quiet
- Clarity
- Mostly clear
- Newbie friendliness
- 48/100