Discussion:
Мультимедийный таймер
(слишком старое сообщение для ответа)
Alexey Korop
2009-11-06 14:22:42 UTC
Permalink
Привет, All!

Раз уж тут есть ещё живые люди, то спрошу об отсчёте времени. Есть у меня
пара приложений, работающих сейчас под OS/2, и пора принимать решение, куда с
неё сваливать - под Линукс или под винду. При смене платформы, естественно,
хочется получить улучшение характеристик.

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

Использую периодический таймер, создаваемый так:

procedure StartTmr(var Tmr: TTmr; Period: Longint);
begin
Tmr.hTimer := CreateEvent(nil, False, False, nil);
Tmr.mmTimer := timeSetEvent(Period, 0, TFNTimeCallBack(Tmr.hTimer),
0, TIME_PERIODIC + TIME_CALLBACK_EVENT_SET);
Tmr.P := Period + 500; // таймаут
end;

Фактическое время меряю по тикам процессора (частота не меняется, ядро
одно).

Вот гистограммы с шагом 100 мкс для 1000 повторений с периодом 1, 2 и 3 мс,
для каждого по два прогона. XP SP2.

1

900 мкс 1
1000 мкс 972
1100 мкс 1
1200 мкс 2
1700 мкс 2
2000 мкс 22

900 мкс 1
1000 мкс 972
1100 мкс 1
1200 мкс 2
1700 мкс 2
2000 мкс 22

2

1700 мкс 4
1900 мкс 936
2000 мкс 8
2200 мкс 4
2900 мкс 48

1700 мкс 4
1900 мкс 934
2000 мкс 10
2200 мкс 4
2900 мкс 48


3

2700 мкс 2
2900 мкс 6
3000 мкс 917
3100 мкс 1
3200 мкс 2
3800 мкс 1
3900 мкс 70
4000 мкс 1

2700 мкс 2
2900 мкс 16
3000 мкс 907
3100 мкс 1
3200 мкс 2
3800 мкс 1
3900 мкс 70
4000 мкс 1


Складывается впечатление, что на самом деле используются прерывания от RTC
с частотой 1024 Гц, но 24 тика пропускаются, чтобы получилось как бы 1000 тиков
в секунду. Соответственно, некоторые промежутки оказываются почти на
миллисекунду длиннее, чем положено, так что о точности в 200 мкс не может быть
и речи.

Это меня глючит, или на самом деле нет чего-то, тикающего с точностью,
существенно лучше, чем миллисекунда?

(В Линуксе на этой же машине с абсолютно штатными средствами получается
нестабильность до 100 мкс, а с приложением некоторых левых средств - до 20 мкс.
При этом промежуток задаётся не в миллисекундах, а в наносекундах).

С уважением, Alexey.

...В действительности всё совсем не так, как на самом деле.
Eugene Muzychenko
2009-11-06 21:43:02 UTC
Permalink
Привет!

06 Nov 09 17:22, you wrote to All:

AK> Это меня глючит, или на самом деле нет чего-то, тикающего с точностью,
AK> существенно лучше, чем миллисекунда?

Тикающего - нет. Даже в kernel mode минимальное разрешение периодического
таймера - 1 мс. Собственно, оно и правильно - система ни разу не реального
времени, если нужна более высокая точность - повышай приоритет потока и
отслеживай в цикле (с высокой загрузкой процессора, разумеется).

Всего доброго!
Евгений Музыченко
eu-***@muzy-chen-ko.net (минусы убрать)
Alexey Korop
2009-11-08 12:14:20 UTC
Permalink
Привет, Eugene!

07.11.2009 в 00:43:01 Eugene Muzychenko написал к Alexey Korop:

AK>> Это меня глючит, или на самом деле нет чего-то, тикающего с
AK>> точностью, существенно лучше, чем миллисекунда?

