Экспертная система Delphi.int.ru

Сообщество программистов
Общение, помощь, обмен опытом

Логин:
Пароль:
Регистрация | Забыли пароль?

Delphi.int.ru Expert

Другие разделы портала

Переход к вопросу:

#   

Статистика за сегодня:  


Лучшие эксперты

Подробнее »



Вопрос # 4 094

/ вопрос открыт /

Здравствуйте, уважаемые эксперты!
объясните мне пожалуйста русским языком чем различаются таймеры

QuertyPerformanceCounter и QuertyPerformanceFrequency???

И что они делают. А ещё если не трудно прокомментируйти как происходит рассчет времени в такой конструкции:

QueryPerformanceFrequency(freq);
QueryPerformanceCounter(start);
{фрагмент кода}
QueryPerformanceCounter(stop);

и время равно Time=stop-sart/freq

amigo Вопрос ожидает решения (принимаются ответы, доступен мини-форум)

Вопрос задал: amigo (статус: 1-ый класс)
Вопрос отправлен: 26 апреля 2010, 20:14
Состояние вопроса: открыт, ответов: 2.

Ответ #1. Отвечает эксперт: Паровоз

Здравствуйте, amigo!
QueryPerformanceCounter - счетчик производительности, который увеличивается с 0, начиная с включения питания. Частота этого счетчика возвращается QueryPerformanceFrequency. Для отсчета времени нужно разделить значение счетчика производительности на частоту:

var
  time: Int64;
  lpPerformanceCount: Int64;
  lpFrequency: Int64;
  koef: Extended;
begin
  QueryPerformanceCounter(lpPerformanceCount);
  time:=lpPerformanceCount;
  .....................//измеряемая операция
  QueryPerformanceCounter(lpPerformanceCount);
  time := lpPerformanceCount - time;
  koef:=1.0E9/lpFrequency;
  time:=Round(time*koef);//наносекунды
end;

Ответ отправил: Паровоз (статус: 10-ый класс)
Время отправки: 26 апреля 2010, 23:28

Ответ #2. Отвечает эксперт: Вадим К

Здравствуйте, amigo!
Я могу сказать одно - этот код содержит маленькую ошибку:) даже две.
эти две функции - не таймеры и сказать чем они различаются нельзя.
Суть такая. Представьте, что в системе есть глобальный таймер (почти как компонент TTimer, и код его события OnTimer выглядит где то так

  c:= c+1;
То есть, он просто увеличивает внутренний счетчик.
При старте системы он равен нулю, но может и какому то числу, нас это волновать не должно. Также счетчик может увеличиваться не на 1, на 5 или 10. Но это тоже личные проблемы системы.
Следующее, что нам хотелось бы знать, это как часто щелкает счетчик. Так как без этого значения можно использовать только для сравнения двух замеров и их отношения. Для этого есть функция QueryPerformanceFrequency ( в тексте вопроса она написана с лишней буквой t). Эта функция выдаст, сколько раз в секунду "щелкает таймер". Следует помнить следующее, что на разных версиях операционной системы эта функция может выдавать разные числа. более того, оно может быть другим после перезапуска системы. Операционная система( ОС ) гарантирует, что оно не поменяется во время работы.

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

Итого, все становиться на свои места. Если нам нужно замерить скорость выполнения некого участка кода, мы просто дважды вызываем функцию QueryPerformanceCounter и записываем значения. Вычитая с одного второе, мы получим кол-во щелчков таймера между двумя событиями. И если хотим перевести в секунды, просто разделим на значение функции QueryPerformanceFrequency. (а ее можно к примеру вызвать один раз при старте приложения).

Формула, приведенная в Вашем вопросе - неверная. правильная будет выглядеть где то так
QueryPerformanceFrequency(@freq);
QueryPerformanceCounter(@start);
{фрагмент кода}
QueryPerformanceCounter(@stop);
и время равно Time=(stop-start)/freq;

А почему там нужны скобки, попробуйте догадаться самостоятельно.

Ответ отправил: Вадим К (статус: Академик)
Время отправки: 26 апреля 2010, 23:37
Оценка за ответ: 5

Комментарий к оценке: ))Спасибо Вадим. А то нигде не дают какого-либо вразумительного объяснния))) Спасибо большое, а код я взял у какогото американского просграмиста)))

Мини-форум вопроса

Всего сообщений: 9; последнее сообщение — 27 апреля 2010, 22:30; участников в обсуждении: 3.
min@y™

