WWW.ИСХОДНИКИ.РУ cpp.sources.ru
java.sources.ru web.sources.ru soft.sources.ru
jdbc.sources.ru asp.sources.ru api.sources.ru

  Форум на исходниках
  C / C++ / Visual C++
  Малые интервалы времени (for jerry & Kosha)

СПРОСИТЬ  ОТВЕТИТЬ
профайл | регистрация | faq

Автор Тема:   Малые интервалы времени (for jerry & Kosha)
zlelik опубликован 03-10-2001 20:20 MSK   Click Here to See the Profile for zlelik   Click Here to Email zlelik  
Еще раз поднимаю тему. Попробовал программу рекоммендованную Kosha. Если делать таймер с частотой 10Кгц, то в секунду вылезает погрешность 0.1 секунды. Если взять 100Кгц то в зависимости от загрузки проца от 0.65 до 1.8 с. Это баг виндом или как. Мне один знакомый сказал что вообще винды не могут мерять малые промежутки времени. Это так или нужно просто через драйвер все делать, а не в простой программе.

Для тестирования я использовал такой код (модифицированный код, который дал Kosha)
программа 100000 раз в секунду добавляет к переменной nTimerInMicroSec по 1 и если значение переменной >100000 то прекращает эту процедуру. До и после вызова этого таймера засекаю системное время, чтобы подсчитать врямя работы программы.

int nTimerInMicroSec;
SYSTEMTIME sTime,sTimeLast;

UINT ThreadProc(LPVOID pParam)
{
CCriticalSection criticalsection;
CSingleLock singlelock(&criticalsection);

LARGE_INTEGER PerformanceCounterLast;
LARGE_INTEGER PerformanceCounterCurrent;
LARGE_INTEGER PerformanceFrequency;
LARGE_INTEGER PerformanceDelta;
float SecondsPassed=0;

PerformanceCounterLast.QuadPart=0;
PerformanceCounterCurrent.QuadPart=0;
PerformanceFrequency.QuadPart=0;
PerformanceDelta.QuadPart=0;

QueryPerformanceFrequency(&PerformanceFrequency);
QueryPerformanceCounter(&PerformanceCounterCurrent);

GetLocalTime(&sTime);

while (nTimerInMicroSec<100000)
{
QueryPerformanceCounter(&PerformanceCounterCurrent);

PerformanceDelta.QuadPart=PerformanceCounterCurrent.QuadPart-PerformanceCounterLast.QuadPart;
if ((PerformanceDelta.QuadPart)>50)
{
SecondsPassed=( (float)PerformanceDelta.QuadPart)/( (float)PerformanceFrequency.QuadPart);

if (SecondsPassed>=0.00001)
{
PerformanceCounterLast=PerformanceCounterCurrent;
singlelock.Lock();

nTimerInMicroSec++;

singlelock.Unlock();
}

}
//Sleep(0);
}
GetLocalTime(&sTimeLast);
CString str;
str.Format("Time = %f; Frequency=%d",sTimeLast.wMinute*60+sTimeLast.wSecond+sTimeLast.wMilliseconds/1000.0-sTime.wMinute*60-sTime.wSecond-sTime.wMilliseconds/1000.0,PerformanceFrequency);
AfxMessageBox(str);
return 0;
}

FIV2 опубликован 03-10-2001 22:45 MSK     Click Here to See the Profile for FIV2  Click Here to Email FIV2     

Use aselbler :)
gecky опубликован 04-10-2001 12:00 MSK     Click Here to See the Profile for gecky  Click Here to Email gecky     
И зачем тебе это?
gecky опубликован 04-10-2001 12:21 MSK     Click Here to See the Profile for gecky  Click Here to Email gecky     
А не попробовать ли

SetPriorityClass(...Real time)
SetThreadPriority(time critical)

Кажется прям система останавливалась пока программа занята была. По крайней мере Win98.
Может погрешность меньше станет.

