Помощь - Поиск - Пользователи - Календарь
Полная версия: Сравненин
Форум «Всё о Паскале» > Pascal, Object Pascal > Задачи
}0pa
Кто-нибудь может програмно показать отличия между inc(n) и n:=n+1 для целого n. Плз помогите!
klem4
Что значит программно показать отличие ? Эти операции выполняют одно и тоже с однаковой скоростью. Ты это хотел услышать ? После компиляции отличиий между inc(n) и n := n + 1 нету никаких.
Malice
Если делаешь n=n+1 то используется сложение через регистр, если inc, то сразу с памятью. Т.е.:

asm
inc word [n] { =inc(i) }

mov ax,[n] {n:=n+1}
inc ax
mov [n],ax
end;


Во всех других вариациях (inc(n,5) и даже inc(n,x)) трансляция таже. Поэтому inc вроде бы лучше..
Все это касается tp.
volvo
Цитата
Эти операции выполняют одно и тоже с однаковой скоростью.
no1.gif Для 16-битных компиляторов (проверялось на TP6, возможно в семерке уже более умный компилятор, надо посмотреть) скорость с Inc будет выше... Выигрыш может составлять до 20%... 32-битные вроде научились оптимизировать...
}0pa
А с помощью Таймера по=моему можно проверить...? Другое дело как?
volvo
Так как показано здесь:
Улучшение кода

(просто подставь те операторы, которые ты хочешь тестировать)
}0pa
Вот сделал:
Код
uses crt;
const
n = 25000;

var
tm, tm1: longint;
i,j,k: longint;
begin
clrscr;
writeln('n = ', n, ' * ', n);

{----- inc(k); -----}
tm1:= MemL[$0040:$006c];
for i := 1 to n do
  for j := 1 to n do
    begin
      inc(k);
    end;
tm:= MemL[$0040:$006c];
tm:=tm-tm1;
writeln('#1: ',tm);


{----- k:=k+1 -----}
tm1:= MemL[$0040:$006c];
for i := 1 to n do
  for j := 1 to n do
    begin
      k:=k+1
    end;
tm:= MemL[$0040:$006c];
tm:=tm-tm1;
writeln('#2: ',tm);
readkey
end.

Результаты теста:
Код

n=25000*25000
#1:179
#2 133

n=15000*15000
#1:126
#2 96

Но хотелось бы знать, что значут эти рез-ты? Неужели k:=k+1 быстрее?
Что определяют эти массивы? Почему они именно так записаны?

Код

tm1:= MemL[$0040:$006c];
.....................................
tm:= MemL[$0040:$006c];

ЗЫ:Уж извините за такое кол-во вопросов. Все-таки хочется узнать! yes2.gif
}0pa
Ну, уж очень хочется узнать give_rose.gif give_rose.gif give_rose.gif
Malice
У тебя k - longint, поэтому inc выглядит так:

add       w,[k],1
adc w,[k+2],0

k:=k+1 так:
mov       ax,[k]
mov dx,[k+2]
add ax,1
adc dx,0
mov [k],ax
mov [k+2],dx

Видимо второй вариант лучше распаралеливается..
Если бы тип был byte, word, integer (умещался в регистр), то результат был бы обратный yes2.gif
}0pa
1.Malice, я просто с трудом понимаю, что значит твой код. Но не мог бы ты пояснить построчно, что ты делаешь?
2.Мой вопрос выше остается в силе

К тому же, если мы вместо longint используем intger, то Run Time Error
Malice
Цитата(}0pa @ 4.12.2006 23:39) *

1.Malice, я просто с трудом понимаю, что значит твой код. Но не мог бы ты пояснить построчно, что ты делаешь?
2.Мой вопрос выше остается в силе


1. Я показал во что транслируются операции inc и + на ассемблере, т.к. сами операции паскаля - черный ящик и для анализа причин не очень подходят. В первом своем посте я показал, что inc на асме короче и оттого быстрее, во втором - что inc короче, но не быстрее ;) , возможно из-за того, что код с '+' лучше распаралелливается процем.
2. чтобы ответить точнее, нужно почитать какие-нибуть статьи про оптимизацию кода, например на wasm.ru