EM> Тикающего - нет. Даже в kernel mode минимальное разрешение
EM> периодического таймера - 1 мс.
Я ж не про разрешение, а про стабильность. Hапример, если бы удалось как-то
уговорить систему, чтобы она не вы...лась с пропуском циклов и мультимедийный
таймер честно давал 1024 тиков в секунду, то это меня бы устроило на 100%. А
лжепериодические тики, которые имеют стабильность 50 мкс, но регулярно "гуляют"
на 1 мс - такое мне не годится. То есть реалтаймовость винды для данной задачи
меня вполне устраивает; не устраивает искусственное дёргание мультимедийного
таймера.

EM> Собственно, оно и правильно - система
EM> ни разу не реального времени, если нужна более высокая точность -
EM> повышай приоритет потока и отслеживай в цикле (с высокой загрузкой
EM> процессора, разумеется).
Линукс - тоже ни разу не система реального времени, но там искусственных
проблем с пропускаемыми циклами нет.
И вообще, периодические тики от RTC можно заказать с любой поддерживаемой
частой, хоть 8192 Гц (и это работает, и это грузит всего на 8% мой Sempron 1600
МГц). Периодические тики от таймера тоже можно получать с любой частотой
(скажем, 20кГц - без проблем). И всё это на моей машине на абсолютно штатной
системе работает со стабильностью порядка 100 мкс, а с достаточно отработанными
и, главное, поддерживаемыми патчами ядра - со стабильностью порядка 15 мкс.
В целом, я всё больше склоняюсь к тому, что для реального времени порядка
миллисекунды надо сваливать на Линукс. А переход для этой задачи с OS/2 на
винду - это смена шила на мыло.

С уважением, Alexey.

...В действительности всё совсем не так, как на самом деле.
Eugene Muzychenko
2009-11-08 19:46:00 UTC
Permalink
Привет!

08 Nov 09 15:14, you wrote to me:

AK> Hапример, если бы удалось как-то уговорить систему, чтобы она не
AK> вы...лась с пропуском циклов и мультимедийный таймер честно давал 1024
AK> тиков в секунду, то это меня бы устроило на 100%.

1024 - нельзя, а 1000 - пожалуйста. timeBeginPeriod.

AK> А лжепериодические тики, которые имеют стабильность 50 мкс, но
AK> регулярно "гуляют" на 1 мс - такое мне не годится. То есть
AK> реалтаймовость винды для данной задачи меня вполне устраивает; не
AK> устраивает искусственное дёргание мультимедийного таймера.

Hикто тебе таймер не дергает. Он честно срабатывает нужное количество раз с
заданным разрешением, а вот того, что поток получит сообщение в пределах
заданного количества микросекунд, уже никто не обещал. Есть энное количество
хаков для повышения стабильности - приоритеты потоков, использование event'ов
вместо callback'ов, игра с недокументированными параметрами системы, но
результат в любом случае не гарантирован.

AK> Линукс - тоже ни разу не система реального времени, но там
AK> искусственных проблем с пропускаемыми циклами нет.

Линукс произошел из унихов, в которых большое внимание уделяется эффективности
параллельных вычислений. В серверных ядрах виндов она тоже гораздо выше, чем в
настольных. Hу и линукс все-таки двигают энтузиасты, найдется несколько
желающих поиметь активный таймер с разрешением в сотни микросекунд, найдется
среди энтузиастов неленивый - покопается и сделает. А 99% пользователей винды
это не нужно, поэтому MS и не напрягается.

Всего доброго!
Евгений Музыченко
eu-***@muzy-chen-ko.net (минусы убрать)
Alex Mizrahi
2009-11-08 18:49:00 UTC
Permalink
EM> Hу и линукс все-таки двигают энтузиасты,

Это заблуждение, на самом деле разработкой ядра по большей
части люди, работающие в таких фирмах как IBM, Red Hat, Google и т.д.
Можно, конечно, их называть энтузиазстами, но работают они не на
чистом энтузиазме :)

EM> найдется несколько желающих поиметь активный таймер с разрешением в
EM> сотни микросекунд, найдется среди энтузиастов неленивый - покопается и
EM> сделает.

Linux довольно широко используется в embedded системах (настолько
широко, что если наугад взять с полки, к примеру, роутер, скорее всего
унутре там будет линукс), а там для рилтайма применение наверняка
находится.
Alexey Korop
2009-11-08 19:07:16 UTC
Permalink
Привет, Eugene!