Heromantor опубликован 04-10-2001 01:09 MSK     Click Here to See the Profile for Heromantor  Click Here to Email Heromantor     
Полностью захватить процессор не удасться ну если только в 9x :), в NT точно не работает, пробовал, все равно другие задачи пашут.
И погрешность будет всегда :( этож не int08 в дос, Вынь гадкая штука все-таки :(((. Может если скажешь задачу то можно будет придумать как это обделать...
Kosha опубликован 04-10-2001 01:21 MSK     Click Here to See the Profile for Kosha  Click Here to Email Kosha     
2zlelik:

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

Дык вот: В принципе, эта байда меряет чего-то-там-пока-время-не-вышло.
Но есть несколько траблов, а именно:
Если в точное "время-вышло" ресурсы проца не у твоей программы, мастдаю по х.ру, вышло оно или не вышло. Как заблокить задачи - ставь приоритет Time Critical. Но это решит всего лишь 50% проблем. Хоть Time Critical, если я ничего не путаю, тормозит ВСЕ, кроме твоей проги, я в этом не уверен. По крайней мере такие баги не убираются.

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

Или DOS ;-) Вот это рулез-так-рулез!

zlelik опубликован 05-10-2001 10:30 MSK     Click Here to See the Profile for zlelik  Click Here to Email zlelik     
Так что, даже из драйвера нельзя точно мерять время в винде?

А вообще задача у меня такая:
Некое устройство подключено через LPT порт, и нужно ему импульсы подавать с частотой (ну 10-100 Кгц).

zlelik опубликован 05-10-2001 10:32 MSK     Click Here to See the Profile for zlelik  Click Here to Email zlelik     
Кстати приоритет процесса я ставил (правда в task manager в 2000 винде), Но это не сильно помогает
zlelik опубликован 05-10-2001 21:31 MSK     Click Here to See the Profile for zlelik  Click Here to Email zlelik     
А если написать прогу под ДОС, и запускать ее в виндах, Она вообще запустится? хотя бы в Win9x (что мне в принципе и надо).
zlelik опубликован 09-10-2001 22:37 MSK     Click Here to See the Profile for zlelik  Click Here to Email zlelik     
неужто никто не знает ничего,
неверю!
Kosha опубликован 10-10-2001 01:14 MSK     Click Here to See the Profile for Kosha  Click Here to Email Kosha     
1/100 миллисекунды - флаг тебе в руки.
Такой таймер в принципе не возможен по определению clock-генератора ;-))))

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

Получается привязка к машине и всю идею загубят кэши...

Но даже эта идея - под голый ДОС.

А еще лучше ее в BIOS зашить...

Organic опубликован 15-10-2001 12:55 MSK     Click Here to See the Profile for Organic  Click Here to Email Organic     
кстати... никто не знает как устроена Sleep??
просто интересно, как она паузю делает...
Sourcer опубликован 15-10-2001 09:01 MSK     Click Here to See the Profile for Sourcer  Click Here to Email Sourcer     
time = GetTickCount(); //in miliseconds
Sourcer опубликован 15-10-2001 10:37 MSK     Click Here to See the Profile for Sourcer  Click Here to Email Sourcer     
Organic : Наверное пускает бесконечный цикл, сравнивает время и когда столько времяни пройдёт скока надо, тогда делает break....

Sleep(DWORD time)
{
time1=GetTickCount();
while(1)
{
if((GetTickCount()-time1)>=time) break;
}
}
что то типа этого! Это в милисекундах...

Organic опубликован 15-10-2001 12:53 MSK     Click Here to See the Profile for Organic  Click Here to Email Organic     
погоди ка...
наскоко я понимаю GetTicksCount возвращает количество миллисекунд, прошедших со старта Windows.
неужто внутри GetTicksCount ведется работа с TimeStampCounter-регистром!!??
вот вам и малые интервалы времени - разобрать GetTicksCount и выдрать оттудова способ работы с TSC (количество тактов отработанных процом после RESET)

причем TSC насрать на многозадачность - он ведь просто считает такты и всё...

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

