Главная страница
Top.Mail.Ru    Яндекс.Метрика
Текущий архив: 2003.07.21;
Скачать: CL | DM;

Вниз

Как замерять время выполнения отдельных частей программы ?   Найти похожие ветки 

 
Кен ©   (2003-06-28 04:00) [0]

Нужно, чтобы отыскивать и ускорять слабые места внутри функций или процедур.


 
Asteroid ©   (2003-06-28 04:37) [1]

Перед началом отдельной части хотя бы time := GetTickCount(); и в конце time := GetTickCount() - time; Вместо GetTickCount() можно и QueryPerformanceCounter(), но он муторнее, хотя и точнее.


 
Sha ©   (2003-06-28 11:55) [2]

Примерно так. Есть тонкости. Подробности у Intel.

function GetCPUTick: int64; assembler;
asm
db 0fh,31h; //rdtsc
end;

const
nullticks= 11;
var
t: cardinal;
begin;
t:=GetCPUTick;
...code here...
t:=GetCPUTick-t-nullticks;
Caption:=IntToStr(t);
end;


 
Asteroid ©   (2003-06-28 19:29) [3]

> Sha © (28.06.03 11:55)
nullticks = 11 - почему иенно 11? Неужели столько уходит на вызов функции?


 
Просто прохожий   (2003-06-28 20:52) [4]

Это такты CPU, которые расходуются на вызов функции. 11 - это очень мало. Конкретное значение зависит от типа процессора. Чтобы узнать значение для твоего процессора, установи nullticks= 0; и не вставляй никакого кода между последовательными вызовами GetCPUTick. Получишь результат, который дальше используй.


 
wicked ©   (2003-06-28 21:06) [5]


> Чтобы узнать значение для твоего процессора, установи nullticks=
> 0; и не вставляй никакого кода между последовательными вызовами
> GetCPUTick. Получишь результат, который дальше используй.

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


 
Просто прохожий   (2003-06-28 21:20) [6]

wicked © (28.06.03 21:06)
Иногда важно точно вешать


 
Кен ©   (2003-06-29 01:35) [7]

> Asteroid © (28.06.03 04:37)
> Перед началом отдельной части хотя бы time := GetTickCount();
> и в конце time := GetTickCount() - time;

Почему то сколько не мерюю результат всегда разный.

> Sha © (28.06.03 11:55)
> Примерно так. Есть тонкости. Подробности у Intel.

А если у меня АМД, то что делать ?


 
Просто прохожий ©   (2003-06-29 12:28) [8]

>Кен © (29.06.03 01:35)
>Почему то сколько не мерюю результат всегда разный.
Во-первых, потому, что Windows не только твою программу исполняет.
Во-вторых, GetTickCount дает текущий тик таймера, который сам длится некоторое время. Представь, что ты замеряешь время своего зевка, пользуясь электронными часами, показывающими только часы и минуты. Результат почти всегда будет равен 0, но иногда будет 1 минута.

>А если у меня АМД, то что делать?
У Sha © тоже AMD :) Смело пользуйся приведенной функцией.
Не забудь повторить измерения несколько раз и взять минимальный результат, чтобы уменьшить издержки Windows.


 
Всеволод Соловьёв ©   (2003-06-29 12:36) [9]

Интел имелся в виду x86 - АМД хоть и RISC процы делает, но они с дешифратором (или как это называется?), то есть разлаживают эти все команды x86 на простенькие плюс-минус-умножить-поделить и работают. (пни и целероны - CISC)


 
me   (2003-06-29 21:59) [10]

есть такие штуки - профайлеры, они засекают время и частоту выполнения отдельных участков программы для поиска "узких" мест
www.eccentrica.org/garb/gpprofile/gpprofile.htm
www.prodelphi.de
www.axiomati.demon.co.uk


 
Sergey Masloff   (2003-06-29 22:07) [11]

me (29.06.03 21:59)
Вот и я думаю - что народ велосипеды изобретает. Или настолько нужно с точностью до тиков процессора ловить?

>www.eccentrica.org/garb/gpprofile/gpprofile.htm
очень удобная штука

>www.prodelphi.de
Они вроде загибаться стали одно время а сейчас посмотрел - сайт обновляется, версии - вобщем, пациент скорее жив?



 
DrPass ©   (2003-06-29 22:12) [12]


> Всеволод Соловьёв © (29.06.03 12:36)
> Интел имелся в виду x86 - АМД хоть и RISC процы делает,
> но они с дешифратором (или как это называется?), то есть
> разлаживают эти все команды x86 на простенькие плюс-минус-умножить-поделить
> и работают. (пни и целероны - CISC)

