1

オブジェクトmemoryには署名付きのメソッドがあります

BinaryPattern const& getPattern(unsigned int index) const;

これを次の for ループで使用しています。

for (unsigned int k = 0; k < memory->size(); k++) {
    const BinaryPattern s = memory->getPattern(k);
    w += s.at(i) * s.at(j);
}

これは非常に遅いです。驚いたことに、次のほうがはるかに高速であることがわかりました。

for (unsigned int k = 0; k < memory->size(); k++) {
    w += memory->getPattern(k).at(i) * memory->getPattern(k).at(j);
}

「getPattern()」は計算を行わず、ベクトルに格納されているパターンを返すだけです。

参照を変数に格納すると、なぜこんなに遅くなるのでしょうか? 参照を2回取得すると遅くなると予想していたので、最初はこれを高速化するために行いました。

4

3 に答える 3

9

その理由は

const BinaryPattern s = memory->getPattern(k);

コピー コンストラクターを呼び出して、オブジェクトのコピーを作成します。変更したくないので、代わりに参照を保存します。

const BinaryPattern& s = memory->getPattern(k);
//                 ^
//                 note this

(参照を使用して右辺値をキャプチャすると、const参照が終了するまで右辺値の有効期間が延長getPattern()されるため、参照ではなくコピーを返すように署名が変更された場合でも、これは機能します。)


最適化されたビルド (デバッグ ビルドを比較していませんよね?) では、コンパイラは関数への 2 つの呼び出しが

memory->getPattern(k).at(i) * memory->getPattern(k).at(j)

副作用がないため、最初の呼び出しで取得したオブジェクトへの参照を保持し、2 番目の呼び出しを最適化して、上記で提案したコードに到達します。

明らかに、オブジェクトをコピーするコストはBinaryPattern無視できません。

于 2012-08-15T13:27:03.220 に答える
3

ここでコピーを作成しているため

const BinaryPattern s = memory->getPattern(k);

に変更するだけ

const BinaryPattern &s = memory->getPattern(k);
于 2012-08-15T13:27:21.837 に答える
3

ラインで

const BinaryPattern s = memory->getPattern(k);

の新しいインスタンスBinaryPatternが作成され、 の戻り値がgetPatternそれにコピーされます。

あなたはおそらく意味した

const BinaryPattern& s = memory->getPattern(k);
于 2012-08-15T13:27:25.580 に答える