min@y™ (статус: Доктор наук), 27 апреля 2010, 08:12 [#1]:

Раз уж речь зашла про эти 2 функции, добавлю, пожалуй, таймер, построенный на них.
{
HRT := THRTimer.Create;
HRT.StartTimer;  Сброс таймера в ноль
HRT.ReadTimer;   Возвращает отсчитанное время в миллисекундах
начиная со времени старта
}
 
unit HRTimer;
 
interface
 
uses Windows;
 
type
  // --------------------- Класс - высокоточный таймер -------------------------
  THRTimer = class(TObject)
    constructor Create;
    function StartTimer: Boolean; // Обнуление таймера
    function ReadTimer: Double;   // Чтение значения таймера в миллисекундах
  private
    StartTime: Double;
    ClockRate: Double;
  public
    Exists: Boolean;    // Флаг успешного создания таймера
  end;
 
var
  Timer: THRTimer; // Глобальая переменная. Создаётся при запуске программы
 
{ Фукнция высокоточной задержки.
 Delphi:
   Синтаксис: function HRDelay(const Milliseconds: Double): Double;
   Milliseconds: Double - задержка в миллисекундах (может быть дробной)
   Результат функции - фактически произошедшая задержка с погрешностью.
   Пример вызова функции: X:= HRDelay(100.0); или HRDelay(100.0);
 
 C++Builder:
   Синтаксис: double HRDelay(const double Milliseconds);
   Double Milliseconds - задержка в миллисекундах (может быть дробной)
   Результат функции - фактически произошедшая задержка с погрешностью.
   Пример вызова функции: double X = HRDelay(100.0); или HRDelay(100.0);}
function HRDelay(const Milliseconds: Double): Double;
 
implementation
 
function HRDelay(const Milliseconds: Double): Double;
begin
  Timer.StartTimer();
  repeat
    Result:= Timer.ReadTimer();
  until Result >= Milliseconds;
end;
 
{ THRTimer }
 
constructor THRTimer.Create;
var
  QW: LARGE_INTEGER;
begin
  inherited Create;
  Exists := QueryPerformanceFrequency(Int64(QW));
  ClockRate := QW.QuadPart;
end;
 
function THRTimer.StartTimer: Boolean;
var
  QW: LARGE_INTEGER;
begin
  Result := QueryPerformanceCounter(Int64(QW));
  StartTime := QW.QuadPart;
end;
 
function THRTimer.ReadTimer: Double;
var
  ET: LARGE_INTEGER;
begin
  QueryPerformanceCounter(Int64(ET));
  Result := 1000.0 * (ET.QuadPart - StartTime) / ClockRate;
end;
 
initialization
  Timer:= THRTimer.Create();
 
finalization
  Timer.Free();
 
end.
Делаю лабы и курсачи по Delphi и Turbo Pascal. За ПИВО! Пишите в личку, а лучше в аську. А ещё лучше - звоните в скайп!
amigo

amigo (статус: 1-ый класс), 27 апреля 2010, 18:30 [#2]:

Ну, то что там скобки я понимаю)))) просто торопился наверно)У меня в коде стоп и старт в скобках)
Вадим К

Вадим К (статус: Академик), 27 апреля 2010, 18:35 [#3]:

Можно использовать и GetTickCount - она возвращает миллисекунды от запуска системы.
классический код
var t:DWORD;
begin
 t := GetTickCount;
//какой то код
 t := GetTickCount -t;
 showmessage(insttostr(t));
Галочка "подтверждения прочтения" - вселенское зло.
amigo

amigo (статус: 1-ый класс), 27 апреля 2010, 18:40 [#4]:

Я так пробовал))) Но к моему большому удивлению он выдавал мне 0, получалось чт офрагмент кода не тратит никакого времени))) Если б было так всё просто я б не ломал голову с этими qerty))
min@y™

min@y™ (статус: Доктор наук), 27 апреля 2010, 18:44 [#5]:

Цитата (Вадим К):

Можно использовать и GetTickCount

Да, но только на сравнительно больших интервалах времени. При малых интервалах (< 15 мс) будет очень большая погрешность. А вот тот код, который привёл я, реально используется у нас на производстве. Он даёт погрешность ±2 мкс независимо от интервала, что нам очень помогло для отсчёта коротких задержек.
Делаю лабы и курсачи по Delphi и Turbo Pascal. За ПИВО! Пишите в личку, а лучше в аську. А ещё лучше - звоните в скайп!
amigo

amigo (статус: 1-ый класс), 27 апреля 2010, 18:49 [#6]:

У меня пока не призводство))) Это типо курсовой, надо оценить время и сложность во теории алгоритмов) А за код спасиб, может пригодится
Вадим К

Вадим К (статус: Академик), 27 апреля 2010, 22:23 [#7]:

Ну так если код очень быстрый, то надо вызвать функцию 1000 или 100000 раз и замерить. Таким образом, даже с GetTickCount можно получить хорошую точность. Даже с наручными часами:)

Конечно, если на машине параллельно работает ещё 300 программ, то нужно это учитывать. Для ещё большего уточнения - можно запускать по несколько раз.

Вот только в цикле надо запускать аккуратно. Делфи новой версии может сообразить, что функция с одними и теми же параметрами запускается и с оптимизировать:) Был случай, с фортран компилятором, который очень долго компилировал код, а потом исполнял его практически моментально. Оказалось, он понял, что исходные данные константные и результат выполнения будет один и тот же и результирующий оптимизированный код выглядел просто как вывод результата (одна строка).
Галочка "подтверждения прочтения" - вселенское зло.
amigo

amigo (статус: 1-ый класс), 27 апреля 2010, 22:29 [#8]:

))), Интересно. Да мне не нужна большая точность. 1 курс всё таки))) Я думаю он не будет при проверке до наносекунды проверять))) Но всё равно спасиб, хоть понял что это
min@y™

min@y™ (статус: Доктор наук), 27 апреля 2010, 22:30 [#9]:

Вадюх, напомни мне завтра, я тебе пример пришлю готовый.
Делаю лабы и курсачи по Delphi и Turbo Pascal. За ПИВО! Пишите в личку, а лучше в аську. А ещё лучше - звоните в скайп!

Чтобы оставлять сообщения в мини-форумах, Вы должны авторизироваться на сайте.

Версия движка: 2.6+ (26.01.2011)
Текущее время: 22 февраля 2025, 11:44
Выполнено за 0.03 сек.