Форум программистов «Весельчак У»
  *
Добро пожаловать, Гость. Пожалуйста, войдите или зарегистрируйтесь.
Вам не пришло письмо с кодом активации?

  • Рекомендуем проверить настройки временной зоны в вашем профиле (страница "Внешний вид форума", пункт "Часовой пояс:").
  • У нас больше нет рассылок. Если вам приходят письма от наших бывших рассылок mail.ru и subscribe.ru, то знайте, что это не мы рассылаем.
   Начало  
Наши сайты
Помощь Поиск Календарь Почта Войти Регистрация  
 
Страниц: [1]   Вниз
  Печать  
Автор Тема: Правда ли что сравнение с нулем эффективнее чем с числом? Т.е. цикл будет работа  (Прочитано 20075 раз)
0 Пользователей и 8 Гостей смотрят эту тему.
USBLexus
Опытный

ru
Offline Offline
Пол: Мужской
Кот рыжий


« : 08-11-2005 05:02 » new

Правда ли что сравнение с нулем эффективнее чем с числом? Т.е. цикл будет работать быстрее
for(int i=100; i; --i;)

чем этот цикл
for(int i=0; i<100; ++i;)
Записан

#define QUESTION(b) (2*b)||(!(2*b)) (c) William Shakespeare
Алексей++
глобальный и пушистый
Глобальный модератор

ru
Offline Offline
Сообщений: 13


« Ответ #1 : 08-11-2005 05:23 » 

думаю разницы в случае не ассемблера нет

а может быть и в случае асма тоже.
(кстати - перед скобкой в конце не надо семиколон)

смотри:
Код:
158:  for(int i=100; i; --i)
00442D51   mov         dword ptr [ebp-14h],64h
00442D58   jmp         CGuard2View::CGuard2View+3F3h (00442d63)
00442D5A   mov         ecx,dword ptr [ebp-14h]
00442D5D   sub         ecx,1
00442D60   mov         dword ptr [ebp-14h],ecx
00442D63   cmp         dword ptr [ebp-14h],0
00442D67   je          CGuard2View::CGuard2View+41Ch (00442d8c)

160:  //&#247;&#229;&#236; &#253;&#242;&#238;&#242; &#246;&#232;&#234;&#235;
161:  for(int i=0; i<100; ++i)
00442D69   mov         dword ptr [i],0
00442D70   jmp         CGuard2View::CGuard2View+40Bh (00442d7b)
00442D72   mov         edx,dword ptr [i]
00442D75   add         edx,1
00442D78   mov         dword ptr [i],edx
00442D7B   cmp         dword ptr [i],64h
00442D7F   jge         CGuard2View::CGuard2View+41Ah (00442d8a)

код - "одинаковый по времени"
Записан

Hooter
Опытный

ru
Offline Offline
Пол: Мужской

« Ответ #2 : 08-11-2005 05:44 » 

Правда ли что сравнение с нулем эффективнее чем с числом? Т.е. цикл будет работать быстрее

Теоретически, да. А практически, чтобы увидеть разницу, нужно как минимум отключить оптимизацию при компиляции.
Записан
Алексей++
глобальный и пушистый
Глобальный модератор

ru
Offline Offline
Сообщений: 13


« Ответ #3 : 08-11-2005 05:50 » 

USBLexus , замерь время:

Код:
	DWORD time1;
DWORD time2;
DWORD diftime;

time1=GetTickCount();

//... тут - то, где надо измерить время

time2=GetTickCount();
diftime=time2-time1;

//diftime - время в миллисекундах


Записан

USBLexus
Опытный

ru
Offline Offline
Пол: Мужской
Кот рыжий


« Ответ #4 : 08-11-2005 09:09 » 

Проверял на таком вот коде:

DWORD time1;
DWORD time2;
DWORD diftime1;
DWORD diftime2;
int temp=0;


while(1){


   time1=GetTickCount();

   for(DWORD i=100000; i; --i)
    for(DWORD k=5000; k; --k)
      temp=7;
      
   time2=GetTickCount();

   diftime1=time2-time1;


   time1=GetTickCount();

   for(DWORD i=0; i<100000; ++i)
    for(DWORD k=0; k<5000; ++k)
     temp=7;

   time2=GetTickCount();

   diftime2=time2-time1;
}
Разницы вроде никакой, даже если она и есть то очень маленькая
Записан

