Форум: "Основная";
Текущий архив: 2006.08.20;
Скачать: [xml.tar.bz2];
ВнизИзмерение интервалов, меньших 1 mS. Найти похожие ветки
← →
JohnKorsh © (2006-07-04 11:08) [0]Извините, но вопрос несколько длинноват.
Для работы с короткими интервалами времени (< 1 mS) пытаюсь использовать команду RDTSС. (Она возвращает в регистрах EDX:EAX число тактов с момента включения процессора.)
Пытаюсь “откалибровать” программу-измеритель - по таймеру Delphi: cчитываю RDTSС_1, запускаю таймер на 100 ms, по окончании считываю RDTSС_2. Разница значений (RDTSC_2 - RDTSC_1) “плавает” не на тысячи, что объяснимо, а на десятки миллионов. Не поможет ли кто понять почему такой разброс?
Вот функция, использованная для чтения числа тактов с момента включения процессора:
function TForm1.RDTSC: comp;
//*************************************************
const
D32 = $66;
var
TimeStamp : record
case byte of
1: (Whole: comp);
2: (Lo, Hi: LongInt);
end;
//--------------------------------------------------------------------------
begin
asm
db $0F; db $31; // BASM не поддерживает команду RDTSC
{$ifdef Cpu386}
mov [TimeStamp.Lo],eax // младшее двойное слово
mov [TimeStamp.Hi],edx // старшее двойное слово
{$else}
db D32
mov word ptr TimeStamp.Lo,AX // mov [TimeStamp.Lo],eax - младшее двойное слово.
db D32
mov word ptr TimeStamp.Hi,DX // mov [TimeStamp.Hi],edx - старшее двойное слово.
{$endif}
end;
Result := TimeStamp.Whole;
end;
С таймером работаю обычным образом, функцию RDTSC вызываю сразу после Timer1.Enabled := True и первой строкой события Tick таймера.
← →
Jeer © (2006-07-04 11:14) [1]Потому, что ОС класса windows не являются ОС реального времени.
В разумных пределах их возможно адаптировать под конкретные задачи, точнее программы адаптировать под конкрентные задачи с учетов особенностей работы в мультизадачной среде.
← →
Rial © (2006-07-04 11:31) [2]Дело в том, что обычный таймер (как я понял, именно он используется),
способем обрабатывать "тики" с минимальной частотой в 55 милисекунд.
Поэтому у Вас тикает он не каждый 100, а каждые 110, и , иногда, 55 милисекунд.
Выход - использование мультимедийного таймера.
TimeSetEvent из модуля MMSystem посоветую.
← →
Desdechado © (2006-07-04 11:41) [3]> Пытаюсь “откалибровать” программу-измеритель - по таймеру Delphi
Это как измерять диаметр сверла линейкой с метровой шкалой.
Лучшее, что мне удавалось получить простым таймером, это что-то около 12 мс, а обычно около 40 мс. А все потому, что Jeer © (04.07.06 11:14) [1]
Т.е. программы могут замирать или замедляться по мановению ОС и нельзя ее заставить выполнять что-то в реальном времени (хоть и есть такой приоритет, но он может поставить раком всю ОС) в ущерб другим процессам, в число которых и сама ОС входит.
← →
второе явление Чапаева народу (2006-07-04 11:43) [4]
> Дело в том, что обычный таймер (как я понял, именно он используется),
> способем обрабатывать "тики" с минимальной частотой в 55
> милисекунд.
В системах линейки NT это регулируется. ХР, к примеру, "тикает" каждые 15 мс. А вообще я бы timeSetEvent() использовал. Даёт миллисекундные интервалы даже в девяностопятке...
← →
Jeer © (2006-07-04 12:27) [5]Да не так уж все и плохо:))
Не говоря уже об RDTSC, с помощью того же GetTickCount можно убедиться, что системный таймер (обертка TTimer) тикает довольно точно даже без поднятия приоритетов.
Надо только помнить о многозадачности и недопускать наличия сервисов и программ, отнимающих значительную часть процессорного времени.
Поскольку slice на платформах NT лежит в районе 10-20 ms (NT, w2k,XP, server, station), то "тиканье" с временными интервалами 100 ms и более наверняка приведет к спорадическом отклонениям от заданного интервала.
"Тиканье" с интервалом меньше slice - невозможно. (при исп. TTimer)
Опять же "тиканье" производится с шагом в slice, т.е. при slice=10 ms интервал составит T = 10*N, где N - целое число >=1
Пример:
TTimer.interval = 100 ms
Число тиков 1000
Среднее значение 100.1 ms
Макс. = 101 ms
Мин. = 100 ms
TTimer.interval = 10 ms
Число тиков 1000
Среднее значение 10.02 ms
Макс. = 10.09 ms
Мин. = 10.0 ms
Если же в момент выполнения такой программы запустить, дефрагментацию, смотреть фильм и искать наибольшее простое число, то результат будет несравненно хуже.
← →
Rial © (2006-07-04 15:51) [6]
> Jeer © (04.07.06 12:27) [5]
Попробуй вывести на экран каждый интервал между тиками этого таймера.
Ты очень сильно удивишься, увидев, что некоторые интервалы были
по 55 секунд.
← →
Jeer © (2006-07-04 16:14) [7]Rial © (04.07.06 15:51) [6]
Не удивлюсь, т.к. их там нет.
См.
Макс. = 10.09 ms
Мин. = 10.0 ms
← →
Cash © (2006-07-04 17:02) [8]JohnKorsh ©:
А чего там калибровать???
Там надо считать такты (RDTSC), а еще надо считать среднюю тактовую
частоту. Такты делим на такты в секунду, получаем тот промежуток
времени, которым мы проработали. Все просто!
const
DelayTime = 500;
Function GetCPUSpeed: DWord;
var
TimerHi, TimerLo: DWORD;
begin
asm
dw 310Fh
mov TimerLo, eax
mov TimerHi, edx
end;
Sleep(DelayTime);
asm
dw 310Fh
sub eax, TimerLo
sbb edx, TimerHi
mov TimerLo, eax
mov TimerHi, edx
end;
Result := Trunc(TimerLo / (1000.0 * DelayTime)); // MHz
end;
← →
Jeer © (2006-07-04 17:45) [9]Cash © (04.07.06 17:02) [8]
Несколько не точный метод.
Завышает истинную частоту в зависимости от общей загрузки проца.
Необходимо поиграть приоритетами.
Страницы: 1 вся ветка
Форум: "Основная";
Текущий архив: 2006.08.20;
Скачать: [xml.tar.bz2];
Память: 0.47 MB
Время: 0.042 c