Текущий архив: 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