Skip to content

algorithms: do not skip leading elements of the second range in parallel set operations - #7844

Open
aneek22112007-tech wants to merge 3 commits into
TheHPXProject:masterfrom
aneek22112007-tech:fix-set-operation-first-chunk
Open

aneek22112007-tech wants to merge 3 commits into
TheHPXProject:masterfrom
aneek22112007-tech:fix-set-operation-first-chunk

Conversation

@aneek22112007-tech

Copy link
Copy Markdown
Contributor

Proposed Changes

  • In set_operation(), decide whether a chunk covers the start of the first range from start1 after walking it back over equal elements.
  • Add test_set_union_first_chunk_shifted and test_set_symmetric_difference_first_chunk_shifted.

Any background context you want to provide?

set_operation() splits the first input across worker threads. Before adjusting the chunk bounds, it recorded first_partition = (start1 == 0). A chunk that was not the original first partition then set start2 with lower_bound of its first value in the second range.

Every chunk except the last one returns immediately when its start and end values compare equal, leaving that partition for the next chunk. The next chunk walks start1 backward over elements equal to its predecessor. That walk can move start1 back to 0, so the chunk now covers the beginning of the first range. It still used the flag captured before the walk, computed start2 with lower_bound(first1[0]), and skipped every element of the second range smaller than first1[0].

With two or more worker threads, hpx::set_union(hpx::execution::par, {1, 1, 2}, {0}) returned 1 1 2 instead of 0 1 1 2. hpx::set_symmetric_difference(hpx::execution::par, {3, 3}, {0, 2}) returned 3 3 instead of 0 2 3 3. One thread does not split the range, so the same calls were correct at --hpx:threads=1.

The new tests compare those calls with std::set_union and std::set_symmetric_difference. With the fix removed, both fail at --hpx:threads=4 (8 checks each). With the fix, set_union_test and set_symmetric_difference_test passed 5/5 at --hpx:threads=1 and 5/5 at --hpx:threads=4. set_difference_test and set_intersection_test passed once each at 4 threads.

Using the adjusted start1 keeps start2 at 0 when the chunk has moved back to the start of the first range.

Checklist

  • I have added a new feature and have added tests to go along with it.
  • I have fixed a bug and have added a regression test.
  • I have added a test using random numbers; I have made sure it uses a seed, and that random numbers generated are valid inputs for the tests.

…lel set operations

set_operation() decided whether a chunk was the first partition before
moving start1 backwards over elements equal to their predecessor. When
the original first chunk bailed out (its start and end values compare
equal) and the next chunk moved start1 back to 0, that chunk still
computed start2 with lower_bound(first1[0]), silently dropping every
element of the second range smaller than first1[0]. With 2 or more
worker threads hpx::set_union(par, {1,1,2}, {0}) returned 1 1 2 and
set_symmetric_difference lost elements the same way. Decide based on
the adjusted start1 instead.

Signed-off-by: aneek22112007-tech <[email protected]>
@coderabbitai

coderabbitai Bot commented Oct 23, 2026 •

Copy link
Copy Markdown
Contributor

Review in Change Stack →

Important

Review skipped

Review was skipped as selected files did not have any reviewable changes.

Run configuration
  • Source mode: Auto
  • Repository: Unavailable
  • Branch: Unavailable
  • File: No configuration file from this repository applied
  • Commit: Unavailable
  • Layers: Repository UI
  • Review profile: CHILL
  • Plan: Advanced
  • Run ID: 478b3430-29b9-422a-8b5e-dd4afb0329ba
Commits

Reviewing files that changed from the base of the PR and between 8579c36 and b9b3d0a.

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Use the checkbox below for a quick retry:

  • 🔍 Trigger review

No actionable comments were generated in the recent review.

ℹ️ Recent review info
⚙️ Run configuration
  • Source mode: Auto
  • Repository: Unavailable
  • Branch: Unavailable
  • File: No configuration file from this repository applied
  • Commit: Unavailable
  • Layers: Repository UI
  • Review profile: CHILL
  • Plan: Advanced
  • Run ID: 2fea2727-86a3-4140-8bdd-7cd0463d84bb
📥 Commits

