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

Add UnorderedMapInsertOps for coo2crs #5877

Merged
merged 13 commits into from
Mar 30, 2023
Merged

Conversation

e10harvey
Copy link
Contributor

To implement the sparse conversion kernel, coo2crs, I would like to have duplicate key insertions accumulate values in a Kokkos::UnorderedMap. This PR adds UnorderedMapInsertOps::AtomicAdd and UnorderedMapInsertOps::NoOp (the current insertion behavior for duplicate keys).

Related to kokkos/kokkos-kernels#1164.

Going forward, I would also like to extend Kokkos::UnorderedMap to support shared memory and add UnorderedMapInsertOps::Overwrite.

containers/src/Kokkos_UnorderedMap.hpp Outdated Show resolved Hide resolved
containers/src/Kokkos_UnorderedMap.hpp Outdated Show resolved Hide resolved
containers/src/Kokkos_UnorderedMap.hpp Outdated Show resolved Hide resolved
containers/src/Kokkos_UnorderedMap.hpp Outdated Show resolved Hide resolved
containers/src/Kokkos_UnorderedMap.hpp Outdated Show resolved Hide resolved
containers/src/Kokkos_UnorderedMap.hpp Outdated Show resolved Hide resolved
containers/unit_tests/TestUnorderedMap.hpp Outdated Show resolved Hide resolved
containers/src/Kokkos_UnorderedMap.hpp Outdated Show resolved Hide resolved
containers/src/Kokkos_UnorderedMap.hpp Outdated Show resolved Hide resolved
containers/src/Kokkos_UnorderedMap.hpp Outdated Show resolved Hide resolved
@masterleinad
Copy link
Contributor

Apparently, this fails on the OpenMP backend and you will also need to fix the indentation. 🙂

@masterleinad
Copy link
Contributor

Looks like there is still a segfault (at least for OpenMP).

containers/src/Kokkos_UnorderedMap.hpp Outdated Show resolved Hide resolved
containers/src/Kokkos_UnorderedMap.hpp Outdated Show resolved Hide resolved
containers/src/Kokkos_UnorderedMap.hpp Outdated Show resolved Hide resolved
Copy link
Member

@crtrott crtrott left a comment

Choose a reason for hiding this comment

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

The proposed approach is a breaking change: why can't we just have an insert function overload which takes an op, or add a insert_accumulate function?

containers/src/Kokkos_UnorderedMap.hpp Outdated Show resolved Hide resolved
Kokkos::View<std::remove_const_t<std::conditional_t<
std::is_void_v<Value>, int, Value>> *,
Device>,
uint32_t>::NoOp>
Copy link
Member

Choose a reason for hiding this comment

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

Adding a template parameter is a breaking change we can't do that really. We could discuss adding this only if deprecated code off, but we can't simply add it. Alternatively, why can't we have an overload of insert which takes an insert op? Is there a reason this has to be a global template for the class?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

This seems like the lightest-weight way to add this operation as well as following the implementation style of UnorderedMap. What about keeping the current approach with a single constructor overload, rather than a new insert method, the constructor overload could include the InsertOp type and constructor parameter?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Thinking about this more now, I see no reason for making the InsertOp a global template for the class other than following the existing implementation style of UnorderedMap (e.g. EqualTo, etc.). I will try refactoring with a new insert method instead. Can you elaborate on how the InsertOp template parameter is a breaking change?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

After trying to remove the InsertOp as a global template parameter, I found that deep copy no longer works. I will look into using insert method overloads rather than a class member.

containers/src/Kokkos_UnorderedMap.hpp Outdated Show resolved Hide resolved
@@ -532,6 +593,7 @@ class UnorderedMap {
}

result.set_existing(curr, free_existing);
if (!is_set) m_insert_op.op(m_values, curr, &v);
Copy link
Member

Choose a reason for hiding this comment

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

yeah this is the only place where this is used. I think we can just have an overload of insert which takes the insert op. Or maybe even have a different name: insert_accumulate or so. Do you see any issue with that approach?

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 only issue I see would be a lot of duplicate code.

@e10harvey
Copy link
Contributor Author

This is ready for another round of reviews. CI tests for 87c3691 will fail until #5899 merges.

@crtrott
Copy link
Member

crtrott commented Mar 15, 2023

Needs a rebase. Question at everyone but especially @masterleinad @nmm0 @nliber @dalg24: Do we like the way the insert ops are grouped here mechanically as nested classes in a separate class?

There are alternatives:

  • nested namespace
  • make them nested classes in UnorderedMap itself
  • named ops (this is what ScatterView does where the ops are called ScatterAdd etc. in the Kokkos::Experimental namespace)

