-
Notifications
You must be signed in to change notification settings - Fork 3.8k
GH-26818: [C++][Python] Preserve order when writing dataset multi-threaded #44470
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
|
9ca8c76
to
28cb588
Compare
This pull request seems to functionally overlap with this one. Some changes are almost exactly the same. Ordering of data is kept in threaded execution with use of batch index. Can you check whether it fixes your use case also? |
28cb588
to
0377ef9
Compare
cpp/src/arrow/acero/options.h
Outdated
@@ -103,8 +103,8 @@ class ARROW_ACERO_EXPORT SourceNodeOptions : public ExecNodeOptions { | |||
std::shared_ptr<Schema> output_schema; | |||
/// \brief an asynchronous stream of batches ending with std::nullopt | |||
std::function<Future<std::optional<ExecBatch>>()> generator; | |||
|
|||
Ordering ordering = Ordering::Unordered(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The constructor has a default value for ordering and initializes ordering
with the value given to the constructor. No point for another default value here, I think.
2776b34
to
6024066
Compare
acero::ConsumingSinkNodeOptions{ | ||
std::move(consumer), | ||
{}, | ||
/*sequence_output=*/write_options.preserve_order})); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
TeeNode needs the same treatment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Right, looks like this requires some refactoring, since TeeNode
is not used for writing datasets I'd leave this to a separate PR.
Since you are fixing dataset write ordering I think this check never fires. It should be moved to InsertBatch. |
6024066
to
697c378
Compare
@gitmodimo I think that refactoring should be done in a separate PR keeping this PR focused on fixing the issue. |
697c378
to
a9a78ce
Compare
a9a78ce
to
f56b166
Compare
f56b166
to
b750bb3
Compare
@zanmato1984 this touches related code area as #44616. Hoping you could take a look when you find time. |
Hi @EnricoMi , I can take a look. Just first glance but do you think the PR description could be updated accordingly? |
|
Also, you might want to update the PR description to reflect its latest purpose. |
I think the PR description is up-to-date, do you see any discrepancy? |
@@ -4591,6 +4591,22 @@ def file_visitor(written_file): | |||
assert result1.to_table().equals(result2.to_table()) | |||
|
|||
|
|||
@pytest.mark.parquet | |||
@pytest.mark.pandas | |||
def test_write_dataset_use_threads_preserve_order(tempdir): |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Added test code from issue description. The test fails with preserve_order=False
.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM
Let's wait for @rok a while before I can merge this. Thanks. |
@github-actions crossbow submit -g cpp -g python |
Revision: dfd958d Submitted crossbow builds: ursacomputing/crossbow @ actions-58bcfa66f9 |
Thanks for doing this @EnricoMi ! This was a long standing issue. |
Thanks everyone for the thorough review! |
After merging your PR, Conbench analyzed the 3 benchmarking runs that have been run so far on merge-commit 021d8ab. There were no benchmark performance regressions. 🎉 The full Conbench report has more details. It also includes information about 6 possible false positives for unstable benchmarks that are known to sometimes produce them. |
Perhaps it'd be worth it to add a benchmark for |
I'll look into this! |
…ti-threaded (apache#44470) ### Rationale for this change The order of rows in a dataset might be important for users and should be preserved when writing to a filesystem. With multi-threaded write, the order is currently not guaranteed, ### What changes are included in this PR? Preserving the dataset order of rows requires the `SourceNode` to sequence the fragments output (this keeps exec batches in the order of fragments), to provide an `ImplicitOrdering` (this gives exec batches an index), and the `ConsumingSinkNode` to sequence exec batches (finally preserve order of batches according to their index). User-facing changes: - Add option `preserve_order` to `FileSystemDatasetWriteOptions` (C++) and `arrow.dataset.write_dataset` (Python). Default behaviour is current behaviour. ### Are these changes tested? Unit tests have been added, ### Are there any user-facing changes? Users can set `FileSystemDatasetWriteOptions.preserve_order = true` (C++) / `arrow.dataset.write_dataset(..., preserve_order=True)` (Python). * GitHub Issue: apache#26818 Lead-authored-by: Enrico Minack <[email protected]> Co-authored-by: Rok Mihevc <[email protected]> Signed-off-by: Rok Mihevc <[email protected]>
…ti-threaded (apache#44470) (#5) ### Rationale for this change The order of rows in a dataset might be important for users and should be preserved when writing to a filesystem. With multi-threaded write, the order is currently not guaranteed, ### What changes are included in this PR? Preserving the dataset order of rows requires the `SourceNode` to sequence the fragments output (this keeps exec batches in the order of fragments), to provide an `ImplicitOrdering` (this gives exec batches an index), and the `ConsumingSinkNode` to sequence exec batches (finally preserve order of batches according to their index). User-facing changes: - Add option `preserve_order` to `FileSystemDatasetWriteOptions` (C++) and `arrow.dataset.write_dataset` (Python). Default behaviour is current behaviour. ### Are these changes tested? Unit tests have been added, ### Are there any user-facing changes? Users can set `FileSystemDatasetWriteOptions.preserve_order = true` (C++) / `arrow.dataset.write_dataset(..., preserve_order=True)` (Python). * GitHub Issue: apache#26818 Lead-authored-by: Enrico Minack <[email protected]> Signed-off-by: Rok Mihevc <[email protected]> Co-authored-by: Rok Mihevc <[email protected]>
Rationale for this change
The order of rows in a dataset might be important for users and should be preserved when writing to a filesystem. With multi-threaded write, the order is currently not guaranteed,
What changes are included in this PR?
Preserving the dataset order of rows requires the
SourceNode
to sequence the fragments output (this keeps exec batches in the order of fragments), to provide anImplicitOrdering
(this gives exec batches an index), and theConsumingSinkNode
to sequence exec batches (finally preserve order of batches according to their index).User-facing changes:
preserve_order
toFileSystemDatasetWriteOptions
(C++) andarrow.dataset.write_dataset
(Python).Default behaviour is current behaviour.
Are these changes tested?
Unit tests have been added,
Are there any user-facing changes?
Users can set
FileSystemDatasetWriteOptions.preserve_order = true
(C++) /arrow.dataset.write_dataset(..., preserve_order=True)
(Python).