std::experimental::parallel:: transform_reduce
|
ヘッダー
<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) |
範囲
[
first
,
last
)
内の各要素に
unary_op
を適用し、その結果(順序不同かつ未規定の方法で集約される可能性あり)を初期値
init
と共に
binary_op
を用いて縮約します。
binary_op が結合的または可換的でない場合、動作は非決定的となります。
unary_op
または
binary_op
が
[
first
,
last
)
内のいずれかの要素を変更するか、イテレータを無効化する場合、動作は未定義です。
目次 |
パラメータ
| first, last | - | アルゴリズムを適用する要素の範囲 |
| init | - | 一般化された合計の初期値 |
| policy | - | 実行ポリシー |
| unary_op | - | 入力範囲の各要素に適用される単項 FunctionObject 。戻り値の型は binary_op への入力として受け入れ可能でなければならない |
| binary_op | - | 指定されない順序で unary_op の結果、他の binary_op の結果、および init に適用される二項 FunctionObject |
| 型要件 | ||
-
InputIt
は
LegacyInputIterator
の要件を満たさなければならない
|
||
戻り値
init と unary_op ( * first ) 、 unary_op ( * ( first + 1 ) ) 、...、 unary_op ( * ( last - 1 ) ) の一般化された和を binary_op 上で計算します。 ここで一般化された和 GSUM(op, a 1 , ..., a N ) は以下のように定義されます:
- if N = 1 , a 1 ,
- if N > 1 , op(GSUM(op, b 1 , ..., b K ), GSUM(op, b M , ..., b N )) where
-
- b 1 , ..., b N は a1, ..., aN の任意の順列であり、
- 1 < K + 1 = M ≤ N
言い換えれば、 unary_op の結果は任意の順序でグループ化および配置される可能性があります。
計算量
O(last - first) 回の unary_op および binary_op の各適用。
例外
- アルゴリズムの一部として呼び出された関数の実行が例外をスローした場合、
-
-
policyがparallel_vector_execution_policyの場合、 std::terminate が呼び出される。 -
policyがsequential_execution_policyまたはparallel_execution_policyの場合、 このアルゴリズムは捕捉されなかった全ての例外を含む exception_list で終了する。捕捉されなかった例外が一つだけの場合、アルゴリズムはexception_listでラップせずにその例外を再スローする場合がある。 最初の例外が発生した後にアルゴリズムが返される前に実行する作業量は未規定である。 -
policyがその他の型の場合、動作は実装定義である。
-
-
アルゴリズムがメモリの割り当てに失敗した場合(自身のため、またはユーザー例外を処理する際に
exception_listを構築するため)、 std::bad_alloc がスローされます。
注記
unary_op は init には適用されません。
範囲が空の場合、 init が変更されずに返されます。
-
policyがsequential_execution_policyのインスタンスである場合、すべての操作は呼び出し元スレッドで実行されます。 -
policyがparallel_execution_policyのインスタンスである場合、操作は未指定の数のスレッドで実行され、互いに非決定的な順序で実行される可能性があります。 -
policyがparallel_vector_execution_policyのインスタンスである場合、実行は並列化とベクトル化の両方が行われる可能性があります:関数本体の境界は考慮されず、ユーザーコードは任意の方法で重複および結合される可能性があります(特に、これによりユーザー提供のCallableは共有リソースにアクセスするためにミューテックスを取得してはならないことを意味します)。
例
transform_reduceは 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'; }
出力:
10007
関連項目
|
要素の範囲を合計または畳み込む
(関数テンプレート) |
|
|
要素の範囲に関数を適用し、結果を宛先範囲に格納する
(関数テンプレート) |
|
|
(parallelism TS)
|
std::accumulate
と類似しているが、順不同で実行される
(関数テンプレート) |