Add sort_actor to cudf-polars + rapidsmpf#21690
Add sort_actor to cudf-polars + rapidsmpf#21690rjzamora wants to merge 41 commits intorapidsai:mainfrom
sort_actor to cudf-polars + rapidsmpf#21690Conversation
python/cudf_polars/cudf_polars/experimental/rapidsmpf/collectives/common.py
Show resolved
Hide resolved
python/cudf_polars/cudf_polars/experimental/rapidsmpf/collectives/shuffle.py
Outdated
Show resolved
Hide resolved
| ) | ||
| if sort_ir.stable: | ||
| nrows = df.table.num_rows() | ||
| base = seq_num * (1 << 32) |
There was a problem hiding this comment.
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.
There was a problem hiding this comment.
Okay, thanks for explaining - I updated the logic here (hopefully in line with your suggestion).
python/cudf_polars/cudf_polars/experimental/rapidsmpf/collectives/sort.py
Outdated
Show resolved
Hide resolved
| 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]) |
There was a problem hiding this comment.
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
There was a problem hiding this comment.
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.
python/cudf_polars/cudf_polars/experimental/rapidsmpf/collectives/sort.py
Outdated
Show resolved
Hide resolved
python/cudf_polars/cudf_polars/experimental/rapidsmpf/collectives/sort.py
Outdated
Show resolved
Hide resolved
| by: list[str], | ||
| by_dtypes: list[DataType], |
There was a problem hiding this comment.
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:
- we only need the schema for all of those operations, so we should redo the utilities to take the schema.
- Let's construct the empty table outside if
local_candidatesis 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
There was a problem hiding this comment.
Okay, yeah - I revised this a bit.
python/cudf_polars/cudf_polars/experimental/rapidsmpf/collectives/sort.py
Outdated
Show resolved
Hide resolved
python/cudf_polars/cudf_polars/experimental/rapidsmpf/collectives/sort.py
Outdated
Show resolved
Hide resolved
|
Fiddle sticks. I accidentally merged in |
Description
Closes #20486
Depends on rapidsai/rapidsmpf#891 (or similar)
Adds
sort_actorfor the "rapidsmpf" runtime.Checklist