Главная страница


ru.algorithms

 
 - RU.ALGORITHMS ----------------------------------------------------------------
 From : Sashka Yackubtchick                  2:5054/29.54   01 Dec 2001  16:13:25
 To : All
 Subject : Min and Max without branching
 -------------------------------------------------------------------------------- 
 
 
 Почитав в эхе на тему сабжа, решил описать некоторые методы
 больше для того чтобы было понятно какие закономерности лежат в
 их основе нежели для того чтобы придложить готовый рецепт.
 Думаю всегда существует возможность когда кому то прийдёт в голову
 новый более оптимальный вариант, но для этого нужна пища для ума,
 вот такую "пищу" довольно прожёванную я хочу попытаться пердложить.
 
 Min \ Max двух чисел без условных переходов.
 --------------------------------------------
 Данные приёмы строятся на трёх китах:
 1.Если сделать AND числа A с числом B в котором все биты установлены в 1 то
 получим тоже самое число A (01011100 and 11111111 = 01011100)
   Если сделать AND числа A с числом B где все биты установлены в 0 то получим 0
   01011100 and 00000000 = 00000000
   результатом AND будет 1 тогда и только тогда когда оба оператора = 1
 2.Если в результате вычитания из меньшего числа вычитается большее то в
 результате произойдёт заем из старшего (воображаемого) разряда и сигналом об
 этом будет установка carry flag с тем чтобы можно его было использовать в
 дальнейшем (вычитать или прибавлять его значение) Сравнение осуществляется в
 компьютере именно вычитанием при этом разница состоит с обычным вычитанием лишь 
 в том что результат не пишется в вычитаемое но флаги ( а они то и
   показывают как через вычитание видно результат сравнения) устанавливаются
 3.Минус 1 выглядит в дополнительном коде как число где все биты установлены в  1
 а 0 где все биты установлены в 0.
 
 Теперь представим что мы сравнили два числа и у нас установился в результате
 carry flag если первое число было меньше второго (произошёл заем при вычитании)
 если мы вычтем carry flag из 0 то получим -1 (11111111) если же займа небыло то 
 останется 0
 Если результат такого вычитания мы используем для AND с неким числом то получим 
 либо это число либо 0.
 Посмотрим как это можно использовать для того чтобы получить минимум двух чисел.
 if (B < A) A = B
 eax  A
 ebx  B
          SUB EBX,EAX ;получим разницу B - A исходя из того что В = А + (B - A)
          SBB ECX,ECX ;вычитает число из само из себя и вычитает carry получим 0
                      ;если B>A и -1 (число где все биты = 1) если B<A
          AND ECX,EBX ;превратим ecx в разницу EBX - EAX если эта разница была 
 ;отрицательной или в 0 если она была положительной
          ADD EAX,ECX ;если ebx был меньше прибавится отрицательная разница    
 ;(иначе говоря произойдёт вычитание) в противном случае                   
 ;прибавится 0 и результат не изменится.
 
 Данный пример взят из известного мануала Ангера Фога по оптимизации для
 процессоров семейства
 Pentium. Правда без всяких коментариев и назван трюком(слово которое я просто
 ненавижу).
 Что даёт мне основание думать что сам Фог к авторству не имеет никакого
 отношения
 хотя он не упоминает откуда взял пример.
 Как и многие другие авторы примеров оптимизации которые "густо" комментируют
 абсолютно
 очевидные вещи и оставляют без комментариев вещи неочевидные для непросвящённых.
 Тем не менее как писал Кнут "многие учёные разными путями и в разное время
 независимо друг от
 друга открыли ..." будем считать что и этот приём один из подобных открытий
 пришедший в голову
 многим независимо.
 
 Теперь к нашим баранам.
 Посмотрим можно ли использовать подобный эффект при нахождении максимума двух
 чисел.
 Обратите внимание на второй шаг кода SBB ECX,ECX
 он означает ecx - ecx - carry flag.  Естествено что A = A и A - A = 0 поэтому
 эта простейшая
 однотактовая команда делает настоящую работу:
 if cf then
  ecx = -1
 else
  ecx = 0
 Причём что важно - предидущее значение cf не важно в любом случае A - A = 0
 и 0 - 1 = -1 а 0 - 0 = 0
 Почему я так долго мурыжу очевидные вещи - в обратном действии не получится
 сделать выбор за 4 команды как примере с MIN HО! Можно это сделать за 4е такта
 также как в MIN (все команды в приведенном примере зависимые и это не позволяет
 их распаралелить по разным АЛУ)
 Итак вариант MAX пять команд но 4е такта (c)Svin.
 
 1. mov ecx,-1 ;ecx = 11111111 11111111 11111111 11111111
 2. sub ebx,eax ;B-A
 3. adc ecx,0  ;if B-A < 0 (-1+ 0 + 1) ecx = 0 else (-1 + 0 + 0) ecx = -1
 4. and ecx,ebx ;if B<A ecx = 0 else ecx = B-A
 5. add eax,ecx ;if B<A eax + 0 else eax+(B-A)
 
 1. Поместим в ecx - 1 (все биты установливаются в 1)
 2. Получим разницу B - A Шаг первый и второй независимы от друг друга и
 выполнятся в разных АЛУ за один такт
 3. Если ebx был меньше eax то установится carry flag и сложение его с -1 даст 0
 4. Результат зависит от шага 3 либо 0 либо B-A
 5. К А добавится разница B-A если B был больше в противном случае добавится 0
 Пока!
              Sashka
 
 --- GoldED/W32 3.00.Beta1+
  * Origin: Svin, Perm, Russia  (2:5054/29.54)
 
 

Вернуться к списку тем, сортированных по: возрастание даты  уменьшение даты  тема  автор 

 Тема:    Автор:    Дата:  
 Min and Max without branching   Sashka Yackubtchick   01 Dec 2001 16:13:25 
Архивное /ru.algorithms/33843c08f5ed.html, оценка 2 из 5, голосов 10
Яндекс.Метрика
Valid HTML 4.01 Transitional