Repository navigation
GPU duplicate sort keys with opposite directions fail after a projection #30322
Copy link
Copy link
Open
Labels
A-gpuArea: gpu engineArea: gpu enginebugSomething isn't workingSomething isn't workingneeds triageAwaiting prioritization by a maintainerAwaiting prioritization by a maintainerpythonRelated to Python PolarsRelated to Python Polars
Description
Checks
- I have checked that this issue has not already been reported.
- I have confirmed this bug exists on the latest version of Polars.
Reproducible example
import polars as pl
t0 = pl.LazyFrame({"c0": [1.0]})
result = t0.sort(["c0", "c0"], descending=[False, True]).select(pl.col("c0").alias("c1"))
print("CPU Result:")
print(result.collect())
print("GPU Result:")
print(result.collect(engine=pl.GPUEngine(raise_on_fail=True)))Log output
CPU Result:
shape: (1, 1)
┌─────┐
│ c1 │
│ --- │
│ f64 │
╞═════╡
│ 1.0 │
└─────┘
GPU Result:
+ Exception Group Traceback (most recent call last):
| File "/test.py", line 11, in <module>
| print(result.collect(engine=pl.GPUEngine(raise_on_fail=True)))
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
| File "/opt/conda/envs/polars-gpu/lib/python3.11/site-packages/polars/_utils/deprecation.py", line 97, in wrapper
| return function(*args, **kwargs)
| ^^^^^^^^^^^^^^^^^^^^^^^^^
| File "/opt/conda/envs/polars-gpu/lib/python3.11/site-packages/polars/lazyframe/opt_flags.py", line 361, in wrapper
| return function(*args, **kwargs)
| ^^^^^^^^^^^^^^^^^^^^^^^^^
| File "/opt/conda/envs/polars-gpu/lib/python3.11/site-packages/polars/lazyframe/frame.py", line 2591, in collect
| return engine_.collect(
| ^^^^^^^^^^^^^^^^
| File "/opt/conda/envs/polars-gpu/lib/python3.11/site-packages/polars/lazyframe/engine.py", line 443, in collect
| return wrap_df(ldf.collect(self.name, callback))
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
| File "/opt/conda/envs/polars-gpu/lib/python3.11/site-packages/cudf_polars/callback.py", line 321, in _callback
| return evaluate_streaming(ir, config_options)
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
| File "/opt/conda/envs/polars-gpu/lib/python3.11/site-packages/cudf_polars/streaming/parallel.py", line 263, in evaluate_streaming
| result, _ = evaluate_logical_plan(ir, config_options, collect_metadata=False)
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
| File "/opt/conda/envs/polars-gpu/lib/python3.11/site-packages/cudf_polars/streaming/actor_graph/core.py", line 110, in evaluate_logical_plan
| _gpu_result, metadata_collector = evaluate_pipeline_spmd_mode(
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
| File "/opt/conda/envs/polars-gpu/lib/python3.11/site-packages/cudf_polars/engine/spmd.py", line 153, in evaluate_pipeline_spmd_mode
| df, metadata = evaluate_on_rank(
| ^^^^^^^^^^^^^^^^^
| File "/opt/conda/envs/polars-gpu/lib/python3.11/site-packages/cudf_polars/engine/core.py", line 961, in evaluate_on_rank
| return execute_ir_on_rank(
| ^^^^^^^^^^^^^^^^^^^
| File "/opt/conda/envs/polars-gpu/lib/python3.11/site-packages/cudf_polars/engine/core.py", line 672, in execute_ir_on_rank
| run_actor_network(ctx, actors=nodes)
| File "rapidsmpf/streaming/core/actor.pyx", line 360, in rapidsmpf.streaming.core.actor.run_actor_network
| File "rapidsmpf/streaming/core/actor.pyx", line 368, in rapidsmpf.streaming.core.actor.run_actor_network
| File "rapidsmpf/streaming/core/actor.pyx", line 365, in rapidsmpf.streaming.core.actor.run_actor_network
| File "/opt/conda/envs/polars-gpu/lib/python3.11/concurrent/futures/_base.py", line 456, in result
| return self.__get_result()
| ^^^^^^^^^^^^^^^^^^^
| File "/opt/conda/envs/polars-gpu/lib/python3.11/concurrent/futures/_base.py", line 401, in __get_result
| raise self._exception
| File "/opt/conda/envs/polars-gpu/lib/python3.11/concurrent/futures/thread.py", line 58, in run
| result = self.fn(*self.args, **self.kwargs)
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
| File "rapidsmpf/streaming/core/actor.pyx", line 267, in rapidsmpf.streaming.core.actor.sync_wait
| File "rapidsmpf/streaming/core/actor.pyx", line 262, in rapidsmpf.streaming.core.actor.sync_wait
| File "rapidsmpf/streaming/core/actor.pyx", line 263, in rapidsmpf.streaming.core.actor.sync_wait
| File "/opt/conda/envs/polars-gpu/lib/python3.11/asyncio/runners.py", line 118, in run
| return self._loop.run_until_complete(task)
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
| File "/opt/conda/envs/polars-gpu/lib/python3.11/asyncio/base_events.py", line 654, in run_until_complete
| return future.result()
| ^^^^^^^^^^^^^^^
| File "rapidsmpf/streaming/core/actor.pyx", line 245, in run_and_publish_task
| File "rapidsmpf/streaming/core/actor.pyx", line 172, in run_py_actors
| File "/opt/conda/envs/polars-gpu/lib/python3.11/asyncio/taskgroups.py", line 145, in __aexit__
| raise me from None
| ExceptionGroup: unhandled errors in a TaskGroup (2 sub-exceptions)
+-+---------------- 1 ----------------
| Exception Group Traceback (most recent call last):
| File "rapidsmpf/streaming/core/actor.pyx", line 158, in py_actor
| File "/opt/conda/envs/polars-gpu/lib/python3.11/site-packages/cudf_polars/streaming/actor_graph/collectives/sort.py", line 869, in sort_actor
| _, local_candidates_list = await gather_in_task_group(
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^
| File "/opt/conda/envs/polars-gpu/lib/python3.11/site-packages/cudf_polars/streaming/actor_graph/utils.py", line 240, in gather_in_task_group
| async with asyncio.TaskGroup() as tg:
| File "/opt/conda/envs/polars-gpu/lib/python3.11/asyncio/taskgroups.py", line 145, in __aexit__
| raise me from None
| ExceptionGroup: unhandled errors in a TaskGroup (1 sub-exception)
+-+---------------- 1 ----------------
| Traceback (most recent call last):
| File "/opt/conda/envs/polars-gpu/lib/python3.11/site-packages/cudf_polars/streaming/actor_graph/collectives/sort.py", line 508, in _receive_and_buffer_chunks
| _select_local_split_candidates(
| File "/opt/conda/envs/polars-gpu/lib/python3.11/site-packages/cudf_polars/streaming/sort.py", line 161, in _select_local_split_candidates
| return DataFrame.from_table(
| ^^^^^^^^^^^^^^^^^^^^^
| File "/opt/conda/envs/polars-gpu/lib/python3.11/site-packages/cudf_polars/containers/dataframe.py", line 247, in from_table
| raise ValueError("Mismatching name and table length.")
| ValueError: Mismatching name and table length.
+------------------------------------
+---------------- 2 ----------------
| Traceback (most recent call last):
| File "rapidsmpf/streaming/core/actor.pyx", line 158, in py_actor
| File "/opt/conda/envs/polars-gpu/lib/python3.11/site-packages/cudf_polars/streaming/actor_graph/nodes.py", line 96, in default_node_single
| metadata_in = await recv_metadata(ch_in, context)
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
| File "/opt/conda/envs/polars-gpu/lib/python3.11/site-packages/cudf_polars/streaming/actor_graph/utils.py", line 717, in recv_metadata
| assert msg is not None, f"Expected ChannelMetadata message, got {msg}."
| ^^^^^^^^^^^^^^^
| AssertionError: Expected ChannelMetadata message, got None.
+------------------------------------Issue description
A one-row Float64 LazyFrame is sorted by ["c0", "c0"] with descending flags [False, True], then projected to a renamed column c1. CPU collection returns the original value 1.0. GPU collection raises an ExceptionGroup. The supplied traceback includes ValueError: Mismatching name and table length. in the cuDF streaming sort actor and AssertionError: Expected ChannelMetadata message, got None.. Both exceptions occur in the recorded GPU execution.
Expected behavior
GPU collection should complete the sort and projection without internal actor errors, returning one Float64 column c1 containing 1.0, matching CPU collection.
Installed versions
Details
--------Version info---------
Polars: 1.44.2
Index type: UInt32
Platform: Linux-6.17.0-29-generic-x86_64-with-glibc2.39
Python: 3.11.17 (main, Oct 7 2026, 00:02:24) [GCC 15.3.0]
Runtime: rt32
----Optional dependencies----
Azure CLI <not installed>
adbc_driver_manager <not installed>
altair <not installed>
azure.identity <not installed>
boto3 <not installed>
cloudpickle <not installed>
connectorx <not installed>
deltalake <not installed>
fastexcel <not installed>
fsspec <not installed>
gevent <not installed>
google.auth <not installed>
great_tables <not installed>
matplotlib <not installed>
numpy 2.4.6
openpyxl <not installed>
pandas 3.0.6
polars_cloud <not installed>
pyarrow <not installed>
pydantic <not installed>
pyiceberg <not installed>
sqlalchemy <not installed>
torch <not installed>
xlsx2csv <not installed>
xlsxwriter <not installed>
cuda-bindings 12.9.9
cuda-core 1.2.1
cuda-pathfinder 1.8.3
cuda-toolkit 12.9.2.0
cudf-polars-cu12 26.10.0
cudf-streaming-cu12 26.10.0
cupy-cuda12x 14.2.0
kvikio-cu12 26.10.0
libcudf-cu12 26.10.0
libcudf-streaming-cu12 26.10.0
libkvikio-cu12 26.10.0
librapidsmpf-cu12 26.10.0
librmm-cu12 26.10.0
libucx-cu12 1.21.0
libucxx-cu12 0.52.0
nvidia-cublas-cu12 12.9.2.10
nvidia-cuda-nvrtc-cu12 12.9.86
nvidia-cuda-runtime-cu12 12.9.79
nvidia-cufft-cu12 11.4.1.4
nvidia-cufile-cu12 1.14.1.1
nvidia-curand-cu12 10.3.10.19
nvidia-cusolver-cu12 11.7.5.82
nvidia-cusparse-cu12 12.5.10.65
nvidia-libnvcomp-cu12 5.3.0.16
nvidia-ml-py 13.615.71
nvidia-nvjitlink-cu12 12.9.86
nvtx 0.2.16
polars 1.44.2
polars-runtime-32 1.44.2
pylibcudf-cu12 26.10.0
rapids-logger 0.3.0
rapidsmpf-cu12 26.10.0
rmm-cu12 26.10.0
Reactions are currently unavailable
Metadata
Metadata
Assignees
Labels
A-gpuArea: gpu engineArea: gpu enginebugSomething isn't workingSomething isn't workingneeds triageAwaiting prioritization by a maintainerAwaiting prioritization by a maintainerpythonRelated to Python PolarsRelated to Python Polars
Activity