Namespaces
Variants

std::experimental::parallel:: transform_reduce

From cppreference.net
Definido en el encabezado <experimental/numeric>
template < class InputIt, class UnaryOp, class T, class BinaryOp >

T transform_reduce ( InputIt first, InputIt last,

UnaryOp unary_op, T init, BinaryOp binary_op ) ;
(1) (TS de paralelismo)
template < class ExecutionPolicy,

class InputIt, class UnaryOp, class T, class BinaryOp >
T transform_reduce ( ExecutionPolicy && policy,
InputIt first, InputIt last,

UnaryOp unary_op, T init, BinaryOp binary_op ) ;
(2) (TS de paralelismo)

Aplica unary_op a cada elemento en el rango [ first , last ) y reduce los resultados (posiblemente permutados y agregados de manera no especificada) junto con el valor inicial init mediante binary_op .

El comportamiento es no determinista si binary_op no es asociativo o no es conmutativo.

El comportamiento es indefinido si unary_op o binary_op modifica cualquier elemento o invalida cualquier iterador en [ first , last ) .

Contenidos

Parámetros

first, last - el rango de elementos al que aplicar el algoritmo
init - el valor inicial de la suma generalizada
policy - la política de ejecución
unary_op - objeto función unario FunctionObject que se aplicará a cada elemento del rango de entrada. El tipo de retorno debe ser aceptable como entrada para binary_op
binary_op - objeto función binario FunctionObject que se aplicará en orden no especificado a los resultados de unary_op , los resultados de otros binary_op y init
Requisitos de tipo
-
InputIt debe cumplir con los requisitos de LegacyInputIterator .

Valor de retorno

Suma generalizada de init y unary_op ( * first ) , unary_op ( * ( first + 1 ) ) , ... unary_op ( * ( last - 1 ) ) sobre binary_op , donde la suma generalizada GSUM(op, a 1 , ..., a N ) se define de la siguiente manera:

  • si N = 1 , a 1 ,
  • si N > 1 , op(GSUM(op, b 1 , ..., b K ), GSUM(op, b M , ..., b N )) donde
  • b 1 , ..., b N puede ser cualquier permutación de a1, ..., aN y
  • 1 < K + 1 = M ≤ N

en otras palabras, los resultados de unary_op pueden agruparse y organizarse en orden arbitrario.

Complejidad

O(last - first) aplicaciones cada una de unary_op y binary_op .

Excepciones

  • Si la ejecución de una función invocada como parte del algoritmo lanza una excepción,
  • si policy es parallel_vector_execution_policy , std::terminate es llamado.
  • si policy es sequential_execution_policy o parallel_execution_policy , el algoritmo termina con una exception_list que contiene todas las excepciones no capturadas. Si solo había una excepción no capturada, el algoritmo puede relanzarla sin envolverla en exception_list . No está especificado cuánto trabajo realizará el algoritmo antes de retornar después de que se encontró la primera excepción.
  • si policy es de algún otro tipo, el comportamiento está definido por la implementación.
  • Si el algoritmo no puede asignar memoria (ya sea para sí mismo o para construir una exception_list al manejar una excepción de usuario), std::bad_alloc es lanzada.

Notas

unary_op no se aplica a init .

Si el rango está vacío, init se devuelve sin modificaciones.

  • Si policy es una instancia de sequential_execution_policy , todas las operaciones se realizan en el hilo que realiza la llamada.
  • Si policy es una instancia de parallel_execution_policy , las operaciones pueden realizarse en un número no especificado de hilos, con secuencias indeterminadas entre sí.
  • Si policy es una instancia de parallel_vector_execution_policy , la ejecución puede ser paralelizada y vectorizada: los límites del cuerpo de la función no se respetan y el código del usuario puede superponerse y combinarse de manera arbitraria (en particular, esto implica que un Callable proporcionado por el usuario no debe adquirir un mutex para acceder a un recurso compartido).

Ejemplo

transform_reduce puede utilizarse para paralelizar std::inner_product :

#include <boost/iterator/zip_iterator.hpp>
#include <boost/tuple.hpp>
#include <experimental/execution_policy>
#include <experimental/numeric>
#include <functional>
#include <iostream>
#include <iterator>
#include <vector>
int main()
{
    std::vector<double> xvalues(10007, 1.0), yvalues(10007, 1.0);
    double result = std::experimental::parallel::transform_reduce(
        std::experimental::parallel::par,
        boost::iterators::make_zip_iterator(
            boost::make_tuple(std::begin(xvalues), std::begin(yvalues))),
        boost::iterators::make_zip_iterator(
            boost::make_tuple(std::end(xvalues), std::end(yvalues))),
        [](auto r) { return boost::get<0>(r) * boost::get<1>(r); }
        0.0,
        std::plus<>()
    );
    std::cout << result << '\n';
}

Salida:

10007

Véase también

suma o pliega un rango de elementos
(function template)
aplica una función a un rango de elementos, almacenando resultados en un rango destino
(function template)
(parallelism TS)
similar a std::accumulate , excepto fuera de orden
(function template)