Войти
ФлеймФорумПрограммирование

Оптимизатор C++ "бьёт по рукам".

Advanced: Тема повышенной сложности или важная.

Страницы: 1 2 Следующая »
#0
10:54, 15 июня 2009

Функция наложения спрайта, в тех местах, где источник ярче приёмника, поканально (ARGB):

 
extern "C" __declspec(dllexport) void __stdcall MAX_(unsigned char* src, unsigned char* dest, int w, int h, int ws, int wd) 
{ 
 int y; 
 int x; 
 for (y = 0; y < h; y++) 
 { 
   for (x = 0; x < w * 4; x++) 
   { 
     if (*(dest + x + y * wd * 4) < *(src + x + y * ws * 4)) 
     { 
       *(dest + x + y * wd * 4) = *(src + x + y * ws * 4); 
     } 
   } 
 } 
 return; 
} 

Теперь я её оптимизирую (это я так думаю):
 
extern "C" __declspec(dllexport) void __stdcall MAX_(unsigned char* src, unsigned char* dest, int w, int h, int ws, int wd) 
{ 
 w *= 4; 
 ws = ws * 4 - w; 
 wd = wd * 4 - w; 
 for (int y = 0; y < h; y++) 
 { 
   for (int x = 0; x < w; x++) 
   { 
     if (*dest < *src) 
     { 
       *dest = *src; 
     } 
     src++; 
     dest++; 
   } 
   src += ws; 
   dest += wd; 
 } 
 return; 
} 

... и она начинает работать на 10% медленнее. С++ оптимизатор отучивает оптимизировать.

#1
11:04, 15 июня 2009

Создавал недавно подобную тему.
Пришли к выводу что лучше не стоит обманывать компилятор :)

З.Ы. Кстати, интересно было бы поразмышлять на тему искусственного интеллекта в компиляторах.

#2
11:12, 15 июня 2009

А чего ассемблер показывает?

#3
11:27, 15 июня 2009

Оптимизированный вариант:

$LL4@MAX_:
  mov  dl, BYTE PTR [ecx]
  cmp  BYTE PTR [eax], dl
  jbe  SHORT $LN1@MAX_
  mov  BYTE PTR [eax], dl

$LN1@MAX_:
  inc  ecx
  inc  eax
  sub  ebx, 1
  jne  SHORT $LL4@MAX_

Неоптимизированный вариант:

$LL4@MIN_:
  mov  cl, BYTE PTR [esi+eax]
  cmp  BYTE PTR [edx+eax], cl
  jbe  SHORT $LN3@MIN_

  mov  BYTE PTR [edx+eax], cl
$LN3@MIN_:
  inc  eax
  cmp  eax, edi
  jl  SHORT $LL4@MIN_

#4
11:40, 15 июня 2009

Mikle

Саттер по этому поводу говорит следующее:

1. Не оптимизируй.
2. Никогда не оптимизируй.

#5
11:42, 15 июня 2009

Mikle
>BYTE PTR [esi+eax]
>BYTE PTR [edx+eax]

Гы... Грамотная петрушка. =) Две базы взял - и попер единым индексатором колбасить. Действительно во втором случае с двумя указателями труднее догадаться, что индексатор может быть единым. Мотаем на ус, как говорится. =)

#6
12:15, 15 июня 2009

Mikle
а можешь ради теста добавить к указателям ключевое __restrict

#7
13:35, 15 июня 2009

Mikle
Цикл тривиальный - все в регистрах помещается, вот два инкримента тут и оказались лишними.

Сравни, до кучи еще с таким вариантом:

extern "C" __declspec(dllexport) void __stdcall MAX_(unsigned char* src, unsigned char* dest, int w, int h, int ws, int wd) 
{ 
 w *= 4; 
 ws = ws * 4; 
 wd = wd * 4; 
 for (int y = 0; y < h; y++) 
 { 
   for (int x = 0; x < w; x++) 
     if (dest[x] < src[x]) dest[x] = src[x]; 

   src += ws; 
   dest += wd; 
 } 
 return; 
} 

#8
16:30, 15 июня 2009

Pushkoff
doc.
Попробую. Хотя это чисто академический интерес - я на асме сделал в 2.5 раза быстрее.

#9
10:50, 17 июня 2009

Mikle
Когда будут результаты?

#10
11:22, 17 июня 2009

У меня в коде есть парочка мест, в которых известно еще на момент компиляции цисло итераций в цикле. Много ли профита можно получить, если развернуть цикл в китайский код?

#11
11:24, 17 июня 2009

MarkoPolo

Можно не в китайский, а в "цикл времени компиляции". Ответ, как обычно, будет "трясти надо". Кстате, оптимизато сам умеет раскручивать циклы.

#12
11:30, 17 июня 2009

Pushkoff
Вариант от doc. даёт точно такой же результат, как мой самый первый. Правда на SSE я написал вариант в 3-4 раза быстрее, зависит от процессора.

#13
11:30, 17 июня 2009

du_hast
Это которая через рекурсивный шаблон? Она не более 32 вложений или нет?

#14
11:40, 17 июня 2009

MarkoPolo

> рекурсивный шаблон

Можно слепить и через перегрузку функции, int2type :)

> 32

Откуда это число?

template <int i, int end, int step> struct loop
{
    static void exec(void)
    {
        printf("%d %d %d\n", i, end, step);
        loop<i + step, end, step>::exec();
    }
};

template <int end, int step> struct loop<end, end, step>
{
    static void exec(void) {}
};

int _tmain(int argc, _TCHAR* argv[])
{
    loop<0, 50, 1>::exec();
}
Страницы: 1 2 Следующая »
ФлеймФорумПрограммирование

Тема в архиве.