Sourcer опубликован 15-10-2001 13:00 MSK     Click Here to See the Profile for Sourcer  Click Here to Email Sourcer     
:)
DoCenT опубликован 05-12-2001 15:18 MSK     Click Here to See the Profile for DoCenT  Click Here to Email DoCenT     
Господа учити мат часть!!!
Все дело в том, что все таймеры и задержки
считаются от цокания ТАЙМЕРА ЧАСОВ ,который тикает 0.055 сек

ДЕЛАЙТЕ ВЫВОДЫ!!!

Kosha опубликован 05-12-2001 21:45 MSK     Click Here to See the Profile for Kosha  Click Here to Email Kosha     
А вот и ни фига. Таймер часов - дерьмо. Есть более веселые способы.
Кто мне мешает мерять количество выполненных команд процессора? Или допустим зациклить какую-нить команду 5000 раз и смотреть, сколько это будет, поделить на 5000, и выполнять по одному? (ну, в Win чуть посложнее, но идея та же).

PerformanceCounter как раз тики проца и меряет, кстати...

zhevak опубликован 06-12-2001 04:16 MSK     Click Here to See the Profile for zhevak  Click Here to Email zhevak     
Привет шумной компании и персонально zlelik

Господа, я работал с железом еще с 198х года.
Так вот что я вам могу сказать. Давайте вспомним,
кто первый сказал: "55 мс". И откуда взялась эта
странная цифра.

Давнам давно, Когда Гейтс был молодой и
(относительно) бедный, знаменитый Голубой Гигант
создал уникальную (в смысле -- бездарную) IBM PC,
которую вскоре переделали в IBM PC/XT. PC-ишка
создавалась в жуткой спешке и не очень продвинутыми
специалистами (иначе бы мы сейчас не маялись с
нехваткой прерываний и др. прелестями, доставшимися
нам в наследство).

Итак, В PC-шке была одна мелкосхема -- таймер i8253.
Он имел три канала:
нулевой -- вырабатывал тики для часов,
первый -- отвечал за регенерацию памяти,
второй -- противно пищал в динамик.

Все три канала таймера были запитаны от единственного
генератора. Кварцевый генератор работал на частоте
14,31818 Мгц.

Затем эту частоту делили на три (= 4.77 МГц) и
подавали на тактовый вход микропроцессора (i8088).
Потом ее еще раз делили на 4 (= 1.19318 МГц) и
подавали на входы всех трех таймеров.

Таймер устроен очень просто. Можно считать, что это
три независимых 16-разрядных регистра (порта). В них
записывается коэффициент деления. Таким образом,
в нулевой канал записывали число 0х0000, в первый --
0х0012, во второй -- 0х0528.

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

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

1.19318 МГц / 65536 = 19.5 Гц или каждые 55 мс.

А вот у первого канала на выходе стоял еще один счетный
триггер, который делил частоту на два. Таким образом,
получались почти 15 микросекундные импульсы.
(Я не привожу расчеты.)

Так вот, изюминка состоит в том, что программы могут не
только инициализировать эти каналы, но и считывать их
текущее состояние. Другими словами, если мы читаем из
нулевого канала его состояние, потом произведем
некоторые "действия", а затем еще раз считаем состояние
канала, то вычислив разницу можно легко посчитать
длительность этих "действий" -- частоту декремента канала
мы ведь знаем -- 1.19 МГц. Здесь надо оговориться, что
длительность измеряемых "действий" не должна превышать
55 мс.

Все было бы хорошо, если б не прогресс. На современных
компьютерах ставятся совершенно другие таймеры, которые
работают с совершенно другими частотами. Но к счастью,
в С++ нет необходимости лазить по портам, каналам таймера
и прочим бестиям. За нас это делают библиотеки.

Я советую Вам, милейший, посмотреть функции

QueryPerformanceFrequency
QueryPerformanceCounter

, которые как раз и работают с нулевым каналом таймера.

