Skip to content

Commit 0621fd0

Browse files
authored
[libcxx] Optimize rng::generate_n for segmented iterators (#165280)
Part of #102817. This patch optimizes `rng::generate_n` for segmented iterators by forwarding the implementation directly to `std::generate_n`. - before ``` rng::generate_n(deque<int>)/32 21.7 ns 22.0 ns 32000000 rng::generate_n(deque<int>)/50 30.8 ns 30.7 ns 22400000 rng::generate_n(deque<int>)/1024 492 ns 488 ns 1120000 rng::generate_n(deque<int>)/8192 3938 ns 3924 ns 179200 ``` - after ``` rng::generate_n(deque<int>)/32 11.0 ns 11.0 ns 64000000 rng::generate_n(deque<int>)/50 16.2 ns 16.1 ns 40727273 rng::generate_n(deque<int>)/1024 292 ns 286 ns 2240000 rng::generate_n(deque<int>)/8192 2291 ns 2302 ns 298667 ```
1 parent e5bb946 commit 0621fd0

File tree

3 files changed

+19
-10
lines changed

3 files changed

+19
-10
lines changed

libcxx/docs/ReleaseNotes/22.rst

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -76,8 +76,9 @@ Improvements and New Features
7676
- The ``std::{fill, fill_n}`` and ``std::ranges::{fill, fill_n}`` algorithms have been optimized for segmented iterators,
7777
resulting in a performance improvement of at least 10x for ``std::deque<int>`` iterators and
7878
``std::join_view<std::vector<std::vector<int>>>`` iterators.
79-
- The ``std::generate`` and ``std::generate_n`` algorithms have been optimized for segmented iterators, resulting in a
80-
performance improvement for ``std::deque<short>`` and ``std::join_view<vector<vector<short>>>`` iterators.
79+
- The ``std::{generate, generate_n}`` and ``std::ranges::generate_n`` algorithms have been optimized for segmented
80+
iterators, resulting in a performance improvement for ``std::deque<short>`` and
81+
``std::join_view<vector<vector<short>>>`` iterators.
8182

8283
Deprecations and Removals
8384
-------------------------

libcxx/include/__algorithm/generate_n.h

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -13,22 +13,34 @@
1313
#include <__config>
1414
#include <__functional/identity.h>
1515
#include <__utility/forward.h>
16+
#include <__utility/move.h>
1617

1718
#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
1819
# pragma GCC system_header
1920
#endif
2021

22+
_LIBCPP_PUSH_MACROS
23+
#include <__undef_macros>
24+
2125
_LIBCPP_BEGIN_NAMESPACE_STD
2226

2327
template <class _OutputIterator, class _Size, class _Generator>
2428
inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 _OutputIterator
25-
generate_n(_OutputIterator __first, _Size __orig_n, _Generator __gen) {
29+
__generate_n(_OutputIterator __first, _Size __orig_n, _Generator& __gen) {
2630
using __iter_ref = decltype(*__first);
2731
__identity __proj;
2832
auto __f = [&](__iter_ref __element) { std::forward<__iter_ref>(__element) = __gen(); };
29-
return std::__for_each_n(__first, __orig_n, __f, __proj);
33+
return std::__for_each_n(std::move(__first), __orig_n, __f, __proj);
34+
}
35+
36+
template <class _OutputIterator, class _Size, class _Generator>
37+
inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 _OutputIterator
38+
generate_n(_OutputIterator __first, _Size __orig_n, _Generator __gen) {
39+
return std::__generate_n(std::move(__first), __orig_n, __gen);
3040
}
3141

3242
_LIBCPP_END_NAMESPACE_STD
3343

44+
_LIBCPP_POP_MACROS
45+
3446
#endif // _LIBCPP___ALGORITHM_GENERATE_N_H

libcxx/include/__algorithm/ranges_generate_n.h

Lines changed: 2 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
#ifndef _LIBCPP___ALGORITHM_RANGES_GENERATE_N_H
1010
#define _LIBCPP___ALGORITHM_RANGES_GENERATE_N_H
1111

12+
#include <__algorithm/generate_n.h>
1213
#include <__concepts/constructible.h>
1314
#include <__concepts/invocable.h>
1415
#include <__config>
@@ -38,12 +39,7 @@ struct __generate_n {
3839
requires invocable<_Func&> && indirectly_writable<_OutIter, invoke_result_t<_Func&>>
3940
_LIBCPP_HIDE_FROM_ABI constexpr _OutIter
4041
operator()(_OutIter __first, iter_difference_t<_OutIter> __n, _Func __gen) const {
41-
for (; __n > 0; --__n) {
42-
*__first = __gen();
43-
++__first;
44-
}
45-
46-
return __first;
42+
return std::__generate_n(std::move(__first), __n, __gen);
4743
}
4844
};
4945

0 commit comments

Comments
 (0)