6

私はgoで簡単なエミュレーターを書いています(私はすべきですか?それともcに戻るべきですか?)。とにかく、私は命令をフェッチしてデコードしています。この時点で、私は0x81のようなバイトを持っており、正しい関数を実行する必要があります。

私はこのようなものを持っている必要があります

func (sys *cpu) eval() {
    switch opcode {
    case 0x80:
        sys.add(sys.b)
    case 0x81:
        sys.add(sys.c)
    etc
    }
}

またはこのようなもの

var fnTable = []func(*cpu) {
    0x80: func(sys *cpu) {
        sys.add(sys.b)
    },
    0x81: func(sys *cpu) {
        sys.add(sys.c)
    }
}
func (sys *cpu) eval() {
    return fnTable[opcode](sys)
}

1.どちらが良いですか?
2.どちらが速いですか?
また
、3。関数をインラインで宣言できますか?
4.cpu struct私はレジスターなどを持っているのですが、レジスターとすべてをグローバルとして持っているともっと速くなりますか?(なしstruct

どうもありがとうございます。

4

3 に答える 3

16

私はいくつかのベンチマークを行いましたが、約4つ以上のケースがあると、テーブルバージョンはスイッチバージョンよりも高速になります。

Goコンパイラ(gc、とにかく、gccgoについてはよくわかりません)が、高密度スイッチをジャンプテーブルに変えるほど賢くないように思われることに驚きました。

更新:Ken ThompsonがGoメーリングリストに投稿し、スイッチの最適化の難しさを説明しています。

于 2012-03-30T02:19:10.400 に答える
3
  1. 最初のバージョンは私には良く見えます、YMMV。

  2. それをベンチマークします。コンパイラが最適化にどれだけ優れているかによって異なります。コンパイラが最適化するのに十分な努力をしない場合、「ジャンプテーブル」バージョンの方が高速になる可能性があります。

  3. 「関数をインラインで宣言する」とは何かの定義によって異なります。Goは、トップレベルでのみ関数/メソッドを宣言および定義できます。しかし、関数はGoの第一級市民であるため、変数/パラメーター/戻り値と関数型の構造化型を持つことができます。このすべての場所で、関数リテラルを変数/フィールド/要素に割り当てることができます...

  4. おそらく。それでも、CPUの状態をグローバル変数に保持しないことをお勧めします。マルチコアをエミュレートすることにした場合は、大歓迎です;-)

于 2012-03-29T15:35:31.963 に答える
0

ある式のastがあり、それを大量のデータ行に対して評価したい場合は、それをラムダのツリーに1回だけコンパイルし、各反復でスイッチをまったく計算しないでください。

たとえば、次のように与えられます。{* (a, {+ (b, c)})}

コンパイル関数(非常に大まかな疑似言語)は次のようになります。

func (e *evaluator) compile(brunch ast) {
    switch brunch.type {
    case binaryOperator:
        switch brunch.op {
        case *: return func() {compile(brunch.arg0) * compile(brunch.arg1)}
        case +: return func() {compile(brunch.arg0) + compile(brunch.arg1)}
        }
    case BasicLit: return func() {return brunch.arg0}
    case Ident: return func(){return e.GetIdent(brunch.arg0)} 
    }
}

したがって、最終的にcompileはfuncを返します。これは、データの各行で呼び出す必要があり、スイッチやその他の計算機能はまったくありません。さまざまなタイプのデータを使用した操作についての質問が残っています。これは、独自の調査用です;)ジャンプテーブルメカニズムが利用できない状況では、これは興味深いアプローチです:)しかし、確かに、func呼び出しはより複雑な操作です。ジャンプ。

于 2016-05-13T12:17:29.813 に答える