Указатель на элемент в двумерном массиве замедляет код

У меня есть этот кусок кода, который получает доступ к некоторой информации о точке на осях «х» и «у». Эта информация позже используется для рисования некоторых точек на экране.
Вот как работает код:

//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;
}

Идея мне кажется совершенно прекрасной, но проблема в том, что первый кусок кода быстрее, чем второй!
Итак, мой вопрос: почему первый фрагмент кода быстрее, чем второй?

Для тех, кто не любит читать:

Почему первый фрагмент кода быстрее, чем другой?
Первый занимает 0,0919 секунды, а второй занимает 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

кроме этой части кода, остальное идентично.

0

Решение

Глядя только на сборку, мы видим дополнительный mov (присваивание y_dptr).
Видя, как это делается на каждой итерации в (внешнем) цикле, и нет никаких других отличий в коде, это может стать причиной снижения производительности.
Кроме этого, в вашем коде нет ничего такого, что могло бы использовать магию указателя, которую вы пытаетесь использовать.
F.E. Вы используете dptr = (y_dptr + y); где вы можете потерять dptr или y_dptr, используя приращение к указателю напрямую (y_dptr ++;).
Это некоторая арифметическая магия указателей, которую вы не используете и которую можно улучшить.

0

Другие решения

Других решений пока нет …

По вопросам рекламы [email protected]