std::experimental::parallel::transform_reduce
| Definiert im Header <experimental/numeric> |
||
| template< class InputIt, class UnaryOp, class T, class BinaryOp > T transform_reduce( InputIt first, InputIt last, |
(1) | (parallelism TS) |
| template< class ExecutionPolicy, class InputIt, class UnaryOp, class T, class BinaryOp > |
(2) | (parallelism TS) |
Wendet unary_op auf jedes Element im Bereich [first, last) an und reduziert die Ergebnisse (möglicherweise permutiert und auf nicht spezifizierte Weise aggregiert) zusammen mit dem Anfangswert init über binary_op.
Das Verhalten ist nicht deterministisch, wenn binary_op nicht assoziativ oder nicht kommutativ ist.
Das Verhalten ist undefiniert, wenn unary_op oder binary_op ein Element modifiziert oder einen Iterator in [first, last) ungültig macht.
Inhalt |
[edit] Parameter
| first, last | - | der Bereich der Elemente, auf die der Algorithmus angewendet wird |
| init | - | der Anfangswert der generalisierten Summe |
| policy | - | die Ausführungsrichtlinie |
| unary_op | - | unäre FunctionObject, die auf jedes Element des Eingabebereichs angewendet wird. Der Rückgabetyp muss als Eingabe für binary_op akzeptabel sein. |
| binary_op | - | binäre FunctionObject, die in nicht spezifizierter Reihenfolge auf die Ergebnisse von unary_op, die Ergebnisse anderer binary_op und init angewendet wird. |
| Typanforderungen | ||
-InputIt muss die Anforderungen von LegacyInputIterator erfüllen. | ||
[edit] Rückgabewert
Verallgemeinerte Summe von init und unary_op(*first), unary_op(*(first + 1)), ... unary_op(*(last - 1)) über binary_op, wobei die verallgemeinerte Summe GSUM(op, a1, ..., aN) wie folgt definiert ist:
- wenn N = 1, a1,
- wenn N > 1, op(GSUM(op, b1, ..., bK), GSUM(op, bM, ..., bN)) wobei
- b1, ..., bN eine beliebige Permutation von a1, ..., aN sein kann und
- 1 < K + 1 = M ≤ N
mit anderen Worten, die Ergebnisse von unary_op können beliebig gruppiert und angeordnet werden.
[edit] Komplexität
O(last - first) Anwendungen von unary_op und binary_op.
[edit] Ausnahmen
- Wenn die Ausführung einer Funktion, die im Rahmen des Algorithmus aufgerufen wird, eine Ausnahme auslöst,
- wenn
policyparallel_vector_execution_policyist, wird std::terminate aufgerufen. - wenn
policysequential_execution_policyoderparallel_execution_policyist, wird der Algorithmus mit einer exception_list beendet, die alle nicht abgefangenen Ausnahmen enthält. Wenn nur eine nicht abgefangene Ausnahme vorlag, kann der Algorithmus diese erneut auslösen, ohne sie inexception_listzu verpacken. Es ist nicht spezifiziert, wie viel Arbeit der Algorithmus ausführt, bevor er nach Auftreten der ersten Ausnahme zurückkehrt. - wenn
policyein anderer Typ ist, ist das Verhalten implementierungsabhängig.
- wenn
- Wenn der Algorithmus keinen Speicher zuweisen kann (weder für sich selbst noch zum Erstellen einer
exception_listbei der Behandlung einer Benutzerausnahme), wird std::bad_alloc ausgelöst.
[edit] Hinweise
unary_op wird nicht auf init angewendet.
Wenn der Bereich leer ist, wird init unverändert zurückgegeben.
- Wenn
policyeine Instanz vonsequential_execution_policyist, werden alle Operationen im aufrufenden Thread ausgeführt. - Wenn
policyeine Instanz vonparallel_execution_policyist, können Operationen in einer nicht spezifizierten Anzahl von Threads ausgeführt werden, die indeterminate zueinander sequenziert sind. - Wenn
policyeine Instanz vonparallel_vector_execution_policyist, kann die Ausführung sowohl parallelisiert als auch vektorisiert werden: Funktionsgrenzen werden nicht beachtet, und Benutzercode kann auf willkürliche Weise überlappt und kombiniert werden (insbesondere bedeutet dies, dass ein bereitgestelltes Callable kein Mutex erwerben darf, um auf eine gemeinsam genutzte Ressource zuzugreifen).
[edit] Beispiel
transform_reduce kann verwendet werden, um std::inner_product zu parallelisieren.
#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'; }
Ausgabe
10007
[edit] Siehe auch
| summiert oder faltet eine Reihe von Elementen (Funktionstemplate) | |
| Wendet eine Funktion auf einen Elementbereich an und speichert die Ergebnisse in einem Zielbereich (Funktionstempelat) | |
| (parallelism TS) |
ähnlich wie std::accumulate, aber nicht-sequenziell (Funktionvorlage) |