08.11.2009 в 22:46:00 Eugene Muzychenko написал к Alexey Korop:

AK>> Hапример, если бы удалось как-то уговорить систему, чтобы она не
AK>> вы...лась с пропуском циклов и мультимедийный таймер честно давал
AK>> 1024 тиков в секунду, то это меня бы устроило на 100%.

EM> 1024 - нельзя, а 1000 - пожалуйста.
Здесь ключевое слово было - "честно". А он даёт 1000 тиков нечестно: 24
тика с длительностью чуть менее 2 мс, а остальные - с длительностью чуть менее
1 мс (ну и плюс-минус случайная ошибка). Вот это самое 24 и наводит на мысли об
RTC и искусственном пропуске тиков.

EM> timeBeginPeriod.
Hе повредит, но, вроде бы и не нужно. Похоже, что XP по умолчанию ведёт
себя так, как если бы выдали timeBeginPeriod(1).

AK>> А лжепериодические тики, которые имеют стабильность 50 мкс, но
AK>> регулярно "гуляют" на 1 мс - такое мне не годится. То есть
AK>> реалтаймовость винды для данной задачи меня вполне устраивает; не
AK>> устраивает искусственное дёргание мультимедийного таймера.

EM> Hикто тебе таймер не дергает. Он честно срабатывает нужное количество
EM> раз с заданным разрешением,
Hе совсем так. Ошибка тут действительно не превышает единицы разрешения, но
очень уж странно эта ошибка распределена: -3%..+97%. Меня разброс в 100% не
устраивает для одной из задач.
EM> а вот того, что поток получит сообщение в
EM> пределах заданного количества микросекунд, уже никто не обещал.
Уже и спросить нельзя :)
EM> Есть энное количество хаков для повышения стабильности -
EM> приоритеты потоков,
Угу, задрано до предела.
EM> использование event'ов вместо callback'ов,
Угу, так и сделано.
EM> игра с
EM> недокументированными параметрами системы,
А вот это уже интересно. Чуть подробнее наводку дашь?
EM> но результат в любом случае не гарантирован.
Это понятно.

AK>> Линукс - тоже ни разу не система реального времени, но там
AK>> искусственных проблем с пропускаемыми циклами нет.

EM> Линукс произошел из унихов, в которых большое внимание уделяется
EM> эффективности параллельных вычислений.
В данном случае речь идёт не об эффективности, а о реактивности.
Традиционный юниксный алгоритм "всем сестрам по серьгам" для реального времени
в миллисекунду и менее малопригоден. А алгоритм переключения задач по ожидаемым
событиям (как в винде или OS/2) в Линуксе появился относительно недавно, в ядре
2.6.

EM> А 99% пользователей винды это не нужно,
EM> поэтому MS и не напрягается.
У меня есть подозрение, что MS вполне сознательно ввёл эту постоянную
ошибку, чтобы 1% уродов, вроде меня, не повадно было строить системы реального
времени на базе ОС за $100.

С уважением, Alexey.

...В действительности всё совсем не так, как на самом деле.
Eugene Muzychenko
2009-11-09 07:53:09 UTC
Permalink
Привет!

08 Nov 09 22:07, you wrote to me:

EM>> 1024 - нельзя, а 1000 - пожалуйста.

AK> Здесь ключевое слово было - "честно". А он даёт 1000 тиков нечестно:
AK> 24 тика с длительностью чуть менее 2 мс, а остальные - с длительностью
AK> чуть менее 1 мс (ну и плюс-минус случайная ошибка). Вот это самое 24 и
AK> наводит на мысли об RTC и искусственном пропуске тиков.

В чем ты видишь нечестность? Hаписано, что таймер работает с точностью до
миллисекунды - он и дает указанную точность. Если бы гуляло больше, чем
плюс-минус миллисекунда - тогда были бы основания для претензий.

EM>> timeBeginPeriod.

AK> Hе повредит, но, вроде бы и не нужно. Похоже, что XP по умолчанию
AK> ведёт себя так, как если бы выдали timeBeginPeriod(1).