%)
Ты чуток перепутал. Все современные процы x86 имеют RISC-ядро (и пни, и VIA C3, и старые AMD K5, K6). А вот Athlon как раз наоборот, особенность его архитектуры - преобразование команд x86 в макрокоманды и исполнение их пачками за такт. Это единственный чистый CISC-процессор в семействе x86

А что касается вопроса - то никаких GetTickCount не нужно. А нужен обычный профайлер


 
Всеволод Соловьёв ©   (2003-06-29 23:01) [13]

2DrPass
давно разбирал и перепутал :)


 
Кен ©   (2003-06-30 02:26) [14]

> Просто прохожий © (29.06.03 12:28)
> >Кен © (29.06.03 01:35)
> >Почему то сколько не мерюю результат всегда разный.
> Во-первых, потому, что Windows не только твою программу
> исполняет.

Вот ! А как на время запретить Виндос исполнять что-либо другое ? Буквально на десятые доли секунды. А то точности никакой.


 
DrPass ©   (2003-06-30 02:37) [15]

Попробуй выставить приоритет realtime для своего процесса. По крайней мере, точность повысится


 
Просто прохожий ©   (2003-06-30 12:20) [16]

Кен © (30.06.03 02:26)
Измеряй время работы небольших кусков кода - не более 5-10 msec. Sha © утверждает, что если подумать, этого обычно хватает.
Повторяй измерения в цикле несколько (>10000) раз и бери минимальное. Тогда на измеряемом интервале хотя бы раз Windows не преключится на другие задачи, не произойдет прерывания от таймера, и ты получишь необходимую точность.


 
panov ©   (2003-06-30 12:28) [17]

Тогда на измеряемом интервале хотя бы раз Windows не преключится на другие задачи, не произойдет прерывания от таймера, и ты получишь необходимую точность.

И как определить этот один раз?

Это из серии - неработающие часы показывают один раз в сутки самое точное время.


 
Просто прохожий ©   (2003-06-30 12:33) [18]

>panov © (30.06.03 12:28)
>И как определить этот один раз?

Смотреть внимательней:
Повторяй измерения в цикле несколько (>10000) раз и бери минимальное.


 
Просто прохожий ©   (2003-06-30 12:35) [19]

Ну, и конечно:
Измеряй время работы небольших кусков кода - не более 5-10 msec.


 
Кен ©   (2003-07-01 04:19) [20]

> Просто прохожий © (30.06.03 12:20)
> Кен © (30.06.03 02:26)
> Измеряй время работы небольших кусков кода - не более 5-10
> msec. Sha © утверждает, что если подумать, этого обычно
> хватает.

Вот на небольших кусках кода как раз можно запросто получить 0. )

> Повторяй измерения в цикле несколько (>10000) раз и бери
> минимальное. Тогда на измеряемом интервале хотя бы раз Windows
> не преключится на другие задачи, не произойдет прерывания
> от таймера, и ты получишь необходимую точность.

Хотелось бы без таких финтов просто. Запретить этой Виндос и всё. Ведь зависают же программы ! Значит всё таки делают это как то программисты.


 
Просто прохожий ©   (2003-07-01 11:15) [21]

>Кен © (01.07.03 04:19
> Вот на небольших кусках кода как раз можно запросто получить 0. )
Надеюсь, ты понял, что мы обсуждаем не GetTickCount, а GetCPUTick.
При использовании GetCPUTick 0 получить в принципе невозможно, т.к. на исполнение любой команды процессора нужен хотя бы один такт процессора. Это очень точная процедура, позволяет получить время исполнения даже одной команды процессора.

> Хотелось бы без таких финтов просто.
А где тут финты? Настоящих финтов ты не видел :)))


 
Asteroid ©   (2003-07-01 17:35) [22]

> Кен © (01.07.03 04:19)
Поставь приоритет на Real-time, больше никто не отвлечет проц от твоей программы.


 
NickBat ©   (2003-07-01 18:16) [23]

Если надо ускорить слабые места некоторых функций и процедур - смени компьютер на старенькую четверку.
Я серьезно. Как-то пришлось где-то полгода работать на древней четверке. Переписал свою программу с Делфи5 на Делфи3. И ужаснулся как медленно она работает, а на Селероне 800 просто летала. :)))
В результате когда опять сел за нормальный компьютер программа работала гораздо быстрее аналогов.


 
Кен ©   (2003-07-02 02:03) [24]

> Просто прохожий © (01.07.03 11:15)
> >Кен © (01.07.03 04:19
> >Вот на небольших кусках кода как раз можно запросто получить
> 0. )
> Надеюсь, ты понял, что мы обсуждаем не GetTickCount, а GetCPUTick.

Теперь понял.

