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

[oneDPL] + oneapi::dpl::__internal::__compare #1621

Merged
merged 5 commits into from
Aug 30, 2024

Conversation

MikeDvorskiy
Copy link
Contributor

This PR introduces oneapi::dpl::__internal::__compare which replace a lambda in hetero __parallel_stable_sort pattern

@MikeDvorskiy MikeDvorskiy force-pushed the dev/mdvorski/sort_lambda_fix branch from 2b501c9 to e1bb26f Compare June 11, 2024 12:11
Comment on lines 140 to 143
operator()(_Xp&& __x, _Yp&& __y)
{
return __comp(__proj(std::forward<_Xp>(__x)), __proj(std::forward<_Yp>(__y)));
}
Copy link
Contributor

Choose a reason for hiding this comment

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

Why not keep const& parameters as in the original lambda? I believe neither comparators nor projections are supposed to modify their arguments.

Copy link
Contributor Author

@MikeDvorskiy MikeDvorskiy Jun 11, 2024

Choose a reason for hiding this comment

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

good question. I intended to keep const&, but made approach at least consistency with the other similar predicates (__pstl_equal, __pstl_less, etc).
The next question why the other similar predicates accept T&&, not const T&... Probably, we had a compile issue with some tricky types (a kind proxy types etc). I will try to figure out 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.

Actually, I've remembered a case when we had a compilation issue when we had changed T&& by const T&. It was the binary_search.pass test. That code tries to call a lambda with T& argument, which is const T& in its turn.

So, keeping const T& for argument of __compare doesn't matche to operator __proj, which can be implemented by user asoperator()(T&) {}.

So, keeping T& we make oneDPL more robust relative to a user projection type definition.

Copy link
Contributor

Choose a reason for hiding this comment

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

If I follow correctly, you are saying that using forwarding references here allows us to accommodate the case where a user provides a projection operator which takes as input a non-const lvalue ref (T&).

The question then follows: is this a good thing?

Our previous code did not enable this, it would be a compile time error. If a user's projection operator actually modifies the input reference, I believe that would result in UB in our sort routine (modified inputs every time the projection is applied). Conceptually projection operators shouldn't modify the input. So, what we are enabling is "convenience" for the user of not adding a const to their input params, and possibly letting a compile time error become a runtime error if their projection actually does modify the input.

Copy link
Contributor

Choose a reason for hiding this comment

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

C++17 states that predicates (unary and binary) as well as comparators "shall/will not apply any non-constant function through the dereferenced iterator". For parallel algorithms, it additionally states that unary and binary operations also "shall not directly or indirectly modify objects via their arguments".

In C++20, projections, comparators, predicates etc. for range-based algorithms are required to satisfy the regular_invocable concept. That concept states that the function invocation "shall not modify the
function object or the arguments."

That's what I meant above saying that "neither comparators nor projections are supposed to modify their arguments." Even if user-provided function objects can technically have non-constant call operators/parameters, its only benefit seems to allow users "forget" const qualifiers - at the risk of having runtime errors, like Dan said above.

Unfortunately, both std libraries and Thrust are tolerant to function objects omitting const, and this is the main reason why we may need to do the same.

Copy link
Contributor Author

@MikeDvorskiy MikeDvorskiy Jun 14, 2024

Choose a reason for hiding this comment

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

(1) done
(2) It seems we tend to relax the requirement - to use T&& instead for const T& for input parameters - so, it doesn't break working user code.

Copy link
Contributor

Choose a reason for hiding this comment

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

I think you misunderstood what I'm saying.
I agree this PR does not break working user code. The purpose of my comment is to state that it is "easy" to go in this direction. However, if we later were to change our minds and want to go back to const T&, from T&&, that could break working user code, so we would not make that change.
I'm just mentioning it to make it clear that we should be sure about our decision because it would be difficult to revert.

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 see your point, Dan....
Alexey (@akukanov), It seems we need a decision maker here.

Copy link
Contributor Author

@MikeDvorskiy MikeDvorskiy Jul 3, 2024

Choose a reason for hiding this comment

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

One more argument in favor of T&& - std::invoke accepts arguments as Args&&... args

Copy link
Contributor

@akukanov akukanov Aug 9, 2024

Choose a reason for hiding this comment

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

I am OK with the current patch. As for the plan - I do not object to revising the content of pstl/utils.h but I do not think it should be done for the same milestone.

@MikeDvorskiy MikeDvorskiy force-pushed the dev/mdvorski/sort_lambda_fix branch from c61dc9b to ecd747c Compare June 12, 2024 09:23
…, + mutabale for comparator and projection fields.
@mmichel11
Copy link
Contributor

I've looked through this PR as well as the parameter discussion and the current version of the patch looks good to me (assuming the minor outstanding comment is addressed).

There is a CI failure but it looks to be from an outdated mac configuration with the no longer supported icpc compiler that we have replaced to test with clang++. I think we should just make sure to get a clean per-commit CI run before merging.

danhoeflinger
danhoeflinger previously approved these changes Aug 29, 2024
Copy link
Contributor

@danhoeflinger danhoeflinger left a comment

Choose a reason for hiding this comment

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

LGTM,
I still prefer the version that adds the change suggested in this comment from @akukanov (I suggest it as a commit here for convenience), but I don't see it as a blocker, so I wont withhold my approval.

@MikeDvorskiy
Copy link
Contributor Author

@danhoeflinger , could you please re-approve (and merge) after your suggestion was committed?

@danhoeflinger danhoeflinger merged commit b742ac2 into main Aug 30, 2024
21 checks passed
@danhoeflinger danhoeflinger deleted the dev/mdvorski/sort_lambda_fix branch August 30, 2024 12:44
@@ -58,6 +58,9 @@ class __equal_value;
template <typename _Tp>
class __not_equal_value;

template <typename _Comp, typename _Proj>
class __compare;
Copy link
Contributor

Choose a reason for hiding this comment

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

class -> struct to align with the definition.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

7 participants