-
Notifications
You must be signed in to change notification settings - Fork 15.2k
[libcxx] Added segmented iterator for count_if #105888
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
|
Thank you for submitting a Pull Request (PR) to the LLVM Project! This PR will be automatically labeled and the relevant teams will be notified. If you wish to, you can add reviewers by using the "Reviewers" section on this page. If this is not working for you, it is probably because you do not have write permissions for the repository. In which case you can instead tag reviewers by name in a comment by using If you have received no comments on your PR for a week, you can request a review by "ping"ing the PR by adding a comment “Ping”. The common courtesy "ping" rate is once a week. Please remember that you are asking for valuable time from other developers. If you have further questions, they may be answered by the LLVM GitHub User Guide. You can also ask questions in a comment on this PR, on the LLVM Discord or on the forums. |
|
@llvm/pr-subscribers-libcxx Author: None (adeel10x) ChangesFull diff: https://github.com/llvm/llvm-project/pull/105888.diff 1 Files Affected:
diff --git a/libcxx/include/__algorithm/count_if.h b/libcxx/include/__algorithm/count_if.h
index 25782069d03275..ba1cdb16b56b41 100644
--- a/libcxx/include/__algorithm/count_if.h
+++ b/libcxx/include/__algorithm/count_if.h
@@ -10,8 +10,10 @@
#ifndef _LIBCPP___ALGORITHM_COUNT_IF_H
#define _LIBCPP___ALGORITHM_COUNT_IF_H
+#include <__algorithm/for_each.h>
#include <__config>
#include <__iterator/iterator_traits.h>
+#include <__iterator/segmented_iterator.h>
#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
# pragma GCC system_header
@@ -19,10 +21,12 @@
_LIBCPP_BEGIN_NAMESPACE_STD
-template <class _InputIterator, class _Predicate>
+template <class _InputIterator,
+ class _Predicate,
+ __enable_if_t<!__is_segmented_iterator<_InputIterator>::value, int> = 0>
_LIBCPP_NODISCARD inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20
-typename iterator_traits<_InputIterator>::difference_type
-count_if(_InputIterator __first, _InputIterator __last, _Predicate __pred) {
+ typename iterator_traits<_InputIterator>::difference_type
+ __count_if(_InputIterator __first, _InputIterator __last, _Predicate __pred) {
typename iterator_traits<_InputIterator>::difference_type __r(0);
for (; __first != __last; ++__first)
if (__pred(*__first))
@@ -30,6 +34,27 @@ count_if(_InputIterator __first, _InputIterator __last, _Predicate __pred) {
return __r;
}
+template <class _SegmentedIterator,
+ class _Predicate,
+ __enable_if_t<__is_segmented_iterator<_SegmentedIterator>::value, int> = 0>
+_LIBCPP_NODISCARD inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20
+ typename iterator_traits<_SegmentedIterator>::difference_type
+ __count_if(_SegmentedIterator __first, _SegmentedIterator __last, _Predicate __pred) {
+ typename iterator_traits<_SegmentedIterator>::difference_type __r(0);
+ std::for_each(__first, __last, [&__r, __pred](auto& __val) mutable {
+ if (__pred(__val))
+ ++__r;
+ });
+ return __r;
+}
+
+template <class _InputIterator, class _Predicate>
+_LIBCPP_NODISCARD inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20
+ typename iterator_traits<_InputIterator>::difference_type
+ count_if(_InputIterator __first, _InputIterator __last, _Predicate __pred) {
+ return __count_if(__first, __last, __pred);
+}
+
_LIBCPP_END_NAMESPACE_STD
-#endif // _LIBCPP___ALGORITHM_COUNT_IF_H
+#endif // _LIBCPP___ALGORITHM_COUNT_IF_H
\ No newline at end of file
|
|
@philnik777 I have pushed the changes for count_if. If it looks fine to you, then I'll go ahead and benchmark. |
| #ifndef _LIBCPP___ALGORITHM_COUNT_IF_H | ||
| #define _LIBCPP___ALGORITHM_COUNT_IF_H | ||
|
|
||
| #include <__algorithm/for_each.h> |
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.
Not attached: This optimization should also be applied to ranges::count_if.
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.
@philnik777 I just want to confirm that you mean to say ranges::count_if and not std::count?
Also, Is ranges::for_each optimized for segmented iterators?
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.
I don't know whether ranges::for_each is optimized. If not, we should definitely do it.
| #include <__algorithm/for_each.h> | ||
| #include <__config> | ||
| #include <__iterator/iterator_traits.h> | ||
| #include <__iterator/segmented_iterator.h> |
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.
Not attached: Please add a benchmark to show that this actually improves performance.
…iterators. Used a single function template that calls std::for_each.
…egemnted iterators
|
@philnik777 I have added the benchmark for count_if to test performance with segmented_iterators: libcxx/test/benchmarks/algorithms/count_if.bench.cpp. |
…d redundant header includes
|
Benchmark compilation was failing due to this error: So, I guess I can't use
|
You should be able to use |
Could you also provide numbers before and after your patch? |
Can we use the template parameter with lambda expressions with C++11? Many files are being compiled with |
This is the new code: This is the command that causes clang crash: And this is the crash stack: No crash if I set -std=c++14/17/20/23 |
|
@adeel10x oh, sweet. Please file a bug against clang for the crash. No, there isn't a specific requirement to make this work in C++11. If there isn't a good reason not to do it we should though. Given that the simple option makes clang crash this seems like a good reason to not do it. Please add a >= C++14 guard and link the bug report. |
Hi @philnik777, If not, could you please tell me what guard I have to use here? |
I think it'd actually be simpler to just refactor the lambda to a function object. That should definitely work in C++03. (Also, you'd want to use |
|
@adeel10x do you plan to continue working on this? |
yes, I'll upload a new patch very soon. |
|
@philnik777 I tried using It also causes c++ std version issue while compiling cxx-benchmarks. This is the error message: Auto cannot be used in function parameters for >C++20. See this for reference. |
|
@adeel10x You can just use a classic template. |
No description provided.