Namespaces
Variants

std::experimental::parallel:: reduce

From cppreference.net
Défini dans l'en-tête <experimental/numeric>
template < class InputIt >

typename std:: iterator_traits < InputIt > :: value_type reduce (

InputIt first, InputIt last ) ;
(1) (TS parallélisme)
template < class ExecutionPolicy, class InputIterator >

typename std:: iterator_traits < InputIt > :: value_type reduce (

ExecutionPolicy && policy, InputIt first, InputIt last ) ;
(2) (TS parallélisme)
template < class InputIt, class T >
T reduce ( InputIt first, InputIt last, T init ) ;
(3) (TS parallélisme)
template < class ExecutionPolicy, class InputIt, class T >
T reduce ( ExecutionPolicy && policy, InputIt first, InputIt last, T init ) ;
(4) (TS parallélisme)
template < class InputIt, class T, class BinaryOp >
T reduce ( InputIt first, InputIt last, T init, BinaryOp binary_op ) ;
(5) (TS parallélisme)
template < class ExecutionPolicy, class InputIt, class T, class BinaryOp >

T reduce ( ExecutionPolicy && policy,

InputIt first, InputIt last, T init, BinaryOp binary_op ) ;
(6) (TS parallélisme)
1) Identique à reduce ( first, last, typename std:: iterator_traits < InputIt > :: value_type { } ) .
3) Identique à reduce ( first, last, init, std:: plus <> ( ) ) .
5) Réduit la plage [ first , last ) , potentiellement permutée et agrégée de manière non spécifiée, avec la valeur initiale init via binary_op .
2,4,6) Identique à (1,3,5) , mais exécuté selon la policy .

Le comportement est non déterministe si binary_op n'est pas associatif ou n'est pas commutatif.

Le comportement n'est pas défini si binary_op modifie un élément quelconque ou invalide un itérateur dans [ first , last ) .

Table des matières

Paramètres

first, last - la plage d'éléments à laquelle appliquer l'algorithme
init - la valeur initiale de la somme généralisée
policy - la politique d'exécution
binary_op - le FunctionObject binaire qui sera appliqué dans un ordre non spécifié au résultat du déréférencement des itérateurs d'entrée, aux résultats d'autres binary_op et à init
Exigences de type
-
InputIt doit satisfaire aux exigences de LegacyInputIterator .

Valeur de retour

Somme généralisée de init et * first , * ( first + 1 ) , ... * ( last - 1 ) sur binary_op ,

où la somme généralisée GSUM(op, a 1 , ..., a N ) est définie comme suit :

  • si N=1 , a 1
  • si N > 1 , op(GSUM(op, b 1 , ..., b K ), GSUM(op, b M , ..., b N ))
  • b 1 , ..., b N peut être n'importe quelle permutation de a1, ..., aN et
  • 1 < K+1 = M ≤ N

en d'autres termes, les éléments de la plage peuvent être regroupés et réorganisés dans un ordre arbitraire.

Complexité

O(last - first) applications de binary_op .

Exceptions

  • Si l'exécution d'une fonction invoquée dans le cadre de l'algorithme lève une exception,
  • si policy est parallel_vector_execution_policy , std::terminate est appelé.
  • si policy est sequential_execution_policy ou parallel_execution_policy , l'algorithme se termine avec une exception_list contenant toutes les exceptions non capturées. S'il n'y avait qu'une seule exception non capturée, l'algorithme peut la relancer sans l'encapsuler dans exception_list . Il n'est pas spécifié combien de travail l'algorithme effectuera avant de retourner après la première exception rencontrée.
  • si policy est d'un autre type, le comportement est défini par l'implémentation.
  • Si l'algorithme ne parvient pas à allouer de la mémoire (soit pour lui-même, soit pour construire une exception_list lors de la gestion d'une exception utilisateur), std::bad_alloc est levée.

Notes

Si la plage est vide, init est retourné, inchangé.

  • Si policy est une instance de sequential_execution_policy , toutes les opérations sont exécutées dans le thread appelant.
  • Si policy est une instance de parallel_execution_policy , les opérations peuvent être exécutées dans un nombre non spécifié de threads, de manière séquencée indéterminée les unes par rapport aux autres.
  • Si policy est une instance de parallel_vector_execution_policy , l'exécution peut être parallélisée et vectorisée : les limites des corps de fonction ne sont pas respectées et le code utilisateur peut être chevauché et combiné de manière arbitraire (ce qui implique notamment qu'un Callable fourni par l'utilisateur ne doit pas acquérir de mutex pour accéder à une ressource partagée).

Exemple

reduce est la version non ordonnée de std::accumulate :

#include <chrono>
#include <experimental/execution_policy>
#include <experimental/numeric>
#include <iostream>
#include <numeric>
#include <vector>
int main()
{
    std::vector<double> v(10'000'007, 0.5);
    {
        auto t1 = std::chrono::high_resolution_clock::now();
        double result = std::accumulate(v.begin(), v.end(), 0.0);
        auto t2 = std::chrono::high_resolution_clock::now();
        std::chrono::duration<double, std::milli> ms = t2 - t1;
        std::cout << std::fixed << "std::accumulate result " << result
                  << " took " << ms.count() << " ms\n";
    }
    {
        auto t1 = std::chrono::high_resolution_clock::now();
        double result = std::experimental::parallel::reduce(
                            std::experimental::parallel::par,
                            v.begin(), v.end());
        auto t2 = std::chrono::high_resolution_clock::now();
        std::chrono::duration<double, std::milli> ms = t2 - t1;
        std::cout << "parallel::reduce result "
                  << result << " took " << ms.count() << " ms\n";
    }
}

Sortie possible :

std::accumulate result 5000003.50000 took 12.7365 ms
parallel::reduce result 5000003.50000 took 5.06423 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)
(parallelism TS)
applique un foncteur, puis réduit de manière non ordonnée
(modèle de fonction)