17

std::async を使用してプログラムを高速化しようとしています。関数があるとしましょう

T* f (const T& t1, const T& t2, const T& t3)

ここで、T はコピーにコストがかかる型です。異なる引数を持つ f のいくつかの独立した呼び出しがあり、ほぼ次のように std::async でそれらを並列化しようとします (ここで、m_futures は正しい型の先物の std::vector です)。

for (...) {
   m_futures.push_back (
       std::async(
           std::launch::async,
           f,
           a,b,c));
}

上記のコードにより、プログラムの実行が遅くなることがわかりました。私は gdb を使用してステップ実行し、future が作成されると、T のコピー コンストラクターが 3 回呼び出されます。何故ですか?引数 a,b,c はヒープに割り当てられていますが、コンパイラはそれを認識していないのでしょうか? どういうわけか明示的にすることはできますか?

const 参照で渡す必要がある場合でも、std::async が引数のコピーを作成するのは常に当てはまりますか? どうにかしてこれを回避することはできますか?私の素朴な考えでは、関数のさまざまな呼び出しに渡されるポインターがあるはずです(とにかくメモリからのみ読み取ります)。問題がある場合は、Linuxでgcc-4.6.3を使用しています。

4

1 に答える 1

21

参照のみを保存するのは安全ではありません。なぜなら、データ競合が存在しないことを保証するものは何もないからです (そして、@utapistim が悲しいことに削除された投稿で述べたように、より深刻なことに、オブジェクトの単なる存在も保証されません)。

コピーではなく参照が実際に必要で、これが正しいことに命を賭けて構わないと思っている場合は、単純に参照ラッパーを使用できます。

std::async(std::launch::async, f, std::cref(a), std::cref(b), std::cref(c))
于 2013-02-13T10:19:52.827 に答える