2012-03-20 3 views
0

私はハックCPUエミュレータを作っていますが、出力を計算する最良の方法は何か不思議でした。一度に1ステップずつ結果を計算するよりも、出力計算を読めない1行に集約する方が効率的ですか?コンパイラは両方のオプションがうまくいくように最適化しますか?基本的には、これらのどれがより効率的である -論理式の計算に最適なオプションは?

この:

 
    word HackALU(word x, word y, bool zx, bool nx, bool zy, bool ny, bool f, bool no) 
    { 
     x = zx ? 0 : x; 
     y = zy ? 0 : y; 

     x = nx ? ~x : x; 
     y = ny ? ~y : y; 

     word result = f ? x + y : x & y; 

     return no ? ~result : result;  
    } 

またはこの:

 
    word HackALU(word x, word y, bool zx, bool nx, bool zy, bool ny, bool f, bool no) 
    { 
     return no ? ~(f ? ((nx ? ~(zx ? 0 : x) : (zx ? 0 : x)) + (ny ? ~(zy ? 0 : y) : (zy ? 0 : y))) : ((nx ? ~(zx ? 0 : x) : (zx ? 0 : x)) & (ny ? ~(zy ? 0 : y) : (zy ? 0 : y)))) : (f ? ((nx ? ~(zx ? 0 : x) : (zx ? 0 : x)) + (ny ? ~(zy ? 0 : y) : (zy ? 0 : y))) : ((nx ? ~(zx ? 0 : x) : (zx ? 0 : x)) & (ny ? ~(zy ? 0 : y) : (zy ? 0 : y)))); 
    } 
+0

によって決定的に速くなり、その場合、分岐予測(例えばPS3のSPU)を、持っていないものは表示されません。同じコードにする。たとえば、nxは上の例ではまったく使用されていませんが、下位のコードブロックの結果に影響するようです。 –

+0

私はタイプミスをしました。今修正されているので、同じ結果が得られるはずです。 – Avi

答えて

1

良い近代的なコンパイラは、最も可能性の両方に同じコードを生成します。このループを使用して

+0

これは知っておきたいことです。最初は実際にはメモリに「結果」という単語を保存するという意味でより多くのメモリを使用するためです。コンパイラはそのステップを排除するでしょうか? – Avi

+1

x86上でgcc 3.3.4で最適化レベル1,2,3を使って 'HackALU()'をコンパイルすると、スタック上に 'result'のためにメモリ変数が予約されていません。すべてがレジスタで行われます。あなた自身のために見てください: 'gcc -c -O -S -o '。 –

+0

すごく、私の質問に答える。 – Avi

0

、私は実際に速いとトップバージョンを示しています。

int n = 0; //optimization busting counter 
clock_t start = clock(); 
    for(word x=0; x<1000; ++x) { 
    for(word y=0; y<1000; ++y) { 
     for(int b = 0; b < 64; ++b) { 
      n += HackALU(x,y,b&0x1,b&0x2,b&0x4,b&0x8,b&0x10,b&0x20); 
} } } 
clock_t end = clock(); 
printf("finished, elapsed ticks = %d, n = %d\n", end - start, n); 

それは私がそれをより速くだろう作ると思う...オプティマイザは本当に良いですしない限り、トップのバージョンは以下の手順になりますかなり明白です分岐を減らすか、分岐を正確に予測する必要があります。

1

論理変更は、一時的なスペースの空白/記憶ではなく、コードのパフォーマンスに大きな影響を与えます。

例えば、いくつかのマシンがあなたのコードは、数学的な操作で枝を交換

word HackALU(word x, word y, bool zx, bool nx, bool zy, bool ny, bool f, bool no) 
{ 
    x = (zx == 0) * x; // [0 or 1] * x; 
    y = (zy == 0) * y; 

    x -= (nx != 0) * 2 * x; 
    y -= (ny != 0) * 2 * x; 

    word result = (f != 0) * (x + y) + (f == 0) * (x & y); 

    return (no != 0) * ~result + (no == 0) * result;  
}