trio-parallel: CPU parallelism for Trio¶
Do you have CPU-bound work that just keeps slowing down your Trio event loop no matter what you try? Do you need to get all those cores humming at once? This is the library for you!
The aim of trio-parallel is to use the lightest-weight, lowest-overhead, lowest-latency method to achieve CPU parallelism of arbitrary Python code with a dead-simple API.
import multiprocessing import trio import trio_parallel import time def hard_work(n, x): t = time.perf_counter() + n y = x while time.perf_counter() < t: x = not x print(y, "transformed into", x) return x async def too_slow(): await trio_parallel.run_sync(hard_work, 20, False, cancellable=True) async def amain(): t0 = time.perf_counter() async with trio.open_nursery() as nursery: nursery.start_soon(trio_parallel.run_sync, hard_work, 2, True) nursery.start_soon(trio_parallel.run_sync, hard_work, 1, False) nursery.start_soon(too_slow) result = await trio_parallel.run_sync(hard_work, 1.5, None) nursery.cancel_scope.cancel() print("got", result, "in", time.perf_counter() - t0, "seconds") # prints 2.xxx if __name__ == "__main__": multiprocessing.freeze_support() trio.run(amain)
Bypasses the GIL for CPU-bound work
Minimal API complexity
looks and feels like Trio threads
Minimal internal complexity
No reliance on
ProcessPoolExecutor, or any background threads
Automatic, opportunistic use of cloudpickle
Automatic LIFO caching of subprocesses
Cancel seriously misbehaving code
currently via SIGKILL/TerminateProcess
Convert segfaults and other scary things to catchable errors
How does trio-parallel run Python code in parallel?¶
Currently, this project is based on
multiprocessing subprocesses and
has all the usual multiprocessing caveats (
freeze_support, pickleable objects
only). The case for basing these workers on multiprocessing is that it keeps a lot of
complexity outside of the project while offering a set of quirks that users are
likely already familiar with.
The pickling limitations can be partially alleviated by installing cloudpickle.
Can I have my workers talk to each other?¶
This is currently possible through the use of
but we don’t and will not officially support it.
This package focuses on providing
a flat hierarchy of worker subprocesses to run synchronous, CPU-bound functions.
If you are looking to create a nested hierarchy of processes communicating
asynchronously with each other, while preserving the power, safety, and convenience of
structured concurrency, look into tractor.
Or, if you are looking for a more customized solution, try using
to spawn additional Trio runs and have them talk to each other over sockets.
Can I let my workers outlive the main Trio process?¶
The worker processes are started with the
daemon flag for lifetime management,
so this use case is not supported.
How should I map a function over a collection of arguments?¶
This is fully possible but we leave the implementation of that up to you. Think of us as a loky for your joblib, but natively async and Trionic. Some example parallelism patterns can be found in the documentation. Also, look into trimeter?