И последнее. Мой предыдущий опыт говорит о том, что если
Вы хотите использовать компьютер в качестве машины для
управления оборудованием и обработки данных, то это
можно делать и на Виндах. Но как только Вы попытаетесь
применять его в качестве прецезионного инструмента, то
лучше работать из-под ДОС, а еще лучше из-под UNIX.
Можно рассмотреть и другой вариант -- в Вашем случае
LPT не _генерирует_ частоту, а _управляет_ частотой
внешнего генератора. Это самый лучший вариант, не смотря
на то, что требует внешнего оборудования. Винды -- это не
коттедж с тремя туалетами для двоих. Винды -- это
коммуналка, где "на 38 комнаток всего одна уборная".
Проблематично какому-то конкретному человечку
периодически справлять свои нужды строго по времени.
Не для таких задач Билл Гейтс создавал "Окна", Вы
онемного шиблись в выборе инструмента для решения своих
задач.


С уважением, Александр Жевак

x опубликован 07-12-2001 03:50 MSK     Click Here to See the Profile for x  Click Here to Email x     
браво zhevak
сразу видно что Александр шарит

теперь подробнее по теме:
пусть проц 500МГц,выходная частота 200кгц
т.е допустимое число тактов на переключение 2000
ежели кто интересовался ядром NT то знает что на задачу там отведено 5-20 мс (т.е если задача в течение этого времени не отдаст управление то оно все равно переключится)
причем процесс с более высоким приоритетом в 9х получит управление СРАЗУ а NT только по истечении интервала

поэтому в NT можно нормально ботать только нахрен убив механизм переключиния задач

в 9х нам непосредственно доступна на запись IDT что делает все легким и удобным

а делаем мы следующее:
1.создаем свой обработчик прерываний от таймера
2.вписываем его дескриптор на место стандартного от маздая

что он должен делать:
I.инициализация:
1.определить с какой скоростью работает сейчас таймер
2.перепрограмировать его на нужную скорость
3.определить частоту проца
II.непосредственная работа
1.сделать что нужно с LPT
2.вызывать стандартный обработчик выравнивая задержками через RDTSC

что следует иметь ввиду:
1.таймер как и LPT железяка внешняя и ее частота вряд-ли больше 4 МГц
2.чипсет тоже дурной=он любит кэшировать запросы и работает в асинхронном режиме

P.S:я бы посоветовал приобрести микроконтроллер вроте ATMEL ATtiny (<1$)
у него 8 ног есть флешка,таймер=короче идеальный генератор=и управлять им с компа

P.P.S:Александр вас не затруднит ответить на некоторые вопросы по железякам (точнее по микроконтроллерам)?

x опубликован 07-12-2001 04:06 MSK     Click Here to See the Profile for x  Click Here to Email x     
ой облажался
>>Я советую Вам, милейший, посмотреть >>функции
>>
>>QueryPerformanceFrequency
>>QueryPerformanceCounter
>>
>>, которые как раз и работают с нулевым >>каналом таймера.

сорри не заметил ляпу

может в далеком 95 году на заре форточкостроения так и БЫЛО=но сейчас 2001 год кончается и используется RDTSC =который ДАВНО СТАЛ ИНДУСТРИАЛЬНЫМ СТАНДАРТОМ и которого нет только в первых пнях

zlelik опубликован 07-12-2001 16:45 MSK     Click Here to See the Profile for zlelik  Click Here to Email zlelik     
Народ, меня кинули. Как оказалось максимальная частота которая мне нужна 500 гц. А ближайшая задача вообще чуть ли не 10 гц. Просто один кадр уверял что в виндах с точностью 0.5 время нельзя померять. С QweryPerfomanceCounter я разобюрался, но на 550 пне погрешность его (хотя фиг знает правильно я ее мерял или нет, я мерял GetLocalTime(), которая с точностью до мс выдает время) и при частоте 10кгц и времени измерения 10 сек выходила погрешность 0,1 с. Но этого мне наверно хватит.

СПРОСИТЬ  ОТВЕТИТЬ
Перейти:


E-mail | WWW.ИСХОДНИКИ.RU

Powered by: Ultimate Bulletin Board, Freeware Version 5.10a
Purchase our Licensed Version- which adds many more features!
© Infopop Corporation (formerly Madrona Park, Inc.), 1998 - 2000.