4

このリンクstd::function vs templateには、std::function のオーバーヘッドに関する素晴らしい議論があります。基本的に、std::function コンストラクターに渡すファンクターのヒープ割り当てによって発生する 10 倍のオーバーヘッドを回避するには、std::ref または std::cref を使用する必要があります。

参照によってラムダを std::function に渡す方法を示す @CassioNeri の回答からの例。

float foo(std::function<float(float)> f) { return -1.0f * f(3.3f) + 666.0f; }
foo(std::cref([a,b,c](float arg){ return arg * 0.5f; }));

現在、Intel スレッド ビルディング ブロック ライブラリは、以下の例に示すように、ラムダ/ファンクターを使用してループを並列評価する機能を提供します。

コード例:

#include "tbb/task_scheduler_init.h"
#include "tbb/blocked_range.h"
#include "tbb/parallel_for.h"
#include "tbb/tbb_thread.h"
#include <vector>

int main() {
 tbb::task_scheduler_init init(tbb::tbb_thread::hardware_concurrency());
 std::vector<double> a(1000);
 std::vector<double> c(1000);
 std::vector<double> b(1000);

 std::fill(b.begin(), b.end(), 1);
 std::fill(c.begin(), c.end(), 1);

 auto f = [&](const tbb::blocked_range<size_t>& r) {
  for(size_t j=r.begin(); j!=r.end(); ++j) a[j] = b[j] + c[j];    
 };
 tbb::parallel_for(tbb::blocked_range<size_t>(0, 1000), f);
 return 0;
}

私の質問は次のとおりです: Intel TBB parallel_for には、std::function で見られるのと同じ種類のオーバーヘッド (ファンクターのヒープ割り当て) がありますか? コードを高速化するために、std::cref を使用して parallel_for への参照によってファンクター/ラムダを渡す必要がありますか?

4

2 に答える 2

2

コードを高速化するために、std::cref を使用して parallel_for への参照によってファンクター/ラムダを渡す必要がありますか?

あなたの主な質問に対する答えがわかりません。しかし、 でそれを行うべきではないため、問題ではありませんtbb::parallel_for

カシオ・ネリが彼の答えで指摘したように:

最後に、ラムダの有効期間が std::function の有効期間を囲んでいることに注意してください。

それは彼が尋ねていた質問の状況にも当てはまりました。しかし、これは には当てはまりませんtbb::parallel_for。の全体的なポイントparallel_for、将来の任意の時点で他のスレッドから指定された関数を呼び出すことです。

参照によって何らかのファンクターを指定する場合は、このファンクターの有効期間が終了するまで続くことを確認する必要parallel_forがあります。そうしparallel_forないと、破棄されたオブジェクトへの参照を呼び出そうとする可能性があります。

良くないね。

したがって、どのようなオーバーヘッドが発生しても、参照で修正することはできません。

于 2013-09-01T01:13:48.120 に答える