#define QUESTION(b) (2*b)||(!(2*b)) (c) William Shakespeare
Алексей++
глобальный и пушистый
Глобальный модератор

ru
Offline Offline
Сообщений: 13


« Ответ #5 : 08-11-2005 09:52 » 

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

Finch
Спокойный
Администратор

il
Offline Offline
Пол: Мужской
Пролетал мимо


« Ответ #6 : 08-11-2005 17:13 » 

Это смотря как компилятор строит цикл.
1. Он может загнать переменную в регистр CX (eCX) и делать цикл через команду LOOP.
Тогда разница должна проявлятся.

2. Осушествлять проверку на  нуль через команду
CMP AX,0 (заместо регистра может быть ячейка памяти)
JNZ ......
Если этим способом, то не должно быть вообше разници

3. Делать проверку сразу после декременирования
DEC AX (или ячейка памяти)
JNZ ......
Но этот вариант очень маловероятен по логике построения комманд компилятором.
Записан

Не будите спашяго дракона.
             Джаффар (Коша)
Алик
Постоялец

kz
Offline Offline

« Ответ #7 : 08-11-2005 17:22 » 

хороший компилятор при декременте должен бы воспользоваться командой loop, которая чуть быстрее, чем сравнение и прыжок. увеличение скорости должно быть, хоть и небольшое. но у меня были тупые ошибки из-за этого счета наоборот.
а геттиккаунт - штука очень не точная (сталкивался с этим).
Записан
Finch
Спокойный
Администратор

il
Offline Offline
Пол: Мужской
Пролетал мимо


« Ответ #8 : 08-11-2005 17:31 » 

Алик, LOOP сам декриментирует. Поэтому это самый быстрый будет способ посторения цикла. Но есть одно но. Занимается регистр. Что не есть хорошо для логики компилятора
Записан

Не будите спашяго дракона.
             Джаффар (Коша)
Алик
Постоялец

kz
Offline Offline

« Ответ #9 : 09-11-2005 09:18 » 

Тут опять же все упирается в качество самого компилятора. Хорошему занятый регистр не помешает. хороший старается оптимизировать как-то циклы и вполне может как-то извратиться, чтобы для возрастающего цикла loop использовать.
Записан
Finch
Спокойный
Администратор

il
Offline Offline
Пол: Мужской
Пролетал мимо


« Ответ #10 : 09-11-2005 13:12 » 

Может быть. Только я один раз долго ловил блох, когда компилятор переделал с возрастаюшего цикла в ниспадаюший. Не помню какая была задача. Но мне очень важно было, чтобы массив заполнялся по возрастанию.
Второй раз, когда я столкнулся с багами связанными с оптимизацией совсем недавно. В Debug режиме программа работала просто на ура. В Release режиме она падала с треском. Я так и не разобрался почему. Так что оптимизация, оптимизации рознь. Когда делаеш программу на уровне косвенных эффектов, иногда можно получить кучу багов во время компиляции в разных режимах.
Записан

Не будите спашяго дракона.
             Джаффар (Коша)
acc15
Гость
« Ответ #11 : 13-12-2005 06:06 » 

вы никак не отловите время выполнения 1-2 команд... gettickcount - бред, оссобенно в многозадачной ос, оссобенно в современных процах, там и предвыборка и предугадывание перехода.
Исходя из справочников выполнение команд:
cmp --- в зависимости от данных 1/2 или 1 такт
jmp --- R-режим = 1 такт. P-режим = 3 такта.
loop --- R-режим = 2 такта. P-режим = 6 тактов.
где R - реальный режим, а P - страничный режим (Windows)
странно но что-то тут нето...
loop = dec ecx, cmp ecx,0 jnz loopmet
(dec ecx = 1) + (cmp ecx,0 = 1) + (jnz = 3) = 5... чтото тут нето... но всё равно вывод очевиден... loop = dec cx, cmp cx,0 jnz loopmet... если не учитывать размер команд (3) и предвыборку, то по скорости выполнения равны.
возьмём дефолтный на сегодняшний день проц... с частотой 2,4 ГГц = 2400000000 Гц. (1/2400000000)*6=0,0000000025 сек. примерно за столько выполнится ваш луп... и какой здесь может быть GetTickCount() ?? ??
про 0... процу абсолютно всё равно что сравнивать... cmp - это не что иное как вычитание... а вычитание происходит по времени одинаково независимо от значения сравниваемой переменной или константы
« Последнее редактирование: 13-12-2005 06:26 от acc15 » Записан
Алексей++
глобальный и пушистый
Глобальный модератор

