gprof を使用して C++ コードのプロファイリングを行ったところ、時間のかなりの部分が 1 つの仮想メソッドを何度も呼び出すことに費やされていることがわかりました。メソッド自体は短く、仮想でない場合はおそらくインライン化できます。
仮想にならないようにすべて書き直す以外に、これを高速化する方法は何ですか?
gprof を使用して C++ コードのプロファイリングを行ったところ、時間のかなりの部分が 1 つの仮想メソッドを何度も呼び出すことに費やされていることがわかりました。メソッド自体は短く、仮想でない場合はおそらくインライン化できます。
仮想にならないようにすべて書き直す以外に、これを高速化する方法は何ですか?
時間はすべて通話に関連していますか? コストがあるのは関数自体でしょうか?この場合、単純にインライン化すると、関数がプロファイラーから消えてしまう可能性がありますが、速度はあまり向上しません。
それが実際に非常に多くの仮想呼び出しを行うオーバーヘッドであると仮定すると、物事を非仮想化せずにできることには限界があります。
コールに時間やフラグなどのアーリー アウトがある場合は、2 レベルのアプローチを使用することがよくあります。チェックは非仮想呼び出しでインライン化され、クラス固有の動作は必要な場合にのみ呼び出されます。
例えば
class Foo
{
public:
inline void update( void )
{
if (can_early_out)
return;
updateImpl();
}
protected:
virtual void updateImpl( void ) = 0;
};
実際の関数呼び出しに費やされた時間ですか、それとも関数自体に費やされた時間ですか?
仮想関数呼び出しは、追加の逆参照を必要とするため、非仮想呼び出しよりも著しく遅くなります。(毛むくじゃらの詳細をすべて読みたい場合は、「vtable」を Google で検索してください。)更新:ウィキペディアの記事はこれに関して悪くないことがわかりました。
ただし、ここで「著しく」とは、いくつかの命令を意味します。呼び出された関数で費やされた時間を含めて、計算全体のかなりの部分を消費している場合は、非仮想化とインライン化を検討するのに最適な場所のように思えます。
しかし、20 年近く C++ を使用してきましたが、これが実際に起こるのを見たことはないと思います。コードを見てみたいです。
仮想呼び出しが本当にボトルネックである場合は、CRTPを試してください。
C++ のシンタックス シュガーが利用できない場合、古き良き 'C' でコードを記述する方法を検討することが有益な場合があります。答えが間接呼び出しを使用していない場合があります。例については、この回答を参照してください。