» Программистские штучки : Берлога инженера - бесплатные программы - стереофото - справочные материалы - обои для рабочего стола


Программистские штучки

Недавно перечитывал книгу господина Алена И.Голуба “С&C++ правила программирования”. Автор пишет, что в C арифметика указателей выполняется быстрее, нежели обращение к данным по индексу массива. В качестве примера приводится следующий код


struct aaa {
int a;
int b;
int c;
};

aaa arr[3][5];

int i,j;

for(i=0; i<3; i++)
for(j=0; i<5; i++)
arr[i][j].a = 6; // Здесь неоптимально

и как альтернатива


struct aaa {
int a;
int b;
int c;
};

aaa arr[3][5];

aaa *ptr = arr;
int i = 3*5;

while(–i>=0)
(ptr++)->a = 6;

Автор пишет, что в первом случае при обращении к элементам массива выполняется два умножения и одно сложение, что не есть оптимально.

Ради интереса я откомпилировал оба примера под MS VC 2005 Beta 2. Вот что у меня получилось.

Без оптимизации исследуемый фрагмент первого примера пример выглядит так


00411366 mov eax,dword ptr [i]
0041136C imul eax,eax,3Ch
0041136F lea ecx,arr[eax]
00411376 mov edx,dword ptr [j]
0041137C imul edx,edx,0Ch
0041137F mov dword ptr [ecx+edx],6

Видим честные два умножения и сложение.

Однако при оптимизации код превращается в нечто следующее


00401008 cmp edx,5
0040100B jge wmain+2Eh (40102Eh)
0040100D mov eax,edx
0040100F shl eax,4
00401012 sub eax,edx
00401014 lea ecx,[esp+eax*4]
00401017 mov eax,5
0040101C sub eax,edx
0040101E add edx,eax
arr[i][j].a = 6;
00401020 mov dword ptr [ecx],6
00401026 add ecx,3Ch
00401029 sub eax,1
0040102C jne wmain+20h (401020h)

Здесь вычисление адреса элемента массива размазано по коду наряду с обработкой параметров, надо сказать, не слишком оптимальных циклов for, однако умножений нет.

Конечно, откомпилированный код второго примера будет несколько компактнее ввиду более простого цикла и быстрее из-за меньшего количества ветвлений, но это будет заметно только в экстремальных случаях, когда нужна действительно жесткая оптимизация.

Я не проверял это на более старых компиляторах. Возможно, там все будет не так хорошо. Может быть будет еще хуже на RISC процессорах, у которых нет таких дьявольски сложных команд как у Intel, где можно хитро объединять умножение со сложением. Если бы я занялся реальной профилировкой, думаю результат был бы еще интереснее.

Но факт остается фактом: в критических местах все нужно проверять самому. Трюки и приемы программирования устаревают с появлением новых компиляторов и платформ, под которые они пишутся.

 Добавьте на news2.ru     Занесите в del.icio.us

Читайте также:
No related posts





Оставить комментарий