Цитата(}0pa @ 4.12.2006 23:39) *

К тому же, если мы вместо longint используем intger, то Run Time Error

Не может быть, если только ты tm тоже сделал integer, нужно менять тип только у K.
hiv
Это все относится к вопросу чистоты эксперимента wink.gif
Вот мой код:
program Project1;
{$APPTYPE CONSOLE}
uses SysUtils, DateUtils;

var
tm,tm1 : TDateTime;
i,k: longint;

begin
k:=-2147483647;
{----- inc(k); -----}
tm1:= Now;
for i := -2147483647 to 2147483646 do inc(k);
tm:= Now;
writeln('#1: ',IntToStr(MilliSecondsBetween(tm,tm1)), #9, IntToStr(k));

k:=-2147483647;
{----- k:=k+1 -----}
tm1:= Now;
for i := -2147483647 to 2147483646 do k:=k+1;
tm:= Now;
writeln('#2: ',IntToStr(MilliSecondsBetween(tm,tm1)), #9, IntToStr(k));
end.
А вот результаты:
Код
С дебаг информацией в генерируемом коде:
#1: 6811        2147483646
#2: 7750        2147483646
Без дебага в коде и отключены всякие проверки:
#1: 4921        2147483646
#2: 5078        2147483646
Как видно эти операции абсолютно одинаково генеряться компилятором Delphi7. Разницу в 3% считаю несущественной.
volvo
yes2.gif Как я и написал выше - 32 битные компиляторы оптимизируют код... Вот фрагменты ASM-кода для вышеприведенной программы (FPC 2.0.4, в режиме совместимости с Дельфи):

# [13] for i := -2147483647 to 2147483646 do inc(k);
movl $-2147483647,U_P$PROJECT1_I
decl U_P$PROJECT1_I
.balign 4
.L13:
incl U_P$PROJECT1_I
incl U_P$PROJECT1_K
cmpl $2147483646,U_P$PROJECT1_I
jl .L13
.Ll5:
.stabn 68,0,14,.Ll5 - _main


# [20] for i := -2147483647 to 2147483646 do k:=k+1;
movl $-2147483647,U_P$PROJECT1_I
decl U_P$PROJECT1_I
.balign 4
.L61:
incl U_P$PROJECT1_I
incl U_P$PROJECT1_K
cmpl $2147483646,U_P$PROJECT1_I
jl .L61
.Ll10:
.stabn 68,0,21,.Ll10 - _main

Как видим, что Inc(k), что K := K + 1 заменяются на INCL

Другое дело - если K сделать байтовым... Тогда:
# [14] for i := -2147483647 to 2147483646 do inc(k);
movl $-2147483647,U_P$PROJECT1_I
decl U_P$PROJECT1_I
.balign 4
.L13:
incl U_P$PROJECT1_I
incb U_P$PROJECT1_K
cmpl $2147483646,U_P$PROJECT1_I
jl .L13
.Ll5:
.stabn 68,0,15,.Ll5 - _main


# [21] for i := -2147483647 to 2147483646 do k:=k+1;
movl $-2147483647,U_P$PROJECT1_I
decl U_P$PROJECT1_I
.balign 4
.L61:
incl U_P$PROJECT1_I
movzbl U_P$PROJECT1_K,%eax
incl %eax
movb %al,U_P$PROJECT1_K
cmpl $2147483646,U_P$PROJECT1_I
jl .L61
.Ll10:
.stabn 68,0,22,.Ll10 - _main
, и разница во времени выполнения кода уже в 2 раза больше.

NTL
Тогда,пожалуйста,объясните рез-ат моего тестера, который показывает, что m:=m+1 немного работает быстрее чем inc(m). blink.gif
ЗЫ:Проверял 15 раз wub.gif
Malice
Потому что у тебя m - longint, читай внимательнее, было уже yes2.gif
Это текстовая версия — только основной контент. Для просмотра полной версии этой страницы, пожалуйста, нажмите сюда.