Как стать автором
Обновить

Комментарии 65

Почему не QueryPerformanceCounter()?
The TSC is generally readable via the RDTSC instruction from user mode, making it the fastest, easiest, and most precise time base available on modern machines.

Alas, it is rather unsafe to use. [...]
На мой взгляд, само получение значения tsc затратит меньше процессорных тактов и данные получатся точнее (как вместо sleep я использовал NtDelayExecution. Еще мелочь, но QueryPerformanceCounter возвратил мне 0 на системе PIII с win2k, а tsc — нормальное значение.
Хотя, я не против, конечно QueryPerformanceCounter, QueryPerformanceFrequency также вполне можно использовать.

Я еще поэкспериментирую с применением этих функций.
НЛО прилетело и опубликовало эту надпись здесь
пока у вашей операционной системы не появится real-time scheduler говорить о каких бы то ни было точных измерениях времени бесполезно… thread/process switch отжирает драгоценное время, обработка прерываний происходит в ущерб программам уровня пользователя. опираться на полученные результаты нет смысла. единственное, что гарантируют все эти функции — процесс проспит не меньше указанного интервала времени. под различной нагрузкой в реальных приложениях все это треснет по швам к сожалению
Дополнительная информация:
1. На некоторых процессорах значение RDTSC может быть рассинхронизировано для разных ядер. Вы никогда не знаете, на каком именно ядре в данный момент выполняется Ваша программа (если только не выставили affinity mask, да и то, я бы не был на 100% уверен), поэтому чтение TSC процессорной командой иногда само вносит существенные искажения. В SMP системах RDTSC вообще по определению рассинхронизировано между процессорами. Поэтому думаю, что performance counters лучший метод для точных замеров времени в прикладных программах для Windows.
2. Программу для Windows не стоит писать так, чтобы она зависела от задержек в функциях типа Sleep. Если речь идет об управлении устройством в реальном времени, то нужно выносить все это в драйвер. В других случаях использовать мультимедийные функции для таймирования. А если кто-то пишет часы для desktop-а – вероятно лучше всего подойдут waitable timers.
Используя для оптимизации кода профайлер из состава библиотеки Jedi, позволил себе исследовать его с целью определения не только общего времени выполнения блока кода, количества запусков и, соответственно, среднего времени операции, но и максимального времени выполнения одиночной операции. Обнаружилось нечто интересное — для блоков кода со средним временем выполнения менее 1 мс значение максимального времени давало часто 16 мс, а то и 32. Особенно когда общее время выполнения при сотнях и тысячах запусков как раз получается те же 16 или 32 мс.

В том профайлере для замера временных отсечек используется функция GetTickCount. Не подскажете, чем заменить ее для более точного отсчета малых интервалов?
BOOL WINAPI QueryPerformanceCounter(
__out LARGE_INTEGER *lpPerformanceCount
);
denim, все так, но описанное хотя бы чуть-чуть поднимает и пробует решить проблему…

sysprg, к сожалению не было возможности проверить и убедиться в преимуществах QueryPerformanceCounter на многоядерных системах, но судя по сказанному Вами, его действительно лучше использовать. Прежде всего я искал способ получить задержки, и для эксперимента, в котором RDTSC служил для подсчета, он пока мне сгодился.
А задержки эти, увы с нужным интервалом не получил: тоже верно — нужен драйвер. Хотя если задержки до 1 мс, можно обойтись, как я описал (NtDelayExecution, sleep, таймеры).
Даже если выставить real-time приоритет для thread, то все равно из-за подкачки/откачки страниц или еще каких-то влияний ядро Windows не всегда мгновенно активирует пользовательскую программу, поэтому писать на прикладном уровне для Windows что-то зависящее от задержек в 1 миллисекунду и меньше — вообще неправильно и малореально. Как и для Linux. С такими вещами нужно или на уровне ядра работать, или использовать специализированные системы реального времени. Как минимум в Windows или в Linux нужно выключать своппинг и не запускать в параллель всякие мультимедийные программы. Но это уже превращает программу в пригодную к использованию только на выделенной машине. Вывод — не очень подходят ОС общего назначения для этого, на прикладном уровне…
В любом случае спасибо за интересную статью! Можно убрать накопление погрешности, это да. Но нельзя обеспечить четкую активацию в точное время с точностью до миллисекунд. Если Вы запустите Ваши программы с любым методом точных задержек параллельно с какой-нибудь ресурсо-жрущей игрушкой, то Вы увидите, что какой бы Вы не использовали метод задержки и какой бы приоритет для thread не выбрали, но время от времени будут происходить задержки в активации thread более чем на одну миллисекунду из-за свопинга или из-за того, что некоторые directx операции не прерываются ядром, и обеспечить мгновенную активацию прикладной программы для Windows в суб-миллисекундном диапазоне в общем случае невозможно.
Очень интересное исследование, спасибо! Срочно ищу по всем юнитам проекта, не используются ли где-либо малые задержки…
НЛО прилетело и опубликовало эту надпись здесь
НЛО прилетело и опубликовало эту надпись здесь
профилирование программ

НЛО прилетело и опубликовало эту надпись здесь
всё зависит от конечной потребности;
иногда бывает что счёт идёт на такты, но rdtsc особо верить нельзя ± 50-100 тактов(pipe-line, out-of-order execution);
но да почти всегда достаточно и QueryPreformanceCounter/QueryPerformanceFrequency, которые работают через ZwQueryPerformanceCounter;
Далеко не все промышленные системы являются «тру» real-time.
Однако сертификацию им проходить все равно требуется.
И это лишь один из примеров.
НЛО прилетело и опубликовало эту надпись здесь
В большинстве штатных ситуаций они, все-таки, предсказуемы.
Другое дело, что гарантий никаких нет 8)
НЛО прилетело и опубликовало эту надпись здесь
Это вы несколько путаете — теорию и реальную жизнь.
При бюджете, например, в 50 тысяч никто не будет вам разрабатывать систему реального времени, снимающую показания с измерительных приборов и отражающих их на индикаторах, за которыми наблюдает диспетчер. Есть ГОСТы, регламентирующие время от изменения показателя до отражения этого изменения, и программа(к слову, написанная на Delphi) с этим справляется — за несколько лет никаких проблем. Это я и называю «предсказуемость в штатной ситуации» — если система даже не real-time, то можно увеличить ее предсказуемость, снижая количество влияющих на нее факторов.
Можно сколько угодно пыжиться и надувать щеки в стиле «а вот если вдруг...», «гарантий нет, что ....» — факт в том, что есть решение, устраивающее заказчика(и реально работающее), и по устраивающей разработчика стоимости.
НЛО прилетело и опубликовало эту надпись здесь
Вообще — по-разному.
Но в общем случае — приходят со счетчика с датой, временем и измерением.
НЛО прилетело и опубликовало эту надпись здесь
Да по-разному. Есть такие, которые с COM-порта, есть такие, которые по Ethernet-у бегают(с TCP в качестве транспорта).
НЛО прилетело и опубликовало эту надпись здесь
1. Его(измерения) появление в БД
2. Его появление на индикаторе, на который смотрит диспетчер
НЛО прилетело и опубликовало эту надпись здесь
1. Ну, БД бывают разные. В данном случае, их несколько, но в данном случае важна лишь одна — ин-мемори, без транзакций. Часть данных являются «высокоприоритетными» — при заполнении их определенными значениями, срабатывают определенные алгоритмы обратной связи(грубо говоря — скакнул ток — сработала защита).
2. Странно, да. Но при сертификации этот фактор не учитывают. Есть отраслевые требования, задокументированные приказом таким-то, хотите получить сертификат — демонстрируйте соответствие.
НЛО прилетело и опубликовало эту надпись здесь
Многовато вопросов задаете, мы уже в сторону ушли 8)
Отвечаю: до индикации время измеряется другой софтиной — эмулятором индикатора, где записываются временные метки значений. Потом достаточно сравнить их с теми, что приходят со счетчика. Ну а время синхронизируется с GPS-приемником.