At least we should check for where we do other stuff like that and what approach we take so we can end up with a consistent way of doing this.

@crtrott
Copy link
Member

crtrott commented Mar 15, 2023

Oh just to confirm: the overload approach of insert with a default insert mechanism is good now.

@nmm0
Copy link
Contributor

nmm0 commented Mar 15, 2023

Needs a rebase. Question at everyone but especially @masterleinad @nmm0 @nliber @dalg24: Do we like the way the insert ops are grouped here mechanically as nested classes in a separate class?

There are alternatives:

* nested namespace

* make them nested classes in UnorderedMap itself

* named ops (this is what ScatterView does where the ops are called ScatterAdd etc. in the Kokkos::Experimental namespace)

At least we should check for where we do other stuff like that and what approach we take so we can end up with a consistent way of doing this.

I guess one question is whether we want this to be a point of customization. I'm not saying we should but if we want additional ops to be added we can't use it in a nested class.

Copy link
Contributor

@nmm0 nmm0 left a comment

Choose a reason for hiding this comment

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

Could you add a test for void value'd maps (i.e. sets)? What is the expected behavior of the ops when value is void?

containers/src/Kokkos_UnorderedMap.hpp Outdated Show resolved Hide resolved
@e10harvey
Copy link
Contributor Author

Could you add a test for void value'd maps (i.e. sets)? What is the expected behavior of the ops when value is void?

Hi @nmm0. Thanks for your review. The op is not executed when the map is void value'd due to if(!is_set). This is already tested and handled the same way it was before this PR was opened. The specific line of code introduced for getting void value'd maps with these insert ops to still build is: https://github.com/kokkos/kokkos/pull/5877/files#diff-2c8acfc1ac5cbbb4cc3da14e466f42c85e415b540c815bf2630c42ec2ac09d59R576.

e10harvey and others added 3 commits March 15, 2023 12:11
Co-authored-by: Daniel Arndt <arndtd@ornl.gov>
Fix OpenMP test failures
Fix CI build error
Increase size of expected_values
@nmm0
Copy link
Contributor

nmm0 commented Mar 15, 2023

Could you add a test for void value'd maps (i.e. sets)? What is the expected behavior of the ops when value is void?

Hi @nmm0. Thanks for your review. The op is not executed when the map is void value'd due to if(!is_set). This is already tested and handled the same way it was before this PR was opened. The specific line of code introduced for getting void value'd maps with these insert ops to still build is: https://github.com/kokkos/kokkos/pull/5877/files#diff-2c8acfc1ac5cbbb4cc3da14e466f42c85e415b540c815bf2630c42ec2ac09d59R576.

Thanks for the clarification!

Let's then do:

if constexpr (!is_set) {
  arg_insert_op.op(m_values, curr, v);
}

Then we don't have to worry about it compiling with a set. Also, in that case, I think we should probably not allow the op to be even specified if inserting into a set.

This is something we probably need to deal with now, because if a user specifies an InsertOp for a set and we clean up the interface later then it would be a breaking change.

I'd like to get other people's opinion on it but one suggestion would be to just do a static_assert, which would be a quick fix rather than making an overload:

if constexpr (is_set) {
  static_assert(std::is_same_v<InsertOpType, default_op_type>);
}

Ensure m_insert_op gets copied too
@e10harvey
Copy link
Contributor Author

The Jenkins SYCL-OneApi failure is unrelated to these changes:

