std:: reduce
|
Défini dans l'en-tête
<numeric>
|
||
|
template
<
class
InputIt
>
typename
std::
iterator_traits
<
InputIt
>
::
value_type
|
(1) |
(depuis C++17)
(constexpr depuis C++20) |
|
template
<
class
ExecutionPolicy,
class
ForwardIt
>
typename
std::
iterator_traits
<
ForwardIt
>
::
value_type
|
(2) | (depuis C++17) |
|
template
<
class
InputIt,
class
T
>
T reduce ( InputIt first, InputIt last, T init ) ; |
(3) |
(depuis C++17)
(constexpr depuis C++20) |
|
template
<
class
ExecutionPolicy,
class
ForwardIt,
class
T
>
T reduce
(
ExecutionPolicy
&&
policy,
|
(4) | (depuis C++17) |
|
template
<
class
InputIt,
class
T,
class
BinaryOp
>
T reduce ( InputIt first, InputIt last, T init, BinaryOp op ) ; |
(5) |
(depuis C++17)
(constexpr depuis C++20) |
|
template
<
class
ExecutionPolicy,
class
ForwardIt,
class
T,
class
BinaryOp
>
|
(6) | (depuis C++17) |
[
first
,
last
)
, potentiellement permutée et agrégée de manière non spécifiée, avec la valeur initiale
init
via
op
.
|
std:: is_execution_policy_v < std:: decay_t < ExecutionPolicy >> est true . |
(jusqu'à C++20) |
|
std:: is_execution_policy_v < std:: remove_cvref_t < ExecutionPolicy >> est true . |
(depuis C++20) |
Étant donné binary_op comme l'opération binaire réelle :
- Le résultat est non déterministe si le binary_op n'est pas associatif ou non commutatif (comme l'addition en virgule flottante).
-
Si l'une des valeurs suivantes n'est pas convertible en
T, le programme est mal formé :
-
- binary_op ( init, * first )
- binary_op ( * first, init )
- binary_op ( init, init )
- binary_op ( * first, * first )
- Si l'une des conditions suivantes est satisfaite, le comportement est indéfini :
-
-
Tn'est pas MoveConstructible . -
binary_op
modifie un élément quelconque de
[first,last). -
binary_op
invalide un itérateur ou un sous-intervalle quelconque de
[first,last].
-
Table des matières |
Paramètres
| first, last | - | la paire d'itérateurs définissant l'intervalle des éléments auxquels appliquer l'algorithme |
| init | - | la valeur initiale de la somme généralisée |
| policy | - | la politique d'exécution à utiliser |
| op | - | le FunctionObject binaire qui sera appliqué dans un ordre non spécifié au résultat de la déréférenciation des itérateurs d'entrée, aux résultats d'autres op et init . |
| Exigences de type | ||
-
InputIt
doit satisfaire aux exigences de
LegacyInputIterator
.
|
||
-
ForwardIt
doit satisfaire aux exigences de
LegacyForwardIterator
.
|
||
Valeur de retour
[
first
,
last
)
sur
op
.
La somme généralisée d'un groupe d'éléments sur une opération binaire binary_op est définie comme suit :
- Si le groupe ne contient qu'un seul élément, la somme est la valeur de cet élément.
- Sinon, effectue les opérations suivantes dans l'ordre :
- Prend deux éléments quelconques elem1 et elem2 du groupe.
- Calcule binary_op ( elem1, elem2 ) et replace le résultat dans le groupe.
- Répète les étapes 1 et 2 jusqu'à ce qu'il ne reste qu'un seul élément dans le groupe.
Complexité
Étant donné N comme std:: distance ( first, last ) :
Exceptions
Les surcharges avec un paramètre de modèle nommé
ExecutionPolicy
signalent les erreurs comme suit :
-
Si l'exécution d'une fonction invoquée dans le cadre de l'algorithme lève une exception et que
ExecutionPolicyfait partie des politiques standard , std::terminate est appelé. Pour tout autreExecutionPolicy, le comportement est défini par l'implémentation. - Si l'algorithme ne parvient pas à allouer de la mémoire, std::bad_alloc est levé.
Notes
std::reduce
se comporte comme
std::accumulate
sauf que les éléments de la plage peuvent être groupés et réorganisés dans un ordre arbitraire.
Exemple
Comparaison côte à côte entre
std::reduce
et
std::accumulate
:
#if PARALLEL #include <execution> #define SEQ std::execution::seq, #define PAR std::execution::par, #else #define SEQ #define PAR #endif #include <chrono> #include <iomanip> #include <iostream> #include <locale> #include <numeric> #include <utility> #include <vector> int main() { std::cout.imbue(std::locale("en_US.UTF-8")); std::cout << std::fixed << std::setprecision(1); auto eval = [](auto fun) { const auto t1 = std::chrono::high_resolution_clock::now(); const auto [nom, résultat] = fun(); const auto t2 = std::chrono::high_resolution_clock::now(); const std::chrono::duration<double, std::milli> ms = t2 - t1; std::cout << std::setw(28) << std::left << nom << "somme : " << résultat << '\t' << "temps : " << ms.count() << " ms\n"; }; { const std::vector<double> v(100'000'007, 0.1); eval([&v]{ return std::pair{"std::accumulate (double)", std::accumulate(v.cbegin(), v.cend(), 0.0)}; }); eval([&v]{ return std::pair{"std::reduce (seq, double)", std::reduce(SEQ v.cbegin(), v.cend())}; }); eval([&v]{ return std::pair{"std::reduce (par, double)", std::reduce(PAR v.cbegin(), v.cend())}; }); } { const std::vector<long> v(100'000'007, 1); eval([&v]{ return std::pair{"std::accumulate (long)", std::accumulate(v.cbegin(), v.cend(), 0l)}; }); eval([&v]{ return std::pair{"std::reduce (seq, long)", std::reduce(SEQ v.cbegin(), v.cend())}; }); eval([&v]{ return std::pair{"std::reduce (par, long)", std::reduce(PAR v.cbegin(), v.cend())}; }); } }
Sortie possible :
// POSIX: g++ -std=c++23 ./example.cpp -ltbb -O3; ./a.out std::accumulate (double) somme : 10,000,000.7 temps : 356.9 ms std::reduce (seq, double) somme : 10,000,000.7 temps : 140.1 ms std::reduce (par, double) somme : 10,000,000.7 temps : 140.1 ms std::accumulate (long) somme : 100,000,007 temps : 46.0 ms std::reduce (seq, long) somme : 100,000,007 temps : 67.3 ms std::reduce (par, long) somme : 100,000,007 temps : 63.3 ms // POSIX: g++ -std=c++23 ./example.cpp -ltbb -O3 -DPARALLEL; ./a.out std::accumulate (double) somme : 10,000,000.7 temps : 353.4 ms std::reduce (seq, double) somme : 10,000,000.7 temps : 140.7 ms std::reduce (par, double) somme : 10,000,000.7 temps : 24.7 ms std::accumulate (long) somme : 100,000,007 temps : 42.4 ms std::reduce (seq, long) somme : 100,000,007 temps : 52.0 ms std::reduce (par, long) somme : 100,000,007 temps : 23.1 ms
Voir aussi
|
additionne ou plie une plage d'éléments
(modèle de fonction) |
|
|
applique une fonction à une plage d'éléments, stockant les résultats dans une plage de destination
(modèle de fonction) |
|
|
(C++17)
|
applique un objet appelable, puis réduit de manière non ordonnée
(modèle de fonction) |
|
(C++23)
|
plie vers la gauche une plage d'éléments
(objet fonction d'algorithme) |