Главная страница
    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.56 MB
Время: 0.009 c
3-67703
Status_I
2003-06-24 00:27
2003.07.21
LookUp-поле


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


14-68062
Карлсон
2003-07-04 23:50
2003.07.21
давайте шварцами меряться!


14-68035
Makhanev A.S.
2003-07-03 05:37
2003.07.21
Сидеть по ночам: ДА или НЕТ?


1-67776
Smart
2003-07-08 07:25
2003.07.21
Проблема с TListView





Afrikaans Albanian Arabic Armenian Azerbaijani Basque Belarusian Bulgarian Catalan Chinese (Simplified) Chinese (Traditional) Croatian Czech Danish Dutch English Estonian Filipino Finnish French
Galician Georgian German Greek Haitian Creole Hebrew Hindi Hungarian Icelandic Indonesian Irish Italian Japanese Korean Latvian Lithuanian Macedonian Malay Maltese Norwegian
Persian Polish Portuguese Romanian Russian Serbian Slovak Slovenian Spanish Swahili Swedish Thai Turkish Ukrainian Urdu Vietnamese Welsh Yiddish Bengali Bosnian
Cebuano Esperanto Gujarati Hausa Hmong Igbo Javanese Kannada Khmer Lao Latin Maori Marathi Mongolian Nepali Punjabi Somali Tamil Telugu Yoruba
Zulu
Английский Французский Немецкий Итальянский Португальский Русский Испанский