43: [ RUN      ] std_algorithms_sorting_ops_test.is_sorted_until
43: is_sorted_until: dynamic_view, all overloads 
43: /var/jenkins/workspace/Kokkos/algorithms/unit_tests/TestStdAlgorithmsIsSortedUntil.cpp:150: Failure
43: Expected equality of these values:
43:   r3
43:     Which is: 32-byte object <70-0B C3-02 00-00 00-00 80-00 A0-93 9C-7F 00-00 89-8C 01-00 00-00 00-00 F9-02 00-00 00-00 00-00>
43:   gold
43:     Which is: 32-byte object <70-0B C3-02 00-00 00-00 80-00 A0-93 9C-7F 00-00 89-8C 01-00 00-00 00-00 9C-00 00-00 00-00 00-00>
43: /var/jenkins/workspace/Kokkos/algorithms/unit_tests/TestStdAlgorithmsIsSortedUntil.cpp:151: Failure
43: Expected equality of these values:
43:   r4
43:     Which is: 32-byte object <70-0B C3-02 00-00 00-00 80-00 A0-93 9C-7F 00-00 89-8C 01-00 00-00 00-00 01-03 00-00 00-00 00-00>
43:   gold
43:     Which is: 32-byte object <70-0B C3-02 00-00 00-00 80-00 A0-93 9C-7F 00-00 89-8C 01-00 00-00 00-00 9C-00 00-00 00-00 00-00>
43: /var/jenkins/workspace/Kokkos/algorithms/unit_tests/TestStdAlgorithmsIsSortedUntil.cpp:165: Failure
43: Expected equality of these values:
43:   r3
43:     Which is: 32-byte object <70-0B C3-02 00-00 00-00 80-00 A0-93 9C-7F 00-00 89-8C 01-00 00-00 00-00 F9-02 00-00 00-00 00-00>
43:   gold
43:     Which is: 32-byte object <70-0B C3-02 00-00 00-00 80-00 A0-93 9C-7F 00-00 89-8C 01-00 00-00 00-00 9C-00 00-00 00-00 00-00>
43: /var/jenkins/workspace/Kokkos/algorithms/unit_tests/TestStdAlgorithmsIsSortedUntil.cpp:166: Failure
43: Expected equality of these values:
43:   r4
43:     Which is: 32-byte object <70-0B C3-02 00-00 00-00 80-00 A0-93 9C-7F 00-00 89-8C 01-00 00-00 00-00 01-03 00-00 00-00 00-00>
43:   gold
43:     Which is: 32-byte object <70-0B C3-02 00-00 00-00 80-00 A0-93 9C-7F 00-00 89-8C 01-00 00-00 00-00 9C-00 00-00 00-00 00-00>
43: is_sorted_until: stride2_view, all overloads 
43: is_sorted_until: stride3_view, all overloads 
43: [  FAILED  ] std_algorithms_sorting_ops_test.is_sorted_until (72 ms)

Full console: https://cloud.cees.ornl.gov/jenkins-ci/blue/rest/organizations/jenkins/pipelines/Kokkos/runs/12424/nodes/49/steps/252/log/?start=0.

@e10harvey
Copy link
Contributor Author

The Jenkins SYCL-OneApi failed again:

43: [ RUN      ] std_algorithms_sorting_ops_test.is_sorted_until
43: is_sorted_until: dynamic_view, all overloads 
43: /var/jenkins/workspace/Kokkos/algorithms/unit_tests/TestStdAlgorithmsIsSortedUntil.cpp:148: Failure
43: Expected equality of these values:
43:   r1
43:     Which is: 32-byte object <40-15 04-02 00-00 00-00 80-00 A0-B3 AD-7F 00-00 89-8C 01-00 00-00 00-00 89-8C 01-00 00-00 00-00>
43:   gold
43:     Which is: 32-byte object <40-15 04-02 00-00 00-00 80-00 A0-B3 AD-7F 00-00 89-8C 01-00 00-00 00-00 9C-00 00-00 00-00 00-00>
43: /var/jenkins/workspace/Kokkos/algorithms/unit_tests/TestStdAlgorithmsIsSortedUntil.cpp:163: Failure
43: Expected equality of these values:
43:   r1
43:     Which is: 32-byte object <40-15 04-02 00-00 00-00 80-00 A0-B3 AD-7F 00-00 89-8C 01-00 00-00 00-00 89-8C 01-00 00-00 00-00>
43:   gold
43:     Which is: 32-byte object <40-15 04-02 00-00 00-00 80-00 A0-B3 AD-7F 00-00 89-8C 01-00 00-00 00-00 9C-00 00-00 00-00 00-00>
43: is_sorted_until: stride2_view, all overloads 
43: is_sorted_until: stride3_view, all overloads 
43: [  FAILED  ] std_algorithms_sorting_ops_test.is_sorted_until (143 ms)

Can anyone confirm that this failure is unrelated to these changes?

@masterleinad
Copy link
Contributor

I would think that the failure is unrelated; the test is not using Kokkos::UnorderedMap.

containers/src/Kokkos_UnorderedMap.hpp Outdated Show resolved Hide resolved
containers/src/Kokkos_UnorderedMap.hpp Outdated Show resolved Hide resolved
e10harvey and others added 2 commits March 20, 2023 07:49
Co-authored-by: Daniel Arndt <arndtd@ornl.gov>
@e10harvey
Copy link
Contributor Author

e10harvey commented Mar 20, 2023

I think this is ready to merge. The OpenMP Target CI failure in Jenkins appears to be unrelated to these change.

Copy link
Contributor

@masterleinad masterleinad left a comment

Choose a reason for hiding this comment

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

Looks OK to me.

@nmm0
Copy link
Contributor

nmm0 commented Mar 22, 2023

