Add support for Python 3.14#597
Conversation
|
Auto-sync is disabled for draft pull requests in this repository. Workflows must be run manually. Contributors can view more details about this message here. |
|
/ok to test |
2 similar comments
|
/ok to test |
|
/ok to test |
|
On Python 3.13, 🐚 pytest --sw --import-mode=append -vs python/ucxx/ucxx/_lib_async/tests --runslow
========================================================================== test session starts ===========================================================================
platform linux -- Python 3.13.12, pytest-8.4.2, pluggy-1.6.0 -- /home/gforsyth/miniforge3/envs/ucxxdev/bin/python3.13
cachedir: .pytest_cache
rootdir: /home/gforsyth/github.com/rapidsai/ucxx/python/ucxx
configfile: pyproject.toml
plugins: asyncio-1.3.0, rerunfailures-16.1
asyncio: mode=Mode.AUTO, debug=False, asyncio_default_fixture_loop_scope=None, asyncio_default_test_loop_scope=function
collected 579 items
stepwise: no previously failed tests, not skipping.
python/ucxx/ucxx/_lib_async/tests/test_benchmark_cluster.py::test_benchmark_cluster [1772122774.873342] [0e080ca-lcedt:606109:0] ucp_context.c:2339 UCX WARN UCP API version is incompatible: required >= 1.20, actual 1.19.0 (loaded from /home/gforsyth/miniforge3/envs/ucxxdev/lib/python3.13/site-packages/libucx/lib/libucp.so)
[1772122775.098271] [0e080ca-lcedt:606109:0] parser.c:2359 UCX WARN unused environment variable: UCX_MEMTYPE_CACHE (maybe: UCX_MEMTYPE_CACHE?)
[1772122775.098271] [0e080ca-lcedt:606109:0] parser.c:2359 UCX WARN (set UCX_WARN_UNUSED_ENV_VARS=n to suppress this warning)
[1772122775.126022] [0e080ca-lcedt:606287:0] ucp_context.c:2339 UCX WARN UCP API version is incompatible: required >= 1.20, actual 1.19.0 (loaded from /home/gforsyth/miniforge3/envs/ucxxdev/lib/python3.13/site-packages/libucx/lib/libucp.so)
[1772122775.131814] [0e080ca-lcedt:606292:0] ucp_context.c:2339 UCX WARN UCP API version is incompatible: required >= 1.20, actual 1.19.0 (loaded from /home/gforsyth/miniforge3/envs/ucxxdev/lib/python3.13/site-packages/libucx/lib/libucp.so)
[1772122775.137594] [0e080ca-lcedt:606299:0] ucp_context.c:2339 UCX WARN UCP API version is incompatible: required >= 1.20, actual 1.19.0 (loaded from /home/gforsyth/miniforge3/envs/ucxxdev/lib/python3.13/site-packages/libucx/lib/libucp.so)
[1772122775.143577] [0e080ca-lcedt:606304:0] ucp_context.c:2339 UCX WARN UCP API version is incompatible: required >= 1.20, actual 1.19.0 (loaded from /home/gforsyth/miniforge3/envs/ucxxdev/lib/python3.13/site-packages/libucx/lib/libucp.so)
[1772122775.298053] [0e080ca-lcedt:606287:0] parser.c:2359 UCX WARN unused environment variable: UCX_MEMTYPE_CACHE (maybe: UCX_MEMTYPE_CACHE?)
[1772122775.298053] [0e080ca-lcedt:606287:0] parser.c:2359 UCX WARN (set UCX_WARN_UNUSED_ENV_VARS=n to suppress this warning)
[1772122775.320073] [0e080ca-lcedt:606304:0] parser.c:2359 UCX WARN unused environment variable: UCX_MEMTYPE_CACHE (maybe: UCX_MEMTYPE_CACHE?)
[1772122775.320073] [0e080ca-lcedt:606304:0] parser.c:2359 UCX WARN (set UCX_WARN_UNUSED_ENV_VARS=n to suppress this warning)
[1772122775.320493] [0e080ca-lcedt:606292:0] parser.c:2359 UCX WARN unused environment variable: UCX_MEMTYPE_CACHE (maybe: UCX_MEMTYPE_CACHE?)
[1772122775.320493] [0e080ca-lcedt:606292:0] parser.c:2359 UCX WARN (set UCX_WARN_UNUSED_ENV_VARS=n to suppress this warning)
[1772122775.331453] [0e080ca-lcedt:606299:0] parser.c:2359 UCX WARN unused environment variable: UCX_MEMTYPE_CACHE (maybe: UCX_MEMTYPE_CACHE?)
[1772122775.331453] [0e080ca-lcedt:606299:0] parser.c:2359 UCX WARN (set UCX_WARN_UNUSED_ENV_VARS=n to suppress this warning)
PASSED
python/ucxx/ucxx/_lib_async/tests/test_config.py::test_get_config PASSED
python/ucxx/ucxx/_lib_async/tests/test_config.py::test_set_env PASSED
python/ucxx/ucxx/_lib_async/tests/test_config.py::test_init_options [1772122776.238999] [0e080ca-lcedt:605539:0] ucp_context.c:2339 UCX WARN UCP API version is incompatible: required >= 1.20, actual 1.19.0 (loaded from /home/gforsyth/miniforge3/envs/ucxxdev/lib/python3.13/site-packages/libucx/lib/libucp.so)
[1772122776.353658] [0e080ca-lcedt:605539:0] parser.c:2359 UCX WARN unused environment variable: UCX_MEMTYPE_CACHE (maybe: UCX_MEMTYPE_CACHE?)
[1772122776.353658] [0e080ca-lcedt:605539:0] parser.c:2359 UCX WARN (set UCX_WARN_UNUSED_ENV_VARS=n to suppress this warning)
PASSED
python/ucxx/ucxx/_lib_async/tests/test_config.py::test_init_options_and_env [1772122776.539047] [0e080ca-lcedt:605539:0] ucp_context.c:2339 UCX WARN UCP API version is incompatible: required >= 1.20, actual 1.19.0 (loaded from /home/gforsyth/miniforge3/envs/ucxxdev/lib/python3.13/site-packages/libucx/lib/libucp.so)
PASSED
python/ucxx/ucxx/_lib_async/tests/test_config.py::test_init_unknown_option SKIPPED (Beginning with UCX >= 1.12, it's only possible to validate UCP options but...)
python/ucxx/ucxx/_lib_async/tests/test_config.py::test_init_invalid_option [1772122776.705415] [0e080ca-lcedt:605539:0] parser.c:1340 UCX ERROR Invalid value for SEG_SIZE: 'invalid-size'. Expected: memory units: <number>[b|kb|mb|gb], "inf", or "auto"
PASSED
python/ucxx/ucxx/_lib_async/tests/test_config.py::test_logging [1772122776.741599] [0e080ca-lcedt:605539:0] ucp_context.c:2339 UCX WARN UCP API version is incompatible: required >= 1.20, actual 1.19.0 (loaded from /home/gforsyth/miniforge3/envs/ucxxdev/lib/python3.13/site-packages/libucx/lib/libucp.so)
[1772122776.898959] [0e080ca-lcedt:605539:0] ucp_context.c:2339 UCX WARN UCP API version is incompatible: required >= 1.20, actual 1.19.0 (loaded from /home/gforsyth/miniforge3/envs/ucxxdev/lib/python3.13/site-packages/libucx/lib/libucp.so)However when trying this on Python 3.14: 🐚 pytest --sw --import-mode=append -vs python/ucxx/ucxx/_lib_async/tests --runslow
========================================================================== test session starts ===========================================================================
platform linux -- Python 3.14.3, pytest-8.4.2, pluggy-1.6.0 -- /home/gforsyth/miniforge3/envs/ucxxdev/bin/python3.14
cachedir: .pytest_cache
rootdir: /home/gforsyth/github.com/rapidsai/ucxx/python/ucxx
configfile: pyproject.toml
plugins: asyncio-1.3.0, rerunfailures-16.1
asyncio: mode=Mode.AUTO, debug=False, asyncio_default_fixture_loop_scope=None, asyncio_default_test_loop_scope=function
collected 579 items
stepwise: no previously failed tests, not skipping.
python/ucxx/ucxx/_lib_async/tests/test_benchmark_cluster.py::test_benchmark_cluster Traceback (most recent call last):
File "/home/gforsyth/miniforge3/envs/ucxxdev/lib/python3.14/multiprocessing/forkserver.py", line 344, in main
code = _serve_one(child_r, fds,
unused_fds,
old_handlers)
File "/home/gforsyth/miniforge3/envs/ucxxdev/lib/python3.14/multiprocessing/forkserver.py", line 384, in _serve_one
code = spawn._main(child_r, parent_sentinel)
File "/home/gforsyth/miniforge3/envs/ucxxdev/lib/python3.14/multiprocessing/spawn.py", line 132, in _main
self = reduction.pickle.load(from_parent)
File "/home/gforsyth/miniforge3/envs/ucxxdev/lib/python3.14/multiprocessing/synchronize.py", line 117, in __setstate__
self._semlock = _multiprocessing.SemLock._rebuild(*state)
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~^^^^^^^^
FileNotFoundError: [Errno 2] No such file or directory
Traceback (most recent call last):
File "/home/gforsyth/miniforge3/envs/ucxxdev/lib/python3.14/multiprocessing/forkserver.py", line 344, in main
code = _serve_one(child_r, fds,
unused_fds,
old_handlers)
File "/home/gforsyth/miniforge3/envs/ucxxdev/lib/python3.14/multiprocessing/forkserver.py", line 384, in _serve_one
code = spawn._main(child_r, parent_sentinel)
File "/home/gforsyth/miniforge3/envs/ucxxdev/lib/python3.14/multiprocessing/spawn.py", line 132, in _main
self = reduction.pickle.load(from_parent)
File "/home/gforsyth/miniforge3/envs/ucxxdev/lib/python3.14/multiprocessing/synchronize.py", line 117, in __setstate__
self._semlock = _multiprocessing.SemLock._rebuild(*state)
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~^^^^^^^^
FileNotFoundError: [Errno 2] No such file or directory
Traceback (most recent call last):
Traceback (most recent call last):
File "/home/gforsyth/miniforge3/envs/ucxxdev/lib/python3.14/multiprocessing/forkserver.py", line 344, in main
code = _serve_one(child_r, fds,
unused_fds,
old_handlers)
File "/home/gforsyth/miniforge3/envs/ucxxdev/lib/python3.14/multiprocessing/forkserver.py", line 344, in main
code = _serve_one(child_r, fds,
unused_fds,
old_handlers)
File "/home/gforsyth/miniforge3/envs/ucxxdev/lib/python3.14/multiprocessing/forkserver.py", line 384, in _serve_one
code = spawn._main(child_r, parent_sentinel)
File "/home/gforsyth/miniforge3/envs/ucxxdev/lib/python3.14/multiprocessing/forkserver.py", line 384, in _serve_one
code = spawn._main(child_r, parent_sentinel)
File "/home/gforsyth/miniforge3/envs/ucxxdev/lib/python3.14/multiprocessing/spawn.py", line 132, in _main
self = reduction.pickle.load(from_parent)
File "/home/gforsyth/miniforge3/envs/ucxxdev/lib/python3.14/multiprocessing/spawn.py", line 132, in _main
self = reduction.pickle.load(from_parent)
File "/home/gforsyth/miniforge3/envs/ucxxdev/lib/python3.14/multiprocessing/synchronize.py", line 117, in __setstate__
self._semlock = _multiprocessing.SemLock._rebuild(*state)
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~^^^^^^^^
File "/home/gforsyth/miniforge3/envs/ucxxdev/lib/python3.14/multiprocessing/synchronize.py", line 117, in __setstate__
self._semlock = _multiprocessing.SemLock._rebuild(*state)
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~^^^^^^^^
FileNotFoundError: [Errno 2] No such file or directory
FileNotFoundError: [Errno 2] No such file or directoryThese failures originate in calls to @pytest.mark.asyncio
async def test_benchmark_cluster(n_chunks=1, n_nodes=2, n_workers=2):
server_file = tempfile.NamedTemporaryFile()
server, server_ret = _run_cluster_server(server_file.name, n_nodes * n_workers)
# Wait for server to become available
with open(server_file.name, "r") as f:
while len(f.read()) == 0:
pass
workers = list(
chain.from_iterable(
_run_cluster_workers(server_file.name, n_chunks, n_workers, i, _worker)
for i in range(n_nodes)
)
)
join_processes(workers + [server], timeout=30)
for worker in workers:
terminate_process(worker)
terminate_process(server)Given the errors raise from Print debugging at: file:///home/gforsyth/github.com/rapidsai/ucxx/python/ucxx/ucxx/benchmarks/utils.py q = mp.Queue()
p = mp.Process(
target=_server_process,
args=(
q,
server_file,
n_workers,
ucx_options_list,
),
)
p.start()
return p, qOn Python 3.14, The context at test time is On Python 3.13, This does indicate that the issue stems from the Changing diff --git a/python/ucxx/ucxx/benchmarks/utils.py b/python/ucxx/ucxx/benchmarks/utils.py
index 5ff72b9..cb77a54 100644
--- a/python/ucxx/ucxx/benchmarks/utils.py
+++ b/python/ucxx/ucxx/benchmarks/utils.py
@@ -163,8 +163,9 @@ def _run_cluster_server(
A tuple with two elements: the process spawned and a queue where results
will eventually be stored.
"""
- q = mp.Queue()
- p = mp.Process(
+ ctx = mp.get_context("fork")
+ q = ctx.Queue()
+ p = ctx.Process(
target=_server_process,
args=(
q,
@@ -173,6 +174,7 @@ def _run_cluster_server(
ucx_options_list,
),
)
+
p.start()
return p, q
@@ -343,10 +345,11 @@ def _run_cluster_workers(
)
processes = []
+ ctx = mp.get_context("fork")
for worker_num in range(num_node_workers):
rank = node_idx * num_node_workers + worker_num
- q = mp.Queue()
- p = mp.Process(
+ q = ctx.Queue()
+ p = ctx.Process(
target=_worker_process,
args=(
q, File "/home/gforsyth/github.com/rapidsai/ucxx/python/ucxx/ucxx/_lib_async/tests/conftest.py", line 70, in ucxx_setup_teardown
loop = asyncio.get_event_loop()
File "/home/gforsyth/miniforge3/envs/ucxxdev/lib/python3.14/asyncio/events.py", line 715, in get_event_loop
raise RuntimeError('There is no current event loop in thread %r.'
% threading.current_thread().name)
RuntimeError: There is no current event loop in thread 'MainThread'.file:///home/gforsyth/github.com/rapidsai/ucxx/python/ucxx/ucxx/benchmarks/utils.py |
|
Ah, the event loop teardown issue is also because of Python 3.14:
|
Python 3.14 changed default context from `fork` to `forkserver` -- it was unset here and working, so changing it to explicit `fork`
Python 3.14 raises a `RuntimeError` for `get_event_loop`, ignoring that
TomAugspurger
left a comment
There was a problem hiding this comment.
Thanks.
Everything I've read suggests that correctly and safely using fork is basically impossible for us mortals. But given that that change is just in a benchmark and it's worked up until this point, I think that it's OK to not investigate this any further for now.
|
/merge |
|
| - pytest-rerunfailures!=16.0.0 | ||
| - pytest<9.0.0 | ||
| - python>=3.11,<3.14 | ||
| - python>=3.11 |
There was a problem hiding this comment.
As usual, please to have upper-bounded by the version we haven't tested (i.e. 3.15).

Description
Contributes to rapidsai/build-planning#205
This PR adds support for Python 3.14.
Notes for Reviewers
This is part of ongoing work to add Python 3.14 support across RAPIDS.
It temporarily introduces a build/test matrix including Python 3.14, from rapidsai/shared-workflows#508.
A follow-up PR will revert back to pointing at the
mainbranch ofshared-workflowsonce allRAPIDS repos have added Python 3.14 support.
This will fail until all dependencies have been updated to Python 3.14
CI here is expected to fail until all of this project's upstream dependencies support Python 3.14.
This can be merged whenever all CI jobs are passing.