これら2つはどのように使い分ければいいのでしょうか。
通常のシングルスレッド逐次処理では、使い分けについて気にする必要はありません。その文脈において自然な方(イテレータペア指定 or 個数指定)を使えばよいでしょう。
第1引数に 実行ポリシーExecutionPolicy
をとるマルチスレッド並列処理に非ランダムアクセスイテレータ(前方向イテレータや双方向イテレータ)を指定するケースでは、std::for_each
関数 よりも std::for_each_n
関数 の方が効率的に処理を実行できる可能性があります。
std::for_each
走査対象範囲を複数スレッドにチャンク分割するとき、「要素総数の計算」が ランダムアクセスイテレータでは計算量 O(1) で済みますが、非ランダムアクセスイテレータでは計算量 O(N) を必要とします。std::for_each_n
ならばこの計算が必要ありません。
なぜ別の関数として追加されたのでしょうか。
std::for_each_n
は、C++17標準ライブラリに追加された「並列アルゴリズム」の一部として追加されました。
並列アルゴリズムは Thrustライブラリ として標準化を目指して検討されてきた経緯があり、当時からthrust::for_each
とthrust::for_each_n
の2種類が存在しました。
2012年頃のC++標準化提案文書 N3408 Parallelizing the Standard Algorithms Library には下記言及があります。要素数を指定する他の並列アルゴリズム(thrust::generate_n
など)の、実装を補助する道具としての側面があったようです。
5.1 std::for_each
versus thrust::for_each
and thrust::for_each_n
std::for_each
assumes the function object it receives contains state which will be mutated inside a serial loop. It returns a copy of this state as a result. std::for_each_n
does not exist.
By contrast, thrust::for_each
and thrust::for_each_n
instantiate many copies of their function object parameter in parallel. In such a setting, shared mutable state within the function object is a performance hazard at best. At worst, it is impossible for some parallel substrates to achieve. Instead, thrust::for_each
and thrust::for_each_n
exist exclusively for the sake of the side effects they may induce on the elements of their input ranges.
For consistency with other higher-level algorithms, thrust::for_each
and thrust::for_each_n
return the end of their input range. This simplifies the implementation of algorithms such as thrust::generate_n
which can be lowered onto thrust::for_each_n
in a straightforward manner.
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
2021/01/19 12:09
2021/01/19 12:23
2021/01/22 08:00