Needs a rebase. Question at everyone but especially @masterleinad @nmm0 @nliber @dalg24: Do we like the way the insert ops are grouped here mechanically as nested classes in a separate class?

There are alternatives:

* nested namespace

* make them nested classes in UnorderedMap itself

* named ops (this is what ScatterView does where the ops are called ScatterAdd etc. in the Kokkos::Experimental namespace)

At least we should check for where we do other stuff like that and what approach we take so we can end up with a consistent way of doing this.

@crtrott did you get satisfactory feedback on this?

Copy link
Contributor

@nmm0 nmm0 left a comment

Choose a reason for hiding this comment

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

I think this is ready depending on what we decide for the convention for Ops

However it needs a changelog entry (4.1) and a corresponding PR for the docs

@nmm0 nmm0 added this to the Release 4.1 milestone Mar 22, 2023
@e10harvey
Copy link
Contributor Author

I think this is ready depending on what we decide for the convention for Ops

However it needs a changelog entry (4.1) and a corresponding PR for the docs

Thinking about Christian's question some more now and in particular how ScatterView handles insertion operators, we should be consistent if possible. @nmm0, @dalg24: Is ScatterView the only other container that supports "operations" in Kokkos core?

Copy link
Contributor

@nmm0 nmm0 left a comment

Choose a reason for hiding this comment

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

Thanks for adding docs and changelog!

@e10harvey
Copy link
Contributor Author

e10harvey commented Mar 23, 2023

I think this is ready depending on what we decide for the convention for Ops
However it needs a changelog entry (4.1) and a corresponding PR for the docs

Thinking about Christian's question some more now and in particular how ScatterView handles insertion operators, we should be consistent if possible. @nmm0, @dalg24: Is ScatterView the only other container that supports "operations" in Kokkos core?

It looks like ScatterView has the concept of a ScatterValue type and specializes ScatterValue for the supported "operation" types like ScatterSum. Thinking about how to support extension of insertion operations in this way is not clear to me. Before this PR, the Kokkos::UnorderedMap only required operator= for the given value_type. With this PR, we only change what operation is used if the given key already exists. So, from my perspective, I think the current approach using arg_insert_op is cleaner than introducing the concept of a ValueType with a ValueOp to UnorderedMap since the body of insert and UnorderedMap are not exposed so generally in the form of a data-type with operator overloads like ScatterView is. In a later PR, we could revisit UnorderedMapInsertOpTypes if they are found to be difficult to use and extend.

@dalg24
Copy link
Member

dalg24 commented Mar 28, 2023

Retest this please

1 similar comment
@PhilMiller
Copy link
Contributor

Retest this please

@PhilMiller
Copy link
Contributor

Rerunning the tests, since it looks like Jenkins had a hiccup

@e10harvey
Copy link
Contributor Author

Retest this please

@e10harvey
Copy link
Contributor Author

GCC 8.4.0 timed out and the SYCL-OneApi test failed again:

43: is_sorted_until: dynamic_view, all overloads 
43: /var/jenkins/workspace/Kokkos/algorithms/unit_tests/TestStdAlgorithmsIsSortedUntil.cpp:149: Failure
43: Expected equality of these values:
43:   r2
43:     Which is: 32-byte object <10-54 8F-02 00-00 00-00 80-00 A0-D3 9A-7F 00-00 89-8C 01-00 00-00 00-00 E1-02 00-00 00-00 00-00>
43:   gold
43:     Which is: 32-byte object <10-54 8F-02 00-00 00-00 80-00 A0-D3 9A-7F 00-00 89-8C 01-00 00-00 00-00 9C-00 00-00 00-00 00-00>
43: /var/jenkins/workspace/Kokkos/algorithms/unit_tests/TestStdAlgorithmsIsSortedUntil.cpp:164: Failure
43: Expected equality of these values:
43:   r2
43:     Which is: 32-byte object <10-54 8F-02 00-00 00-00 80-00 A0-D3 9A-7F 00-00 89-8C 01-00 00-00 00-00 E1-02 00-00 00-00 00-00>
43:   gold
43:     Which is: 32-byte object <10-54 8F-02 00-00 00-00 80-00 A0-D3 9A-7F 00-00 89-8C 01-00 00-00 00-00 9C-00 00-00 00-00 00-00>
43: is_sorted_until: stride2_view, all overloads 
43: is_sorted_until: stride3_view, all overloads 
43: [  FAILED  ] std_algorithms_sorting_ops_test.is_sorted_until (74 ms)

@dalg24 dalg24 merged commit fdb089b into kokkos:develop Mar 30, 2023
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.

None yet

6 participants