Неточностей в связи со всем этим — море. Когда я ковырялся с GPS, вскрылись такие бездны «гуляния» системного таймера виндов, что хватались за голову — для обычного процесса там и речи нет даже о точности более чем в 0.1 с. При помощи таких вот статей все эти неточности можно несколько уменьшить. И иногда и это «несколько» может хорошо выручить — будь подобная(только более развернутая и с рассмотрением других вариантов) статья у меня под рукой пару-тройку лет назад — здорово бы сэкономил свое время. Умный, как известно, предпочитает учиться на чужих ошибках.

Real-time систему не на спецжелезе со спецосью не построишь, это факт. Но далеко не всегда требуется настоящий real-time.
НЛО прилетело и опубликовало эту надпись здесь
Ну, архитектуру мудрил не я. Разработчикам далеко не всегда дают требуемые сроки и возможность делать «как надо бы по-хорошему», вы не знали? 8)
Я еще раз говорю — вы слишком привязаны к теории. В жизни оно по-разному складывается.

>В чем проблема? Запросто!

AVR-ка, мигающая светодиодами? 8))

Проблем разных много, их сложно охватить в рамках дискуссии в комментариях, да и не силен я в матчасти.
НЛО прилетело и опубликовало эту надпись здесь
>Видел ПО

Я сам писал — чувствуете разницу?

>для управление производственной линией под DOS/4GW

