Skip to content

Add sort_actor to cudf-polars + rapidsmpf#21690

Open
rjzamora wants to merge 41 commits intorapidsai:mainfrom
rjzamora:sort-actor
Open

Add sort_actor to cudf-polars + rapidsmpf#21690
rjzamora wants to merge 41 commits intorapidsai:mainfrom
rjzamora:sort-actor

Conversation

@rjzamora
Copy link
Member

@rjzamora rjzamora commented Mar 6, 2026

Description

Closes #20486
Depends on rapidsai/rapidsmpf#891 (or similar)

Adds sort_actor for the "rapidsmpf" runtime.

Checklist

  • I am familiar with the Contributing Guidelines.
  • New or existing tests cover these changes.
  • The documentation is up to date with these changes.

@rjzamora rjzamora self-assigned this Mar 6, 2026
@rjzamora rjzamora requested a review from a team as a code owner March 6, 2026 19:30
@rjzamora rjzamora added feature request New feature or request 2 - In Progress Currently a work in progress non-breaking Non-breaking change labels Mar 6, 2026
@rjzamora rjzamora requested review from bdice and mroeschke March 6, 2026 19:30
@github-actions github-actions bot added Python Affects Python cuDF API. cudf-polars Issues specific to cudf-polars labels Mar 6, 2026
@GPUtester GPUtester moved this to In Progress in cuDF Python Mar 6, 2026
)
if sort_ir.stable:
nrows = df.table.num_rows()
base = seq_num * (1 << 32)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is incorrect in a multi-rank setting. I think what you're trying to do is give each row in the (concatenated) stream of local table chunks a unique id.

seq_num * (1 << 32) is a good offset for this because by construction no sequence numbers from chunks on the same rank can now overlap.

But, it seems unnecessary (you have the number of rows when adding the column, so just keep track of that locally).

However, what this doesn't do is ensure that two different ranks have different sequence numbers. For that, you need to incorporate the rank in the high bits of the id, such that when you sort globally, rows from rank-1 (say) come after rows from rank-0 if their keys are equal.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Okay, thanks for explaining - I updated the logic here (hopefully in line with your suggestion).

Comment on lines +292 to +313
df = DataFrame.from_table(
out_table,
cast(Sequence[str], column_names_list),
dtypes_list,
stream,
)
sort_order = [
list(column_order)[by.index(n)]
if n in by
else plc.types.Order.ASCENDING
for n in column_names_list
]
nulls = [
list(null_order)[by.index(n)]
if n in by
else plc.types.NullOrder.AFTER
for n in column_names_list
]
sorted_tbl = plc.sorting.sort(
df.table, sort_order, nulls, stream=stream
)
out_table = plc.Table(sorted_tbl.columns()[:-1])
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This sort is wrong, because it sorts by all the columns in the table, whereas you only want to sort by the key columns (and the disambiguating seq_id column).

You want to be using sort_by_key

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Makes sense - I decided to construct a Sort so I can use do_evaluate, but I can move to an explicit sort_by_key if you'd prefer.

Comment on lines +75 to +76
by: list[str],
by_dtypes: list[DataType],
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

These arguments are only used to construct the schema of the "empty" table for the case that the local candidates are empty, which is then used to provide the schema for chunk_to_frame.

Two things:

  1. we only need the schema for all of those operations, so we should redo the utilities to take the schema.
  2. Let's construct the empty table outside if local_candidates is empty.

So this function becomes:

async def _compute_sort_boundaries(
    context: Context,
    comm: Communicator,
    ir_context: IRExecutionContext,
    local_candidates: list[TableChunk],
    schema: Schema,
    num_partitions: int,
    column_order: list[plc.types.Order],
    null_order: list[plc.types.NullOrder],
    allgather_id: int
) -> plc.Table:
    stream = ...
    boundaries = _get_final_sort_boundaries(
        chunk_to_frame(
            await concat_batch(local_candidates, context, schema, ir_context)
        )
    )
    if comm.nranks > 1:
         ...
    boundaries = _get_final_sort_boundaries(
         ...
    )
    return boundaries.table

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Okay, yeah - I revised this a bit.

@rjzamora rjzamora requested review from a team as code owners March 17, 2026 14:42
@copy-pr-bot
Copy link

copy-pr-bot bot commented Mar 17, 2026

This pull request requires additional validation before any workflows can run on NVIDIA's runners.

Pull request vetters can view their responsibilities here.

Contributors can view more details about this message here.

@github-actions github-actions bot added libcudf Affects libcudf (C++/CUDA) code. CMake CMake build issue Java Affects Java cuDF API. cudf.pandas Issues specific to cudf.pandas pylibcudf Issues specific to the pylibcudf package labels Mar 17, 2026
@rjzamora rjzamora changed the base branch from release/26.04 to main March 17, 2026 14:43
@rjzamora
Copy link
Member Author

Fiddle sticks. I accidentally merged in main - I guess this is slipping to 26.06 then :)

@rjzamora rjzamora removed request for a team and kingcrimsontianyu March 17, 2026 14:48
@rjzamora rjzamora removed libcudf Affects libcudf (C++/CUDA) code. Python Affects Python cuDF API. CMake CMake build issue Java Affects Java cuDF API. cudf.pandas Issues specific to cudf.pandas pylibcudf Issues specific to the pylibcudf package labels Mar 17, 2026
@github-actions github-actions bot added the Python Affects Python cuDF API. label Mar 17, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

3 - Ready for Review Ready for review by team cudf-polars Issues specific to cudf-polars feature request New feature or request non-breaking Non-breaking change Python Affects Python cuDF API.

Projects

Status: In Progress

Development

Successfully merging this pull request may close these issues.

[FEA]: Support multi-partition Sort in cudf-polars rapidsmpf runtime

3 participants