5

パフォーマンス上の理由から、仮想関数を回避するために、不思議なことに繰り返し発生するテンプレートパターンを使用しています。何百万回も実行する小さなコマンドがたくさんあります。これをコマンドパターンに適合させようとしています。キューに大量のコマンドを追加してから、それらを繰り返し実行して、それぞれを1つずつ実行したいと思います。各コマンドは、仮想機能を回避するためにCRTPを使用します。私が遭遇している問題は、コマンドパターンが通常ポインターのベクトルを使用して実装されていることです。ただし、Commandクラスがテンプレート化されている場合、汎用Commandポインターを渡すのは困難になります。私はC++の専門家ではないので、テンプレート化されたコマンドオブジェクトのベクトルを格納する明白な方法があるのではないでしょうか。私は次のようなものを使おうとしています:

boost:ptr_vector commands;
AddCommand(Command* command) {
  commands.push_back(command);
}

問題はCommand型ではないためCommand* command、コンパイルエラーが発生します。を使用するCommand<CommandType>必要がありますが、さまざまな種類のコマンドを保持するためのキューが必要なため、それは機能しません。

ソリューションのアイデアはありますか?それとも、仮想関数は私の唯一の選択肢ですか?

追加:コマンドオブジェクトは、モンテカルロシミュレーションアルゴリズムの一部です。つまり、Commandは正規分布からの乱数であり、正規分布のパラメーターはクラスの一部です。したがって、コマンドパターンは非常にうまく適合します。状態を維持する必要のある関数に対して、特定の順序で多くの呼び出しがあります。

4

3 に答える 3

12

CRTP は、コンパイラが関数呼び出しをインライン化できるように、コンパイル時にオブジェクトの実行時の型を解決することによってその魔法を行います。ジェネリック型へのポインターのベクトルがある場合、コンパイラーは特定の具象型を判別できず、コンパイル時の解決を行うことができません。

質問にある情報だけから、仮想機能が最良の選択肢だと思います。ただし、仮想関数はそれほど遅くはありません。確かに、それらはインライン関数よりも遅いですが、多くの場合、十分に高速です! 特に、プロセスが処理時間ではなく I/O 時間に制限されている場合。

この質問の回答の 1 つに、この問題に関する詳細な議論があります。要約すると、仮想関数呼び出しのオーバーヘッドはおそらくナノ秒単位で測定されます。それよりも複雑ですが、重要なのは、関数が単一の割り当てのような本当に些細なことをしている場合を除き、仮想関数を恐れてはならないということです。コマンドが小さいとおっしゃっていたので、その通りなのかもしれません。仮想関数を使用して簡単なプロトタイプを作成し、許容できるパフォーマンスが得られるかどうかを確認します。

于 2009-06-11T00:27:54.257 に答える
2

コンパイル時にコマンド キューを作成しない限り、目的は達成できません。

于 2009-06-11T00:33:31.360 に答える
1

コマンド キューが頻繁に変更されるか、めったに変更されないかはわかりません。

実行される頻度に比べてめったに変更されない場合、これはコード生成の仕事である可能性があるように思えます。

必要なアクションを実行するプログラムを印刷し、オンザフライで dll をコンパイルしてリンクし、ロードするだけです。これには約 1 秒かかります。クラス、オブジェクト、またはディスパッチはありません。そして、それをシングルステップすると、答えに実質的に寄与しないサイクルはほとんど見られません.

于 2009-06-12T11:24:17.470 に答える