Skip to content
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

GH-39798: [C++] Optimize Take for fixed-size types including nested fixed-size lists #41297

Merged
merged 12 commits into from
May 3, 2024

Conversation

felipecrv
Copy link
Contributor

@felipecrv felipecrv commented Apr 18, 2024

Rationale for this change

Introduce utilities for dealing with fixed-width types (including fixed-size lists of fixed-width types) generically. And use it for initial optimizations of Take and Filter.

What changes are included in this PR?

  • Introduce utilities for dealing with fixed-width types generically
  • Use faster Take kernel on small power-of-2 byte widths of fixed-width types
    • from FSLTakeExec (including FSLs of FSBs)
    • from FSBTakeExec (done before this PR)
  • Take on any fixed-width type (as a separate issue [C++] Extract the kernel loops used for PrimitiveTakeExec and generalize to any fixed-width type #41301)
  • Use faster Filter kernel on both primitive and fixed-width types of any length
    • from FSLFilterExec (including FSLs of FSBs)
    • from FSBFilterExec (done before this PR)

Are these changes tested?

By existing and new tests.

Are there any user-facing changes?

Some functions added to the arrow::util namespace and documented inline.

cpp/src/arrow/util/fixed_width_internal.h Outdated Show resolved Hide resolved
cpp/src/arrow/util/fixed_width_internal.h Outdated Show resolved Hide resolved
@github-actions github-actions bot added awaiting changes Awaiting changes and removed awaiting committer review Awaiting committer review labels Apr 25, 2024
@felipecrv felipecrv requested a review from pitrou May 2, 2024 14:57
Copy link
Member

@bkietz bkietz left a comment

Choose a reason for hiding this comment

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

Thank you for working on this! My greatest concern is the number of header utilities introduced for handling fixed-width-like. It seems unnecessary to ensure that so many of these are inlined when they don't appear inside a hot loop.

cpp/src/arrow/util/fixed_width_internal.h Show resolved Hide resolved
cpp/src/arrow/util/fixed_width_internal.h Outdated Show resolved Hide resolved
cpp/src/arrow/util/fixed_width_test_util.h Show resolved Hide resolved
cpp/src/arrow/util/fixed_width_test.cc Show resolved Hide resolved
@felipecrv
Copy link
Contributor Author

This push was just a rebase. Fixes coming next.

@github-actions github-actions bot added awaiting change review Awaiting change review and removed awaiting changes Awaiting changes labels May 2, 2024
@github-actions github-actions bot removed the awaiting change review Awaiting change review label May 2, 2024
@github-actions github-actions bot added awaiting merge Awaiting merge awaiting changes Awaiting changes and removed awaiting merge Awaiting merge labels May 2, 2024
@github-actions github-actions bot added awaiting change review Awaiting change review and removed awaiting changes Awaiting changes labels May 2, 2024
@felipecrv
Copy link
Contributor Author

@bkietz linker errors fixed.

@felipecrv
Copy link
Contributor Author

CI failures are unrelated. I'm going to merge now, but more feedback can be posted here or on the follow-up PRs that use and extend this work.

@felipecrv felipecrv merged commit 9749d7d into apache:main May 3, 2024
34 of 36 checks passed
@felipecrv felipecrv removed the awaiting change review Awaiting change review label May 3, 2024
Copy link

After merging your PR, Conbench analyzed the 7 benchmarking runs that have been run so far on merge-commit 9749d7d.

There was 1 benchmark result indicating a performance regression:

The full Conbench report has more details. It also includes information about 41 possible false positives for unstable benchmarks that are known to sometimes produce them.

@felipecrv felipecrv deleted the fixed_modulo_nesting branch May 3, 2024 15:18
@felipecrv
Copy link
Contributor Author

@ursabot please benchmark lang=R

@ursabot
Copy link

ursabot commented May 3, 2024

Benchmark runs are scheduled for commit 0034a04. Watch https://buildkite.com/apache-arrow and https://conbench.ursa.dev for updates. A comment will be posted here when the runs are complete.

Copy link

Thanks for your patience. Conbench analyzed the 6 benchmarking runs that have been run so far on PR commit 0034a04.

There were no benchmark performance regressions. 🎉

The full Conbench report has more details.

@apache apache deleted a comment from ursabot May 3, 2024
Copy link
Member

@pitrou pitrou left a comment

Choose a reason for hiding this comment

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

Sorry for the belated review here.

cpp/src/arrow/util/fixed_width_internal.h Show resolved Hide resolved
/// \brief Checks if the given array has a fixed-width type or if it's an array of
/// fixed-size list that can be flattened to an array of fixed-width values.
///
/// Fixed-width types are the ones defined by the is_fixed_width() predicate in
Copy link
Member

Choose a reason for hiding this comment

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

In general, it's nice for docstrings to be precise and explanatory, but a 150-lines long docstring ensures that most readers won't read it in entirety. Can you try to distill it down a bit?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Isn't that what \brief is for? It's rather long because of the examples.

Without them, it's really hard to understand the intricacies of this concept.

Copy link
Member

Choose a reason for hiding this comment

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

\brief is for a one-liner introductory sentence, but if every non-trivial API function gets a 150-line docstring, then nobody will read them anymore (and, besides, even the source code will become impossible to navigate).

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I will remove the comments from the /// and spread the explanation, but I think this concept is complicated enough that having a long comment in the source code is worth it.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Changed this in #41597.

cpp/src/arrow/util/fixed_width_internal.h Show resolved Hide resolved
cpp/src/arrow/util/fixed_width_internal.h Show resolved Hide resolved
inline bool IsFixedWidthLike(const ArraySpan& source, bool force_null_count,
ExtraPred extra_predicate) {
const auto* type = source.type;
// BOOL is considered fixed-width if not nested under FIXED_SIZE_LIST.
Copy link
Member

Choose a reason for hiding this comment

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

This is a rather weird API design choice. Won't it confuse callers?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I started without BOOL then almost every IsFixedWidthLike check in the Take kernel had to have || type->id() == BOOL.

Additionally, excluding BOOL would put this function in conflict with is_fixed_width(). I wanted to preserve the property that the set of arrays that passes this predicate is a superset of the arrays that can pass is_fixed_width(type->id()). How could an array be [Is]FixedWidthLike if it's not even [is_]fixed_width()?

Copy link
Member

Choose a reason for hiding this comment

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

My "weird API design choice" comment was about the "if not nested under FSL" part :-)

Copy link
Contributor Author

Choose a reason for hiding this comment

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

API change in #41597.

cpp/src/arrow/util/fixed_width_internal.h Show resolved Hide resolved
/// is_fixed_width(*mutable_array->type) SHOULD be true
/// \return The pointer to the fixed-width values of an array or NULLPTR
/// if pre-conditions are not satisfied.
ARROW_EXPORT const uint8_t* OffsetPointerOfFixedWidthValues(const ArraySpan& source);
Copy link
Member

Choose a reason for hiding this comment

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

Most if not all API functions operating on arrays take the offset into account, so adding "Offset" to the function name does not bring any additional information. FixedWidthValuesPointer would be shorter and more consistent with MutableFixedWidthValuesPointer below.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

The inconsistency with MutableFixedWidthValuesPointer was on purpose because that one requires the input to have offset==0.

Most if not all API functions operating on arrays take the offset into account...

And the pointers they return can easily have the offset applied to them after the fact. I gave the Offset- prefix to this one so it works as a reminder to the caller that ptr + arr.offset won't work (it might by accident), but it's not correct for the general case. The actual offset is a complicated sum of offset products.

cpp/src/arrow/util/fixed_width_internal.h Show resolved Hide resolved
cpp/src/arrow/util/fixed_width_test_util.h Show resolved Hide resolved
cpp/src/arrow/util/fixed_width_test_util.h Show resolved Hide resolved
@github-actions github-actions bot added awaiting committer review Awaiting committer review awaiting changes Awaiting changes and removed awaiting committer review Awaiting committer review labels May 6, 2024
@felipecrv
Copy link
Contributor Author

@pitrou replied to your comments, please resolve the ones that you think are acceptable and discuss further the ones you still think need to be addressed.

Many questions revolve around the handling of BOOL and offsets. Do you think I should extend this to support BOOL as well? With all the extra complexity that would bring?

felipecrv added a commit that referenced this pull request May 14, 2024
…t bit-sized types (BOOL) (#41597)

### Rationale for this change

Post-merge feedback from #41297.

### What changes are included in this PR?

 - Supporting `BOOL` as both a top-level and nested in FSL types
 - Removing the long example from the docstring of `IsFixedWidthLike`

These changes don't affect users because this header was added recently and not released.

### Are these changes tested?

Yes, by existing and new test cases.
* GitHub Issue: #41596

Authored-by: Felipe Oliveira Carvalho <[email protected]>
Signed-off-by: Felipe Oliveira Carvalho <[email protected]>
vibhatha pushed a commit to vibhatha/arrow that referenced this pull request May 25, 2024
…sted fixed-size lists (apache#41297)

### Rationale for this change

Introduce utilities for dealing with fixed-width types (including fixed-size lists of fixed-width types) generically. And use it for initial optimizations of `Take` and `Filter`.

### What changes are included in this PR?

- [x] Introduce utilities for dealing with fixed-width types generically
- [x] Use faster `Take` kernel on small power-of-2 byte widths of fixed-width types
  - [x] from `FSLTakeExec` (including FSLs of FSBs)
  - [x] from `FSBTakeExec` (done before this PR)
- [x] ~Take on any fixed-width type~ (as a separate issue apache#41301)
- [x] Use faster `Filter` kernel on both primitive and fixed-width types of any length
   - [x] from `FSLFilterExec` (including FSLs of FSBs)
   - [x] from `FSBFilterExec` (done before this PR)

### Are these changes tested?

By existing and new tests.

### Are there any user-facing changes?

Some functions added to the `arrow::util` namespace and documented inline.
* GitHub Issue: apache#39798

Authored-by: Felipe Oliveira Carvalho <[email protected]>
Signed-off-by: Felipe Oliveira Carvalho <[email protected]>
vibhatha pushed a commit to vibhatha/arrow that referenced this pull request May 25, 2024
…support bit-sized types (BOOL) (apache#41597)

### Rationale for this change

Post-merge feedback from apache#41297.

### What changes are included in this PR?

 - Supporting `BOOL` as both a top-level and nested in FSL types
 - Removing the long example from the docstring of `IsFixedWidthLike`

These changes don't affect users because this header was added recently and not released.

### Are these changes tested?

Yes, by existing and new test cases.
* GitHub Issue: apache#41596

Authored-by: Felipe Oliveira Carvalho <[email protected]>
Signed-off-by: Felipe Oliveira Carvalho <[email protected]>
JerAguilon pushed a commit to JerAguilon/arrow that referenced this pull request May 29, 2024
…support bit-sized types (BOOL) (apache#41597)

### Rationale for this change

Post-merge feedback from apache#41297.

### What changes are included in this PR?

 - Supporting `BOOL` as both a top-level and nested in FSL types
 - Removing the long example from the docstring of `IsFixedWidthLike`

These changes don't affect users because this header was added recently and not released.

### Are these changes tested?

Yes, by existing and new test cases.
* GitHub Issue: apache#41596

Authored-by: Felipe Oliveira Carvalho <[email protected]>
Signed-off-by: Felipe Oliveira Carvalho <[email protected]>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

Successfully merging this pull request may close these issues.

5 participants