> А где тут финты? Настоящих финтов ты не видел :)))
В многократном повторении, поиске минимального значения. Нечётко это как то.


> Asteroid © (01.07.03 17:35)
> > Кен © (01.07.03 04:19)
> Поставь приоритет на Real-time, больше никто не отвлечет
> проц от твоей программы.

А какой командой это делается ? В справке я чего-то не нашёл ничего путного.


 
Asteroid ©   (2003-07-02 02:17) [25]

> Кен © (02.07.03 02:03)
Делай полный поиск (с построением максимальной базы для поиска).

SetPriorityClass( GetCurrentProcess(), REALTIME_PRIORITY_CLASS );

Не забудь потом обратно поставить, а то фиг достучишься потом до программы без Application.ProcessMessages(); другие приложения вообще отдыхают:
SetPriorityClass( GetCurrentProcess(), NORMAL_PRIORITY_CLASS );


 
Sha ©   (2003-07-02 08:21) [26]

>Кен © (02.07.03 02:03)
>В многократном повторении, поиске минимального значения. Нечётко это как то.

Поиск в цикле минимального t - все очень четко. Это помогает избавиться от всего перечисленного выше, чего не позволяет сделать игра с приоритетами. Не ленись, походи по асм-сайтам, поиск по слову "оптимизация". Сходи на Intel. Узнаешь другие особенности, которые надо учитывать при точных измерениях. Там много интересного.


 
Radionov Alexey ©   (2003-07-02 08:34) [27]

см. GetThreadTimes - для NT


 
Кен ©   (2003-07-04 03:22) [28]

Что то эти тики не правильно показывают.

Вот два варианта функции для вычисления минимального значения.
Длина кода разная, а время выполнения одно и тоже. Как это может быть ?


function Min(const R1, R2: Cardinal):Cardinal; overload;
begin
// Result := R1;
// if R2 < R1 then Result := R2;

{ ( время - 6, длина кода - 11 байт )
mov ecx, eax
cmp eax, edx
jbe +$02
mov ecx, edx
mov eax, ecx
ret
}

// if R1 < R2 then Result := R1 else Result := R2;
{ ( время - 6, длина кода - 7 байт )
cmp edx,eax
jnb +$02
mov eax,edx
ret
}
end;


Кстати, я думал, что Дельфи оптимизирует код, а он нет. Даже в таких простых случаях.


 
Кен ©   (2003-07-04 03:26) [29]

Да, и как из Дебаггера текст можно проще скопировать ? У меня почему то не копируется.


 
Asteroid ©   (2003-07-04 03:51) [30]

> Кен © (04.07.03 03:22)
Не понимаю, как тебе в голову мог придти первый вариант. Второй однозначно быстрее. А время - может потому что он вызывает не то, что ты написал, а то, что с таким же именем перегружено (overload).


 
kaif ©   (2003-07-04 04:20) [31]

Я в свое время под DOS программы отлаживал с помощью звуков, которые посылал на динамик. Очень прикольно и прекрасно чувствуется любая разница. Боюсь в Windows-е этот финт не пройдет... Или после каждой такой посылки придется еще Application.ProcessMessages вызывать. Хотя не знаю...


 
Кен ©   (2003-07-04 04:56) [32]

> Asteroid © (04.07.03 03:51)
> > Кен © (04.07.03 03:22)
> Не понимаю, как тебе в голову мог придти первый вариант.

Мне разны еварианты приходили. Например я обнаружил, что замена

jnb +$02 (<)
на
jnbe +$02 (<=)
В некоторых случаях влияет на время выполнения. Почему непонятно.


> А время - может потому что он вызывает не то, что ты написал,
> а то, что с таким же именем перегружено (overload).

Но ассемблер то он тот показывет.
Остальные вызовы Min - это не с Cardinal, а с Float, Byte, Integer и чем то ещё.
Кстати, для Cardinal и Integer это будет одинаково вроде работать ?


> kaif © (04.07.03 04:20)
> Я в свое время под DOS программы отлаживал с помощью звуков,
> которые посылал на динамик. Очень прикольно и прекрасно
> чувствуется любая разница. Боюсь в Windows-е этот финт не
> пройдет...


Команда beep;

Или Sound :

procedure Sound(Frequency, Duration: Integer);
asm
push edx
push eax
call _Win32Platform
cmp eax, VER_PLATFORM_WIN32_NT
jne @@9X
call Windows.Beep
ret
@@9X:
pop eax
pop edx
push ebx
push edx
mov bx, ax
mov ax, 34DDh
mov dx, 0012h
cmp dx, bx
jnc @@2
div bx
mov bx, ax
in al, 61h
test al, 3
jnz @@1
or al, 3
out 61h, al
mov al, 0B6h
out 43h, al
@@1:
mov al, bl
out 42h, al
mov al, bh
out 42h, al
call Windows.Sleep
in al, 61h
and al, 0FCh
out 61h, al
jmp @@3
@@2:
pop edx
@@3:
pop ebx
end;



 
Asteroid ©   (2003-07-04 05:15) [33]

