3 ms·
00106 template<typename _InputIterator, typename _Tp, typename _BinaryOperation> 00107 _Tp 00108 accumulate(_InputIterator __first, _InputIter
by knome 2y ago
00106 template<typename _InputIterator, typename _Tp, typename _BinaryOperation>
00107 _Tp
00108 accumulate(_InputIterator __first, _InputIterator __last, _Tp __init,
00109 _BinaryOperation __binary_op)
00110 {
00111 // concept requirements
00112 __glibcxx_function_requires(_InputIteratorConcept<_InputIterator>)
00113 __glibcxx_requires_valid_range(__first, __last);
00114
00115 for (; __first != __last; ++__first)
00116 __init = __binary_op(__init, *__first);
00117 return __init;
00118 }
https://gcc.gnu.org/onlinedocs/libstdc++/libstdc++-html-USERS-4.0/stl__numeric_8h-source.html#l00108
It's just a loop.
The compiler is doing all of the same transformations regardless of whether you use the higher order function or just write a loop yourself.
--------------
_STD_BEGIN
_EXPORT_STD template <class _InIt, class _Ty, class _Fn>
_NODISCARD _CONSTEXPR20 _Ty accumulate(const _InIt _First, const _InIt _Last, _Ty _Val, _Fn _Reduce_op) {
// return noncommutative and nonassociative reduction of _Val and all in [_First, _Last), using _Reduce_op
_STD _Adl_verify_range(_First, _Last);
auto _UFirst = _STD _Get_unwrapped(_First);
const auto _ULast = _STD _Get_unwrapped(_Last);
for (; _UFirst != _ULast; ++_UFirst) {
#if _HAS_CXX20
_Val = _Reduce_op(_STD move(_Val), *_UFirst);
#else // ^^^ _HAS_CXX20 / !_HAS_CXX20 vvv
_Val = _Reduce_op(_Val, *_UFirst);
#endif // ^^^ !_HAS_CXX20 ^^^
}
return _Val;
}
https://github.com/microsoft/STL/blob/63354c3fa9c1fb2ab1fccb58c47d23c6af1c290f/stl/inc/numeric#L24
Also just a loop in MS' standard lib.
- nine_k 2y agoTry -O2 or -O3 like you would in a release build. See https://stackoverflow.com/a/50786881 https://stackoverflow.com/a/50786881
- knome 2y agoOptimization levels aren't going to care if you're using std::accumulate or not. They'll either analyze the loop directly, or they'll analyze it after munging it through the template function instantiation code and inlining the results of the template function. After that, both are doing what you originally said, lifting the C into an abstract form and analyzing it for whether parallel computation can be applied. Hell, the code to SSE enabled asm examples they give in the comment you link are just plain for loops.