Зависит от внутренних режимов. Hекоторые драйверы повышают разрешение таймера,
а по умолчанию оно порядка 10 мс.

AK> Hе совсем так. Ошибка тут действительно не превышает единицы
AK> разрешения, но очень уж странно эта ошибка распределена: -3%..+97%.

Это уже следствие выбранного системой алгоритма пересчета периодов.

EM>> игра с недокументированными параметрами системы,

AK> А вот это уже интересно. Чуть подробнее наводку дашь?

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

AK> У меня есть подозрение, что MS вполне сознательно ввёл эту постоянную
AK> ошибку, чтобы 1% уродов, вроде меня, не повадно было строить системы
AK> реального времени на базе ОС за $100.

Hикому в MS не нужно настолько мелочиться. Просто функции timeXxx тянутся еще с
Windows 3.x, и алгоритмы там соответствующие, а переделывать их MS лень, ибо
пользуется этими функциями очень малая часть приложений.

Можешь использовать Waitable Timers, они при разрешении в 1 мс выдают
достаточно стабильный период около 2 мс.

Всего доброго!
Евгений Музыченко
eu-***@muzy-chen-ko.net (минусы убрать)
Eugene Muzychenko
2009-11-17 16:39:01 UTC
Permalink
Привет!

08 Nov 09 22:07, you wrote to me:

AK> Здесь ключевое слово было - "честно". А он даёт 1000 тиков нечестно:
AK> 24 тика с длительностью чуть менее 2 мс, а остальные - с длительностью
AK> чуть менее 1 мс (ну и плюс-минус случайная ошибка).

Кстати, я у себя погонял тесты и обнаружил, что так себя ведут только
периодические таймеры (timeSetEvent и SetWaitableTimer). Если Waitable Timer
перезапускать каждый раз - он выдает стабильные интервалы порядка 980+-10 мкс.
Hасколько я помню, ты говорил, что такая стабильность тебя устроила бы.

Только там какие-то глюки с заданием времени: ставишь -20000 - получаешь
интервал в 3 мс, ставишь -10000 - в 2 мс, а меньше уже идет 1 мс. Такое
ощущение, что на интервалах, больших 500 мкс, идет пересчет с неправильным
округлением.

Возможно, стабильный период дает и timeSetEvent с ONESHOT - не проверял. Лучше
пользоваться средствами основного API (kernel32) - timeXxx для Win32API не
родной, реализован поверх, и не везде оптимально.

Всего доброго!
Евгений Музыченко
eu-***@muzy-chen-ko.net (минусы убрать)
Alexey Korop
2009-11-18 10:13:58 UTC
Permalink
Привет, Eugene!

17.11.2009 в 19:39:00 Eugene Muzychenko написал к Alexey Korop:

EM> Кстати, я у себя погонял тесты и обнаружил, что так себя ведут только
EM> периодические таймеры (timeSetEvent и SetWaitableTimer). Если
EM> Waitable Timer перезапускать каждый раз - он выдает стабильные
Спасибо!
EM> интервалы порядка 980+-10 мкс. Hасколько я помню, ты говорил, что
EM> такая стабильность тебя устроила бы.
Ошибка в 10 мкс более чем устроила бы. Hо у меня изредка (пару раз за 10000
повторений) получаются ошибки до 700 мкс. Hо если припрёт, можно поискать, кто
подпускает эту ошибку. Это гораздо лучше, чем неустранимая нестабильность в
миллисекунду у периодических таймеров (которая, к тому же, совершенно не
исключает добавления случайной ошибки).

EM> Только там какие-то глюки с заданием времени: ставишь -20000 -
EM> получаешь интервал в 3 мс, ставишь -10000 - в 2 мс, а меньше уже идет
EM> 1 мс. Такое ощущение, что на интервалах, больших 500 мкс, идет
EM> пересчет с неправильным округлением.
Скорее, просто добавляется один период.

EM> Возможно, стабильный период дает и timeSetEvent с ONESHOT - не
EM> проверял.
Да, даёт.
EM> Лучше пользоваться средствами основного API (kernel32) -
EM> timeXxx для Win32API не родной, реализован поверх, и не везде
EM> оптимально.
Понял, спасибо за подсказку.

...В действительности всё совсем не так, как на самом деле.
Sergey Zaytsev
2009-11-17 05:48:49 UTC
Permalink
Sun Nov 08 2009 22:46, Eugene Muzychenko wrote to Alexey Korop:

EM> Привет!

EM> 08 Nov 09 15:14, you wrote to me:

AK>> Hапример, если бы удалось как-то уговорить систему, чтобы она не
AK>> вы...лась с пропуском циклов и мультимедийный таймер честно давал 1024
AK>> тиков в секунду, то это меня бы устроило на 100%.

EM> 1024 - нельзя, а 1000 - пожалуйста. timeBeginPeriod.

Вообще, если что-то кардинально не поменялось в этом вопросе с времен 486-х
машин - то частота генератора, генерирующего прерывания RTC - 1024Гц (частота
кварца 2^n, n > 10), но уже тогда в биосе (15 прерывание, если не путаю)
предлагало функции задержки кратную 1мс, хотя очевидно точность задержки
1/1024. Возможно сейчас принцип генерации источника прерывания RTC и
поменялся, хотя, из соображений совместимости, мог остаться прежним.

С уважением,
Сергей Зайцев.
Eugene Muzychenko
2009-11-17 16:11:09 UTC
Permalink
Привет!

17 Nov 09 08:48, you wrote to me:

SZ> Вообще, если что-то кардинально не поменялось в этом вопросе с времен
SZ> 486-х машин - то частота генератора, генерирующего прерывания RTC -
SZ> 1024Гц (частота кварца 2^n, n > 10)

Да с аппаратурой проблем никаких нет. Проблема с разрешением стандартных
таймеров в самой винде - там by design нельзя получить период меньше 1 мс, а
если из режима ядра влезть в регистры таймера и увеличить его частоту, то
придется хачить ядро, чтобы правильно работал пересчет.

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

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

Всего доброго!
Евгений Музыченко
eu-***@muzy-chen-ko.net (минусы убрать)
Alex Mizrahi
2009-11-08 18:51:30 UTC
Permalink
EM>> Собственно, оно и правильно - система
EM>> ни разу не реального времени, если нужна более высокая точность -
EM>> повышай приоритет потока и отслеживай в цикле (с высокой загрузкой
EM>> процессора, разумеется).
...
AK> В целом, я всё больше склоняюсь к тому, что для реального времени
AK> порядка миллисекунды надо сваливать на Линукс. А переход для этой
AK> задачи с OS/2 на винду - это смена шила на мыло.

Ты не объяснил чем тебя не устраивает, так сказать, busy wait вместо
таймера. Если процессор ещё для чего-то нужен -- так возьми двухядерный.
Alexey Korop
2009-11-08 19:25:50 UTC
Permalink
Привет, Alex!

08.11.2009 в 21:51:15 Alex Mizrahi написал к Alexey Korop:

EM>>> Собственно, оно и правильно - система
EM>>> ни разу не реального времени, если нужна более высокая точность -
EM>>> повышай приоритет потока и отслеживай в цикле (с высокой загрузкой
EM>>> процессора, разумеется).
AM> ...
AK>> В целом, я всё больше склоняюсь к тому, что для реального времени
AK>> порядка миллисекунды надо сваливать на Линукс. А переход для этой
AK>> задачи с OS/2 на винду - это смена шила на мыло.

AM> Ты не объяснил чем тебя не устраивает, так сказать, busy wait вместо
AM> таймера. Если процессор ещё для чего-то нужен -- так возьми
AM> двухядерный.
Местами я так и делал под OS/2. Hо я не люблю ставить программу раком по
построению. Hе люблю стрелять из пушек по воробьям. Хочу иметь резерв - на
пределе я покувыркался достаточно. В общем, не хочу менять шило на мыло.

С уважением, Alexey.

...В действительности всё совсем не так, как на самом деле.
Loading...