0

「x」軸と「y」軸上のポイントに関する情報にアクセスするこのコードがあります。この情報は、後で画面に点を描画するために使用されます。コードの仕組みは次のとおりです。

//MAX_X_COORD has a value of 169 
//MAX_Y_COORD has a value of 55
void RedrawFromDATAtable() 
{
    COORD pos;
    HANDLE tmpbuf = CreateConsoleScreenBuffer(GENERIC_WRITE , NULL, NULL, CONSOLE_TEXTMODE_BUFFER, NULL);
    WriteConsoleA(tmpbuf, " ", 1, NULL, NULL);
    if(SetConsoleActiveScreenBuffer(tmpbuf)==0)
    {MessageBoxA(NULL, "ERROR", "ERROR", 0);return;}
    bufferdata_ex *  dptr;
    //bufferdata_ex * y_dptr;
    int  * lcol(new int); //Increases speed by reducing function calls - Experienced about twice as fast drawing!

for(short x=0;x<MAX_X_COORD;x++)
    {
        //y_dptr = bridge->DATA[x];
        for(short y=0;y<MAX_Y_COORD;y++) 
        {

            //dptr = (y_dptr+y); //Rewrite to use a constant pointer!
            dptr = &(_bridge->DATA[x][y]);
            if(dptr->InUse==true)
            {
            {
                pos.X = x;
                pos.Y = y;
                SetConsoleCursorPosition(output, pos);
                //haschanged = false;
            }
            if(!(*lcol==dptr->color)) //Need for a new color?
            {   SetConsoleTextAttribute(output, dptr->color);lcol = &dptr->color;}

            char c((char)dptr->sym);
            WriteConsoleA(output, &c, 1, NULL, NULL);
                lcol = &dptr->color;
            }

        }

    }
SetConsoleTextAttribute(output, bridge->current_color);
SetConsoleCursorPosition(output, last_mouse_position);
SetConsoleActiveScreenBuffer(output);
CloseHandle(tmpbuf);
delete lcol;
}

ケースにカット!

大丈夫!そのため、最近、そのような配列にアクセスするとコードが遅くなると考えました。私の知る限り、配列内の要素にアクセスするたびに、プロセッサは配列のベースアドレスを取得し、そこから要素のサイズに、指定された要素のアドレスを見つけるために使用されるインデックスを掛けます。ここでの私の考えは、アドレスへのポインターを作成するだけでなく、それを使用して要素を処理するのではなく、プロセッサーにそれを複数回実行させると、コードが遅くなるということでした。そこで、コードを次のように書き直しました。

void RedrawFromDATAtable() 
{
    COORD pos;
    HANDLE tmpbuf = CreateConsoleScreenBuffer(GENERIC_WRITE , NULL, NULL, CONSOLE_TEXTMODE_BUFFER, NULL);
    WriteConsoleA(tmpbuf, " ", 1, NULL, NULL);
    if(SetConsoleActiveScreenBuffer(tmpbuf)==0)
    {MessageBoxA(NULL, "ERROR", "ERROR", 0);return;}
    bufferdata_ex *  dptr;
    bufferdata_ex * y_dptr;
    int  * lcol(new int); //Increases speed by reducing function calls - Experienced about twice as fast drawing!

for(short x=0;x<MAX_X_COORD;x++)
    {
        y_dptr = _bridge->DATA[x];
        for(short y=0;y<MAX_Y_COORD;y++) 
        {

            dptr = (y_dptr+y); //Rewrite to use a constant pointer!
            //dptr = &(bridge->DATA[x][y]);
            if(dptr->InUse==true)
            {
            {
                pos.X = x;
                pos.Y = y;
                SetConsoleCursorPosition(output, pos);
                //haschanged = false;
            }
            if(!(*lcol==dptr->color)) //Need for a new color?
            {   SetConsoleTextAttribute(output, dptr->color);lcol = &dptr->color;}

            char c((char)dptr->sym);
            WriteConsoleA(output, &c, 1, NULL, NULL);
                lcol = &dptr->color;
            }

        }

    }
SetConsoleTextAttribute(output, bridge->current_color);
SetConsoleCursorPosition(output, last_mouse_position);
SetConsoleActiveScreenBuffer(output);
CloseHandle(tmpbuf);
delete lcol;
}

このアイデアは私にはまったく問題ないように思えますが、問題は、最初のコードが 2 番目のコードよりも高速であることです。だから私の質問は、最初のコードが2番目のコードよりも速いのはなぜですか?

読むのが苦手な方へ:

最初のコードが他のコードよりも速いのはなぜですか? 最初のものは終了するのに 0.0919 秒かかり、2 番目のものは 0.226 秒かかります。

また、これはアセンブリがポインターを処理する方法のコピーです。

    //No pointers
dptr = &(bridge->DATA[x][y]);
001B41C6  mov         eax,dword ptr [this]  
001B41C9  mov         ecx,dword ptr [eax+14h]  
001B41CC  movsx       edx,word ptr [x]  
001B41D0  imul        edx,edx,370h  
001B41D6  lea         eax,[ecx+edx+1D4h]  
001B41DD  movsx       ecx,word ptr [y]  
001B41E1  shl         ecx,4  
001B41E4  add         eax,ecx  
001B41E6  mov         dword ptr [dptr],eax  


//With pointers
//Pointing to DATA[x]
012C41A5  mov         eax,dword ptr [this]  
012C41A8  mov         ecx,dword ptr [eax+14h]  
012C41AB  movsx       edx,word ptr [x]  
012C41AF  imul        edx,edx,370h  
012C41B5  lea         eax,[ecx+edx+1D4h]  
012C41BC  mov         dword ptr [y_dptr],eax 


//Pointing to DATA[x]+y
012C41E0  movsx       eax,word ptr [y]  
012C41E4  shl         eax,4  
012C41E7  add         eax,dword ptr [y_dptr]  
012C41EA  mov         dword ptr [dptr],eax  

コードのこの部分以外は同じです。

4

1 に答える 1

0

アセンブリだけを見ると、追加の mov (y_dptr の割り当て) が表示されます。
(外側の) ループのすべての反復でこれがどのように行われるかを確認し、コードに他の違いがないことを確認すると、これがパフォーマンス低下の理由になる可能性があります。
それ以外には、使用しようとしているポインター マジックを利用するコードは実際には何もありません。
fe dptr = (y_dptr+y); を使用します。ポインターでインクリメントを直接使用することで、dptr または y_dptr のいずれかを失う可能性があります (y_dptr++;)。
これは、使用していないポインター演算マジックであり、改善される可能性があります。

于 2013-06-09T20:15:45.410 に答える