DOS тоже отвечает не всем требованям стандартов Real-time ОС. Геморы с драйверами, отсутствие многозадачности, как следствие — отсутствие вменяемого IPC.
НЛО прилетело и опубликовало эту надпись здесь
Главное требование для hard real-time — гарантированный результат операции за четко определенный промежуток времени. DOS этого не гарантирует.
НЛО прилетело и опубликовало эту надпись здесь
С каких это пор там что-то гарантировано?
А если, например, возникнет прерывание?
Или CLI и побежали? Далеко не убежите 8)
НЛО прилетело и опубликовало эту надпись здесь
По-моему, вы несколько заблуждаетесь относительно DOS'а.
НЛО прилетело и опубликовало эту надпись здесь
Ну на этом тогда и закончим.
С вопросами веры — это к батюшкам в церковь 8)
НЛО прилетело и опубликовало эту надпись здесь
Во-первых, RTKernel по сути практически заменяет DOS(чего разработчики и не отрицают, допуская установку на комп вообще без оси).
Во-вторых, я же вроде изначально говорил о том, что реальная жизнь вносит коррективы. RTKernel, например, сам по себе стоит 1000 евро. А где вы найдете под него разработчика, если речь не про Москву? Сколько такой разработчик запросит денег? А как вы будете поддерживать свой продукт? А если требуется возможность багфикса через интернет?
В-третьих, даже с RTKernel вы получаете soft real-time, а никак не hard real-time. Т.е. от простой программы под Windows оно будет отличаться только тем, что тайминги будут намного(но все же не бесконечно много) надежнее. Гарантии все равно не будет.
НЛО прилетело и опубликовало эту надпись здесь
>Это не противоречит ни одной моей фразе, сказанной выше.

Ну, например, он не совсем «поверх» DOS 8)
Да и речь вроде шла на основе DOS'а а не спецсофте — в самом начале ветки я и писал, что спецжелезо и спецсофт требуются для Hard real-time.
Кроме того, я не спец в архитектуре x86, вполне возможно, что и там есть затыки.

>Это уже другой вопрос, не связанный с «можно ли для DOS сделать realtime-приложение»

Не забывайте, что речь началась с вашего вопроса «для чего это нужно». Я объяснил, что soft real-time системы можно строить и на бытовых осях, при определенном подходе.
Ну чего вы реально под DOS навертите(при разумных затратах), если, например, вам обрабатывать надо гигабайты данных в час, где-то их складировать, куда-то их пересылатьи т.п.? Десятком/сотней станков порулить — это одно, а вот тысячей управляемых источников данных?

>Ниже некуда.

А драйвера? А обработчики прерываний?

Дискуссия, по-моему, переходит в затяжную. Если у вас есть аккаунт в Wave-предлагаю обсудить там. Если нет, могу прислать инвайт — пишите почту в личку.
НЛО прилетело и опубликовало эту надпись здесь
P.S. минусы вам проставляю не я, это кто-то набежал со стороны в нашу ветку 8(
НЛО прилетело и опубликовало эту надпись здесь
Делфи… как давно это было…
Отвык уже от begin-end…
Интересно, насколько он еще используется в реальных проектах?..
Довольно часто. По ссылке показаны примеры популярных программ, написанных на Delphi: www.embarcadero.com/application-showcase
Исчезающе мало.

Смотрим статистику вакансий на Dice.com:
C# — 4800
Java — 10086
Delphi — 53
Методология измерения не совсем правильная. NtDelayExecution переносит поток из списка плнируемых в список ожидания. Повторный запуск произойдет через заданный интервал + время до следующего планирования + время на смену контектов потока. Поэтому маленькие интервалы никогда не будут правильно измеряны в ОС с планировщиками общего назначения. А при больших интервалах кажущаяся точность появляется потому, что отношение необходимой задержки к накладным расходам становится больше — накладные расходы меньше влияют на результат измерения. При переключении задач может также происходить инвалидация кеша процессора, его заполнение требует время, вероятность велика, если код долго не получал управления из-за того, что был отложен — скорее всего неиспользуемый код был вытеснен.

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

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

Также желательно инвалидировать кеши 1 уровня перед замерами и очищать конвеер (например дальним вызовом, только тут может помешать предсказание переходов...).
xor eax, eax;
cpuid;
rdtsc;
;
;code under investigation
;
xor eax, eax
cpuid;
rdtsc;
Спасибо за хинт :)
1. «На некоторых версиях Delphi есть готовая команда rdtsc»
Это не готовая команда на некоторых версиях Delphi, а наличие поддержки встроенным ассемблером оной команды. В Delphi6 уже есть, в старших тем более.

2. Про разные архитектуры процессоров, многоядерность и нереалтаймность Win32 уже сказали.

3. А какое практическое применение у этого метода? Т.е. когда он действительно дает принципиально лучший результат относительно известных стандартных? Ведь если мы имеем дело с получением некоторых отсчетов от некоторого железа, то удобнее всего (и так делается в реальной жизни) использовать метки времени от самого железа.
Недавно нужна была подобная функциональность. За полчасика набросал базовый модуль для профайлинга, основываясь на QueryPerfomanceCounter. Получилась точность порядка 3 микросекунд (к сожалению, не помню, какой был процессор). Если бы использовать ассемблерные вставки, и дополнительные оптимизации, то, думаю, можно было бы догнать до 1 мкс (а может и еще точнее); но на тот момент мне данной точности было достаточно.
НЛО прилетело и опубликовало эту надпись здесь
хороша статья) в мемориз)
жаль голоса на сегодня закончились) автор, в случае чего — стучи, плюсануть карму и топик однозначно надо)
Зарегистрируйтесь на Хабре, чтобы оставить комментарий

Публикации

Истории