Reviewing files that changed from the base of the PR and between 2058cc1 and 589e3d4.

📒 Files selected for processing: 3
  • libs/core/algorithms/include/hpx/parallel/algorithms/detail/set_operation.hpp
  • libs/core/algorithms/tests/unit/algorithms/set_symmetric_difference.cpp
  • libs/core/algorithms/tests/unit/algorithms/set_union.cpp

Included review availability: This review used your included allowance. Your plan provides up to 8 included reviews per hour; 7 remain after this review.

📝 Summary

Summary by CodeRabbit

  • Bug Fixes

    • Improved correctness of parallel set union and symmetric difference for inputs containing duplicate values or unevenly sized ranges.
  • Tests

    • Added regression coverage comparing parallel results and output positions with standard-library behavior across repeated symmetric-difference runs and multiple set-union checks.

The set operation implementation now checks the first input start directly. Regression tests compare parallel set union and symmetric difference outputs and returned iterators with standard-library results for fixed input pairs.

Changes: Set operation partition condition

Layer / File(s) Summary
Direct partition-start check
libs/core/algorithms/include/hpx/parallel/algorithms/detail/set_operation.hpp
The sequence-2 lower-bound search checks start1 != 0 directly. The local first_partition flag is removed.
Shifted-input regression tests
libs/core/algorithms/tests/unit/algorithms/set_union.cpp, libs/core/algorithms/tests/unit/algorithms/set_symmetric_difference.cpp
New tests compare parallel results and returned output iterators with standard-library results. Both tests run four times and are called from hpx_main.

Priority: Normal

Estimated code review effort: 2 (Simple) | ~10 minutes

Change: Bug fix

Merge Risk: Minimal · up to 589e3

No unresolved issue is evident from the supplied change context; the change is ready for normal merge checks.

Pre-merge checks: Passed 4 · Failed 1

Failed Failed checks: 1 warning

Check name Status Explanation Resolution
Docstring Coverage Warning Docstring coverage is 28.57% which is insufficient. The required threshold is 80.00%. Docstring coverage is scoped to functions touched by this diff. Analyzed 7 functions across 3 files. Write docstrings for the functions missing them to satisfy the coverage threshold.
Passed Passed checks: 4 passed
Check name Status Explanation
Description check Passed The description clearly explains the parallel set-operation bug, the implementation change, and the added regression tests.
Title check Passed The title clearly and concisely identifies the main fix: preserving leading elements from the second range in parallel set operations.
Linked Issues check Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check Passed Check skipped because no linked issues were found for this pull request.
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create a new PR
  • Autofix · Keep fixing CodeRabbit findings and required CI, and resolving merge conflicts

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@codacy-production

Copy link
Copy Markdown

Up to standards ✅

🟢 Issues 0 issues

Results:
0 new issues

View in Codacy

NEW Get contextual insights on your PRs based on Codacy's metrics, along with PR and Jira context, without leaving GitHub. Enable AI reviewer
TIP This summary will be updated as you push new changes.

@StellarBot

Copy link
Copy Markdown
Collaborator

Can one of the admins verify this patch?

@Ishaan400

Copy link
Copy Markdown
Contributor

I ran into the same bug independently while comparing the parallel set algorithms against std:: on random inputs. For example, set_union(par, {3, 3, 3}, {2}) gives {3, 3, 3}. I arrived at the same change. With it applied locally, set_union and set_symmetric_difference matched std:: in 200,000 random cases (sorted inputs up to 6000 elements, few distinct values, seq and par, 2 threads), down from 4,044 mismatches with par before, and the existing set operation unit tests still pass.

@aneek22112007-tech

Copy link
Copy Markdown
Contributor Author

Thanks @Ishaan400 for independently confirming this, and for the randomized check against std::. That's great extra validation of the fix.

@aneek22112007-tech

Copy link
Copy Markdown
Contributor Author

@hkaiser the two red checks are unrelated to this change: init_runtime.force_disconnect (timeout) and supervision.distributed.tcp.supervision_await_terminal (assertion in test_await_terminal_epoch_mismatch_never_resolves). Everything else passes, including the set algorithm tests.

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants