2009-08-26 10 views
0

パフォーマンス関数の観点から分岐関数呼び出しの最適な実装は何ですか?分岐最適化

単純なケースでは、バイトコードを解釈し、コードに応じて関数呼び出しを実行するかなり大きなswitch文があります。

普通のケースでは、同じことをするgotosとラベルを計算しました。

これを行うための最善の方法は何ですか?

抽象たとえば、

 
schedule: 
    swap_entity(); 
    goto *entity_start(); 

lb_code1: 
    do_stuff(); 
    goto *next_code_item(); 

lb_code2: 
    do_stuff(); 
    goto *next_code_item(); 

... 

編集:への私の参照おそらくやや誤った「分岐関数が呼び出されます」。分岐コード実行。

+1

AFAIKは、JITコンパイルよりも優れています。理想的には、ランタイム情報を使用して不必要なコードをすべて削除する最適化があります。 しかし、基本的には、「絶対ベスト」。 Pfft。決してそれを見たことはない。 – gimpf

+0

コンパイル(コード生成、JITなど)が「絶対的にベスト」であることに合意しました。関数ポインタの配列へのインデックス付けは、opsがすべて同じ型を持つ場合に機能します。 –

+0

絶対最善の言葉はおそらく愚かではあるが、「より速い方法」がより正確になるだろう。 – psyeugenic

答えて

1

ここでスピードブーストをお探しなら、他のバイトコードディスパッチ機構を見てください。 a question which sort-of asked that beforeがありました。

基本的には、毎回間違って予測されている可能性の高いgotoがあり、その後に関数呼び出しがあります。 direct threadingのようなテクニックでは、インタプリタのオーバーヘッドを大幅に減らすことができます。 Inline threadingはより困難ですが、大きなメリットがあります。

私はいくつかの他の質問でfurther resourcesを与えました。

3

たぶん、関数ポインタの配列は、推測で:

void dispatch(Message* message) 
{ 
    //MessageType is a finite enum 
    MessageType messageType = message->messageType; 
    int index = (int)messageType; 
    //there's an array element for each enum value 
    FunctionPointer functionPointer = arrayOfFunctionPointers[index]; 
    (*functionPointer)(message); 
} 

実際の答えは、ハードウェアに依存しており、問題の大きさとCPUのキャッシュのようなものに依存します。

+0

自分の啓発のために、メッセージのデータ型は何ですか?私は覚えていないので尋ねます - > Cの中にいること。 – CAbbott

+0

"メッセージ"を "ユーザー定義型"の例として与えています。この仮想構造体にはいくつかのフィールドがあり、そのうちの1つはmessageTypeという名前で、タイプはMessageTypeであり、ユーザー定義の列挙型です。 '' - > ''は '' * '"と一緒に行き、インスタンスではなく値ではなくポインタで渡されます。 – ChrisW

+0

@Chris - explainationのおかげで、 ' - >'構文が導入されたときを思い出すことができなかった、私はそれがC++の導入だと思った(つまり、message-> messageTypeと(* message)).messageType – CAbbott

2

です。いくつかのテーブル駆動型アプローチは、通常は最速ですが、スイッチのステートメントがどのように実装されているのかが分かります。確かに、あなたは はこのエリアの任意の推奨事項は、 からSOユーザーが読んでいないとする必要があります。何か提案があれば、それを実装し、すべてのコンパイラの最適化を有効にしてビルドのパフォーマンスを測定する必要があります。