> Кен © (04.07.03 04:56)
Потому что в некоторых случаях (а именно равенство) он либо делал лишний mov, либо нет :)


 
Кен ©   (2003-07-04 05:25) [34]

> Asteroid © (04.07.03 05:15)
> > Кен © (04.07.03 04:56)
> Потому что в некоторых случаях (а именно равенство) он либо
> делал лишний mov, либо нет :)

Нет. Я учитывал это. Я как выше советовали зацикливал функцию и искал минимальные значение.

-
Жаль, что Дельфи код не оптимизирует. Ведь писать надо как понятнее, а не как быстрее будет выполнятся.
Может есть какие оптимизаторы кода ?


 
Sha ©   (2003-07-04 09:32) [35]

>Кен © (04.07.03 03:22)
>Что то эти тики не правильно показывают.

Современные процессоры могут исполнять несколько команд за один такт.
КАК ЖЕ ТЫ ЛЕНИВ.........


 
Anatoly Podgoretsky ©   (2003-07-04 10:56) [36]

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


 
Кен ©   (2003-07-05 02:40) [37]

> Anatoly Podgoretsky © (04.07.03 10:56)
> По вопросам оптимизации и времени выполнение команд надо
> идти на интел и брать ихний талмуд по этому поводу иначе
> ты ничего не поймешь в современных процессорах и как они
> работают, Почему напромер иногда если добавить несколько
> пустых команд процедура начинает работать быстрее.

А есть какие нибудь оптимизаторы кода написанные этими крутыми фирмами ?

Чтобы, например, написать функцию, из дебаггера вытянуть её код в ассемблере, оптимизировать его и засунуть обратно в Дельфи, но уже в виде asm-вставки.

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


 
Sha ©   (2003-07-05 10:59) [38]

Перво-наперво: оптимальным должен быть алгоритм, а уж потом его воплощение в твоей программе.
Лучший оптимизатор - голова.
Delphi тоже неплохо оптимизирует (распределение регистров, в частности), но она не знает толком, что тебе нужно было. Отсюда лишний код - обычно это разнообразные повторные проверки при работе со строками, неоптимальные проверки окончания цикла, повторное вычисление выражений (особенно индексных).
В принципе, ты сам можешь значительно увеличить скорость работы своей программы, если в перечисленных местах не будешь полагаться на Delphi, а оптимизировать исходник самостоятельно. Для этого даже BASM не требуется, просто нужен небольшой опыт. Всегда смотри во что преобразуется твой код, и постепенно поймешь как надо писать, чтобы все работало быстро. Правда, обилие continue, break, repeat вместо while не всегда хорошо смотрится.


 
Anatoly Podgoretsky ©   (2003-07-05 11:23) [39]

Кен © (05.07.03 02:40)
Ничего не вступает в противоречие, кроме твоих знаний.
Использование BASM в твоем случае приведет к замедлени работы программы, Дельфи в отличии от тебя знает какие последовательности ассемблерных команд оптимальнее.
В неопытных руках ассемблер приводит к видимому на глаз замедлению, проверено опытом.
Главный источник оптимизации это алгоритмы.

Кроме того, ты уже сходил на Интел за белой книгой по оптимизации под Пентиум?


 
Кен ©   (2003-07-06 03:55) [40]

> Sha © (05.07.03 10:59)
> . Всегда смотри во что преобразуется твой код, и постепенно
> поймешь как надо писать, чтобы все работало быстро.

А нельзя, чтобы программа сама делала вариации из моего кода и смотрела во что он преобразуется, а потом оставляла самый скоросной вариант ?



Страницы: 1 2 вся ветка

Текущий архив: 2003.07.21;
Скачать: CL | DM;

Наверх




Память: 0.59 MB
Время: 0.015 c
4-68124
cain
2003-05-21 09:54
2003.07.21
мышь над компонентом


1-67812
bloodman
2003-07-09 16:44
2003.07.21
PE + DLL


7-68104
Makhanev A.S.
2003-05-10 16:18
2003.07.21
TSHellTreeView: как запретить проверку диска 3.5 (A)?


1-67912
Mishenka
2003-07-07 19:56
2003.07.21
Свойство Enabled для UpDown...


3-67680
Александр Ч_
2003-06-26 16:58
2003.07.21
Перебор записей в DataSet