ru
Offline Offline
Сообщений: 13


« Ответ #12 : 13-12-2005 07:05 » 

acc15 , GetTickCount()  я предложил для оценки времени большого количества вычислений Улыбаюсь  а не одной команды проца

ЗЫ. Какая разница, предугадывание, луп не луп, если один код выполнится за 10 с, а другой за 1 с (это к примеру) ?
Записан

acc15
Гость
« Ответ #13 : 13-12-2005 08:09 » 

прикасаясь к теме... там сказано что сравнение с нулём быстрее чем с другим числом... вот я и написал...

если одинаковый по действию код выполнится позже другого то значит что в том коде который выполнится медленнее есть лишние действия... а какие могут быть лишние действия в простом сравнении? ? ? ?
« Последнее редактирование: 13-12-2005 08:20 от acc15 » Записан
Алексей++
глобальный и пушистый
Глобальный модератор

ru
Offline Offline
Сообщений: 13


« Ответ #14 : 13-12-2005 08:43 » 

acc15 , да эт всё понятно, лишнего нет, дело в другом: как прогу на СИ перелопатит компилятор Улыбаюсь
Записан

Mayk
Гость
« Ответ #15 : 30-12-2005 05:29 » 

Ну во-первых это не та эффективность которую стоит добиваться. Улыбаюсь
Если что-то работает медленно, то шанс добится выигрыша в скорости используя этот способ равен нулю.


прикасаясь к теме... там сказано что сравнение с нулём быстрее чем с другим числом... вот я и написал...
если одинаковый по действию код выполнится позже другого то значит что в том коде который выполнится медленнее есть лишние действия... а какие могут быть лишние действия в простом сравнении? ? ? ?
Само сравнение. У процессора есть флаг "Ноль ли число" но у него нет флага "равно ли число 1924"
3. Делать проверку сразу после декременирования
DEC AX (или ячейка памяти)
JNZ ......
Но этот вариант очень маловероятен по логике построения комманд компилятором.
Вот здесь сравнения нет.
Кстати, некоторые компиляторы используют sub blabla,1.

в общем имхо низкоуровневую оптимизацию надо оставить компилятору.
Записан
acc15
Гость
« Ответ #16 : 30-12-2005 13:28 » 

Цитата
Само сравнение. У процессора есть флаг "Ноль ли число" но у него нет флага "равно ли число 1924"
вот именно что он есть, и устанавливается он только по исполнению некоторых команд процессора, к примеру тот же cmp устанавливает эти флаги, поэтому сравнение необходимо для установки флагов, по которым будет выполнен условный джамп.

Сравнение с 0, а не с 1924, не путай, если ты про это
Цитата
про 0... процу абсолютно всё равно что сравнивать... cmp - это не что иное как вычитание... а вычитание происходит по времени одинаково независимо от значения сравниваемой переменной или константы
то если сравнивать 1924 или 0 это всё равно. просто поменяются флаги.
Записан
Mayk
Гость
« Ответ #17 : 31-12-2005 10:21 » 

вот именно что он есть, и устанавливается он только по исполнению некоторых команд процессора, к примеру тот же cmp устанавливает эти флаги, поэтому сравнение необходимо для установки флагов, по которым будет выполнен условный джамп.
Если сделать sub <Ваш-Любимый-Регистр>, 1
то флаги и так поменияются. Не надо будет сравнивать. Не надо делать cmp. Вычитание уже сделано. Флаги уже установлены.
Сравнение с нулем в общем случае конечно не бессмысленно, но после sub'а и dec'а смысла в нём всё же нет. Никакого. ZF уже и так установлен в 1, если результат 0.Команду cmp ,0 можно выкинуть.

« Последнее редактирование: 20-12-2007 19:17 от Алексей1153++ » Записан
acc15
Гость
« Ответ #18 : 01-01-2006 15:07 » 

впринципе ты прав, но если тебе не нужно вычитание, а нужно именно сравнение, то как тогда быть? только cmp...

хотя я нашел ошибку...  loop = dec cx, cmp cx,0 jnz loopmet... без cmp.. т.к. не нужен..
« Последнее редактирование: 01-01-2006 15:09 от acc15 » Записан
Страниц: [1]   Вверх
  Печать  
 

Powered by SMF 1.1.21 | SMF © 2015, Simple Machines