1- # SPDX-FileCopyrightText: Copyright (c) 2026, NVIDIA CORPORATION & AFFILIATES.
1+ # SPDX-FileCopyrightText: Copyright (c) 2026, NVIDIA CORPORATION & AFFILIATES. All rights reserved.
22# SPDX-License-Identifier: Apache-2.0
33"""OrderScheme adjustment utilities for the RapidsMPF streaming runtime."""
44
1010import polars as pl
1111
1212import pylibcudf as plc
13+ from cudf_streaming .partition_utils import unpack_and_concat
14+ from cudf_streaming .table_chunk import TableChunk
1315from pylibcudf .contiguous_split import pack
14- from rapidsmpf .integrations .cudf .partition import unpack_and_concat
1516from rapidsmpf .memory .packed_data import PackedData
1617from rapidsmpf .streaming .coll .sparse_alltoall import SparseAlltoall
1718from rapidsmpf .streaming .core .message import Message
18- from rapidsmpf .streaming .cudf .table_chunk import TableChunk
1919
2020from cudf_polars .containers import DataFrame , DataType
2121from cudf_polars .streaming .actor_graph .utils import (
2727from cudf_polars .utils .cuda_stream import stream_ordered_after
2828
2929if TYPE_CHECKING :
30+ from cudf_streaming .channel_metadata import OrderScheme , Ordering
3031 from rapidsmpf .communicator .communicator import Communicator
3132 from rapidsmpf .memory .buffer_resource import BufferResource
3233 from rapidsmpf .streaming .core .channel import Channel
3334 from rapidsmpf .streaming .core .context import Context
34- from rapidsmpf .streaming .cudf .channel_metadata import OrderScheme
3535 from rmm .pylibrmm .stream import Stream
3636
3737 from cudf_polars .dsl .ir import IR , IRExecutionContext
4141_PID_PLC_DTYPE = plc .DataType (plc .TypeId .INT32 )
4242
4343
44+ def _primary_ordering (scheme : OrderScheme ) -> Ordering :
45+ """Return the single ordering supported by adjust_orderscheme for now."""
46+ (ordering ,) = scheme .orderings
47+ return ordering
48+
49+
4450def _contiguous_owner (pid : int , nranks : int , npartitions : int ) -> int :
4551 """Return the rank owning *pid* under contiguous partition assignment."""
4652 return pid * nranks // npartitions
@@ -81,10 +87,12 @@ def _contiguous_owners(
8187
8288def _validate_schemes (input_scheme : OrderScheme , output_scheme : OrderScheme ) -> None :
8389 """Validate the first-pass flat OrderScheme adjustment contract."""
84- if not output_scheme .strict_boundaries :
90+ input_ordering = _primary_ordering (input_scheme )
91+ output_ordering = _primary_ordering (output_scheme )
92+ if not output_ordering .strict_boundaries :
8593 raise ValueError ("adjust_orderscheme requires a strict output OrderScheme." )
86- prefix_len = len (output_scheme .keys )
87- if input_scheme .keys [:prefix_len ] != output_scheme .keys :
94+ prefix_len = len (output_ordering .keys )
95+ if input_ordering .keys [:prefix_len ] != output_ordering .keys :
8896 raise NotImplementedError (
8997 "adjust_orderscheme currently requires the output OrderScheme keys "
9098 "to be a prefix of the input OrderScheme keys."
@@ -94,18 +102,18 @@ def _validate_schemes(input_scheme: OrderScheme, output_scheme: OrderScheme) ->
94102def _split_points (
95103 table : plc .Table ,
96104 boundary_table : plc .Table ,
97- scheme : OrderScheme ,
105+ ordering : Ordering ,
98106 stream : Stream ,
99107) -> list [int ]:
100108 """Return row split points that partition *table* by *scheme* boundaries."""
101109 if boundary_table .num_rows () == 0 :
102110 return []
103- key_table = plc .Table ([table .columns ()[key .column_index ] for key in scheme .keys ])
111+ key_table = plc .Table ([table .columns ()[key .column_index ] for key in ordering .keys ])
104112 split_col = plc .search .lower_bound (
105113 key_table ,
106114 boundary_table ,
107- [key .order for key in scheme .keys ],
108- [key .null_order for key in scheme .keys ],
115+ [key .order for key in ordering .keys ],
116+ [key .null_order for key in ordering .keys ],
109117 stream = stream ,
110118 )
111119 return (
@@ -133,16 +141,16 @@ def _append_partition_id(table: plc.Table, pid: int, stream: Stream) -> plc.Tabl
133141def _boundary_search_positions (
134142 input_boundary_table : plc .Table ,
135143 output_boundary_table : plc .Table ,
136- output_scheme : OrderScheme ,
144+ output_ordering : Ordering ,
137145 stream : Stream ,
138146) -> tuple [list [int ], list [int ]]:
139147 """Search output boundary positions for projected input boundary rows."""
140148 if input_boundary_table .num_rows () == 0 :
141149 return [], []
142- prefix_len = len (output_scheme .keys )
150+ prefix_len = len (output_ordering .keys )
143151 input_prefix_boundaries = plc .Table (input_boundary_table .columns ()[:prefix_len ])
144- orders = [key .order for key in output_scheme .keys ]
145- null_orders = [key .null_order for key in output_scheme .keys ]
152+ orders = [key .order for key in output_ordering .keys ]
153+ null_orders = [key .null_order for key in output_ordering .keys ]
146154 lower_col = plc .search .lower_bound (
147155 output_boundary_table ,
148156 input_prefix_boundaries ,
@@ -169,16 +177,16 @@ def _boundary_search_positions(
169177def _peer_ranks (
170178 rank : int ,
171179 nranks : int ,
172- input_scheme : OrderScheme ,
173- output_scheme : OrderScheme ,
180+ input_ordering : Ordering ,
181+ output_ordering : Ordering ,
174182 lower_positions : list [int ],
175183 upper_positions : list [int ],
176184) -> tuple [list [int ], list [int ]]:
177185 """Return source and destination ranks needed for OrderScheme adjustment."""
178- input_npartitions = input_scheme .num_boundaries + 1
179- output_npartitions = output_scheme .num_boundaries + 1
180- output_prefix_only = len (output_scheme .keys ) < len (input_scheme .keys )
181- include_upper_boundary = output_prefix_only or not input_scheme .strict_boundaries
186+ input_npartitions = input_ordering .num_boundaries + 1
187+ output_npartitions = output_ordering .num_boundaries + 1
188+ output_prefix_only = len (output_ordering .keys ) < len (input_ordering .keys )
189+ include_upper_boundary = output_prefix_only or not input_ordering .strict_boundaries
182190
183191 def dsts_for_source (source_rank : int ) -> list [int ]:
184192 input_start , input_stop = _partition_range (
@@ -265,10 +273,10 @@ async def _adjust_orderscheme_local(
265273 ir_context : IRExecutionContext ,
266274 ch_out : Channel [TableChunk ],
267275 ch_in : Channel [TableChunk ],
268- output_scheme : OrderScheme ,
276+ output_ordering : Ordering ,
269277) -> None :
270- npartitions = output_scheme .num_boundaries + 1
271- boundary_chunk = output_scheme .get_boundaries (context .br ())
278+ npartitions = output_ordering .num_boundaries + 1
279+ boundary_chunk = output_ordering .get_boundaries (context .br ())
272280 boundary_table = boundary_chunk .table_view ()
273281 pending_pid : int | None = None
274282 pending_chunks : ChunkStore | None = None
@@ -294,11 +302,11 @@ async def emit_pending(pid: int) -> None:
294302 if chunk .table_view ().num_rows () == 0 :
295303 continue
296304 with stream_ordered_after (
297- context .get_stream_from_pool ,
305+ context .br (). stream_pool . get_stream ,
298306 upstreams = (chunk .stream , boundary_chunk .stream ),
299307 ) as stream :
300308 table = chunk .table_view ()
301- splits = _split_points (table , boundary_table , output_scheme , stream )
309+ splits = _split_points (table , boundary_table , output_ordering , stream )
302310 for pid , piece in enumerate (
303311 plc .copying .split (table , splits , stream = stream )
304312 ):
@@ -372,7 +380,9 @@ async def adjust_orderscheme(
372380 sortedness is not checked here.
373381 """
374382 _validate_schemes (input_scheme , output_scheme )
375- npartitions = output_scheme .num_boundaries + 1
383+ input_ordering = _primary_ordering (input_scheme )
384+ output_ordering = _primary_ordering (output_scheme )
385+ npartitions = output_ordering .num_boundaries + 1
376386 local_pids = _local_partitions (comm .rank , comm .nranks , npartitions )
377387
378388 if comm .nranks > 1 and collective_id is None :
@@ -386,31 +396,31 @@ async def adjust_orderscheme(
386396 ir_context ,
387397 ch_out ,
388398 ch_in ,
389- output_scheme ,
399+ output_ordering ,
390400 )
391401 return
392402
393- input_boundary_chunk = input_scheme .get_boundaries (context .br ())
394- boundary_chunk = output_scheme .get_boundaries (context .br ())
403+ input_boundary_chunk = input_ordering .get_boundaries (context .br ())
404+ boundary_chunk = output_ordering .get_boundaries (context .br ())
395405 boundary_table = boundary_chunk .table_view ()
396406 srcs : list [int ] = []
397407 dsts : list [int ] = []
398408 if comm .nranks > 1 :
399409 with stream_ordered_after (
400- context .get_stream_from_pool ,
410+ context .br (). stream_pool . get_stream ,
401411 upstreams = (input_boundary_chunk .stream , boundary_chunk .stream ),
402412 ) as stream :
403413 lower_positions , upper_positions = _boundary_search_positions (
404414 input_boundary_chunk .table_view (),
405415 boundary_table ,
406- output_scheme ,
416+ output_ordering ,
407417 stream ,
408418 )
409419 srcs , dsts = _peer_ranks (
410420 comm .rank ,
411421 comm .nranks ,
412- input_scheme ,
413- output_scheme ,
422+ input_ordering ,
423+ output_ordering ,
414424 lower_positions ,
415425 upper_positions ,
416426 )
@@ -429,11 +439,13 @@ async def adjust_orderscheme(
429439 if chunk .table_view ().num_rows () == 0 :
430440 continue
431441 with stream_ordered_after (
432- context .get_stream_from_pool ,
442+ context .br (). stream_pool . get_stream ,
433443 upstreams = (chunk .stream , boundary_chunk .stream ),
434444 ) as stream :
435445 table = chunk .table_view ()
436- splits = _split_points (table , boundary_table , output_scheme , stream )
446+ splits = _split_points (
447+ table , boundary_table , output_ordering , stream
448+ )
437449 for pid , piece in enumerate (
438450 plc .copying .split (table , splits , stream = stream )
439451 ):
@@ -473,7 +485,7 @@ async def adjust_orderscheme(
473485 output_chunks [pid ].extend (chunks )
474486 else :
475487 assert exchange is not None
476- stream = context .get_stream_from_pool ()
488+ stream = context .br (). stream_pool . get_stream ()
477489 for packed in exchange .extract (source_rank ):
478490 remote_piece = _unpack_remote_piece (packed , stream , context .br ())
479491 if remote_piece is None :
0 commit comments