Экзотическое поведение функции time под Windows

Интересные алгоритмы, олимпиадные задачи, эффектные и эффективные решения. freepascal, delphi, c, c++, c#, java, javascript, perl, ruby, python, php, bash, wsh и т.д. Компиляторы, интерпретаторы, линкеры, отладчики, системы контроля версий и многое другое.

Модератор: xdsl

Экзотическое поведение функции time под Windows

Сообщение xdsl 11 дек 2008, 01:13

Как было обнаружено студентами 483 группы во время лабораторных работ по СРВ, поведение функции time в delphi не соответствует ожиданиям. При двух последовательных вызовах time или now разница в полученном времени всегда больше 1 миллисекунды, причем - намного (10-15 миллисекунд). Проверка данного факта с использованием freepascal, показала, что данная проблема действительно имеет место быть, причем - именно для windows. В линуксе тот-же код дает адекватные результаты ;)

timetest.pp :
Код: Выделить всё
{$mode objfpc}
{$h+}
uses
  SysUtils;

function doWork():string;
  var tm1,tm2:tdatetime; counter:int64;
begin
   counter:=0; tm1:=time;
   repeat  tm2:=time;  inc(counter);  until (tm2<>tm1);
   result:='Delta time: '+formatdatetime('tt:zzz',tm2-tm1)+'; Cycles: '+inttostr(counter);
end;

begin
writeln(dowork());
end.
По коду видно, что выход из цикла в функции doWork произойдёт только в случае, когда в очередной раз полученное значение текущего времени будет отличаться от зафиксированного перед циклом значения. Дополнительно, счетчик counter фиксирует количество итераций. Следуя логике, разница между двумя временными штампами должна быть минимально возможной - 1мс. Вместо этого получаем довольно экзотические результаты, подобные следующим:
Код: Выделить всё
...
Delta time: 0:00:00:016; Cycles: 4116
Delta time: 0:00:00:016; Cycles: 4318
Delta time: 0:00:00:015; Cycles: 4894
Delta time: 0:00:00:016; Cycles: 3580
...

Тот-же самый код в линуксе даёт гораздо более корректные результаты:
Код: Выделить всё
...
Delta time: 00:00:00:001; Cycles: 55
Delta time: 00:00:00:001; Cycles: 65
Delta time: 00:00:00:001; Cycles: 69
Delta time: 00:00:00:001; Cycles: 1
Delta time: 00:00:00:001; Cycles: 64
Delta time: 00:00:00:001; Cycles: 4
Delta time: 00:00:00:001; Cycles: 9
...
Здесь вызывает недоумение разнобой в количестве циклов, а также их крайне небольшое количество по сравнению с виндовс.
Оба факта объясняются тем, что способ получения текущего времени в линуксе - это вызов системной функции gettimeofday, которая возвращает количество секунд и микросекунд, прошедшее с 1970 года. Эти данные приходится преобразовывать и усекать, т.к. тип TDateTime не содержит
микросекунды. Дополнительно, сам системный вызов gettimeofday под линуксом работает дольше, т.к. возвращает больше информации (в том числе - о локальной временной зоне) и дает более точные результаты, чем системный вызов getlocaltime вод виндовс. Модифицируем программу под юникс-специфику

timetest2.pp :
Код: Выделить всё
{$mode objfpc}
{$h+}
uses
  SysUtils,Unix;

function doWork():string;
  var counter:int64;
      tz1,tz2:timeval;
      mksec1,mksec2:int64;
begin
   fpgettimeofday(@tz1,nil);
   counter:=0;
   repeat
    fpgettimeofday(@tz2,nil);
    inc(counter);
    mksec1:=int64(tz1.tv_sec)*1000000+tz1.tv_usec; mksec2:=int64(tz2.tv_sec)*1000000+tz2.tv_usec;
   until (mksec2-mksec1>1000);
   result:='Delta time: '+inttostr(mksec2-mksec1)+' microseconds;'+' Cycles: '+inttostr(counter);
end;

begin
writeln(dowork());
end.

Результаты нескольких последовательных запусков timetest2.pp:
Код: Выделить всё
Delta time: 1007 microseconds; Cycles: 141
Delta time: 1004 microseconds; Cycles: 140
Delta time: 1006 microseconds; Cycles: 140
Delta time: 1003 microseconds; Cycles: 139


Общий вывод: для получения точного времени невозможно использовать функцию time в windows, в то время как в linux данная функции реализована корректно.

P.S. Для обеспечения равных условий опции компилятора freepascal были выставлены идентичными для Windows и Linux, сторонние приложения во время тестирования - far под windows, konsole(kde) - под linux, при этом загрузка процессора приложениями и системными службами была не более 1%.
xdsl
 
Сообщения: 1236
Зарегистрирован: 09 дек 2008, 05:16
Откуда: ВЦ ШГПИ
Полное имя: Слинкин Д.А.

Re: Экзотическое поведение функции time под Windows

Сообщение xdsl 12 дек 2008, 11:49

Запуская на разных машинах (CPU - в одной ценовой категории, Intel и AMD), достиг очень любопытных результатов в предыдущей программе. Вместо:
Код: Выделить всё
Delta time: 1007 microseconds; Cycles: 141
Delta time: 1004 microseconds; Cycles: 140
Delta time: 1006 microseconds; Cycles: 140
Delta time: 1003 microseconds; Cycles: 139

Получил максимум:
Код: Выделить всё
Delta time: 1001 microseconds; Cycles: 4015
Delta time: 1001 microseconds; Cycles: 4012
Delta time: 1001 microseconds; Cycles: 3951
Delta time: 1001 microseconds; Cycles: 3983

Исключив из цикла вызов функции получения времени, получил более ожидаемые результаты (от 3 до 10 секунд на миллиарде итераций). Похоже, следует провести более глубокое исследование особенностей фрипаскалевской генерации и выполнения кода на различных ядрах Linux и различных CPU
xdsl
 
Сообщения: 1236
Зарегистрирован: 09 дек 2008, 05:16
Откуда: ВЦ ШГПИ
Полное имя: Слинкин Д.А.

Re: Экзотическое поведение функции time под Windows

Сообщение Vladislav_133 16 дек 2008, 01:35

Материал представленный в данной теме чрезвычайно интересный и совсем не простой. Мне бы хотелось ответить на него развернуто. А поскольку по опыту знаю, что на форумах не любят длинных сообщений, то разобью материал на три части: Общие соображения, Почему постановка, как мне кажется, не точна, Ответ по существу.
И так

Общие соображения.

Данное сообщение выводит на очень интересную проблему измерения производительности программного обеспечения. Возьмем упрощенную задачу.
Предположим мы измеряем время выполнения некоторого фрагмента программы. Естественно замерить момент времени в начале выполнения и в его конце и вычислить разность. Но легко убедиться, что каждый раз мы будем получать различные промежутки времени, хотя, скорее всего сравнимые. Здесь мы имеем некоторый элемент случайности. Откуда он здесь берется?
Так вот время выполнения некоторого участка кода состоит из двух частей. Это можно записать так T=T1+T2. При этом T1 - статическая часть, T2 - случайная часть. Можно сказать, что T1 состит из сумм всех времен выполнения команд процессора, в которые компилятор преобразует код на языке высокого уровня. Отчего зависит T1? если кратко то

1. Аппаратной составляющей: процессор, шины, оперативная память, кэш.
2. Компилятора. Разные компиляторы по-разному транслируют программу с ЯВУ в язык процессора.
3. Параметров трансляции. Особенно это касается параметров оптимизации кода.
4. Среды выполнения. Если мы рассматриваем компиляторы, то средой исполнения будет операционная системы. ОС влияет на выполнение программы в частности из-за того, что в программе используются системные вызовы.
5. Разумеется от кода программы. Если вы собрались сравнивать по быстроте фрагменты на двух различных языках, то здесь важно выбрать адекватные фрагменты. Т.е. алгоритмы должны быть реализованы при помощи сравнимых схожих средств.

И так, если вы намерены измерять и сравнивать производительность вам необходимо учитывать все перечисленные факторы.

Но у нас остается еще составляющая T2. Какова ее природа? В программах, выполняющихся под управлением ОС ее появление обязательно. Дело в том, что выполнение программы может прерываться другими задачами системныеми или не системными. И здесь также имеется несколько факторов, отчего зависит величина T2:

1. Приоритет выполняемой задачи.
2. Системные задачи, которые время от времени запускает ОС.
3. Наличие в системе различных служб.
4. Наличие в системе запущенных прикладных задач.
5. Обработка системой внешних вызовов, если ОС играет роль сервера (файлового, сервера БД, WEB-сервера и т.д.).
6. Запус самой программой параллельно-обрабатывающихся потоков.

Учесть эти факторы чрезвычайно сложно, а в общем случае нельзя вовсе. В общем случае есть смысл говорить только о некотором среднем времени выполнения:
<T>=T1+<T2>. Усреднение осуществляется некоторому количеству однотипных запусков данногофрагмента. Но чтобы сравнивать времена выполнения в разных операционных системах, необходимо тщательно проанализировать все перечисленные выше факторы (и случайные и нет).
Аватара пользователя
Vladislav_133
Elite
 
Сообщения: 1386
Зарегистрирован: 13 дек 2008, 18:08
Полное имя: П.В.Ю.

Re: Экзотическое поведение функции time под Windows

Сообщение Vladislav_133 16 дек 2008, 01:51

Почему постановка, как мне кажется, не точна

Однажды очень давно, мне пришлось столкнуться с одной интересной ошибкой. Речь идет не о программировании, а математике. В некоторых к книгах к правильному результату приходили не правильным методом. Когда я проанализировал этот метод, то обнаружил, что в нем присутствуют две ошибки, которые, так сказать, гасят друг друга. Это мне стало уроком на всю жизнь. Постановка и методы вывода должны быть точными.
В рассматриваемом вопросе следовало бы:

1. Посмотреть машинный код, который получается в результате трансляции. Ни от куда не следует, что компилятор Delphi под Windows и под Linux делают это одинаково. В частности и настройки их посмотреть.
2. Посмотреть код функций, которые вызываются для получения количества долей секунд. Код функций, наверняка разный, а самое главное, мы бы узнали, что за системные функции вызываются. Честно говоря, у меня была мысль этим заняться, поскольку это в русле моих интересов лежит, да времени пока нет.
3. Ну и учесть настройки ОС, хотя бы ориентировочно. В частности, на будущее, не нужно сравнивать Linux, скажем с Windows XP, надо сравнивать c Windows Server (2003 илит другой). Это аксиома. В противном случае не стоит и вообще подобные вопросы поднимать.

Однако я не утверждаю, что результат не правилен. Выводы скороспелы. См. следующее сообщение.
Аватара пользователя
Vladislav_133
Elite
 
Сообщения: 1386
Зарегистрирован: 13 дек 2008, 18:08
Полное имя: П.В.Ю.

Re: Экзотическое поведение функции time под Windows

Сообщение Vladislav_133 16 дек 2008, 02:17

Ответ по существу

А теперь по существу. Честно говоря, Linux знаю плохо, хотя и программирую под ним. Насколько я понимаю, системная функция, которая используется для получения момента времени возвращает время в микро секундах. Тогда как функция, которая используется в Windows - миллисекундах. Получается, что сравниваются несравнимые вещи. В чем тут дело?
А дело в том, в Windows имеются две группы функций, которые можно использовать для получения промежутков времени. Первую группу можно назвать нормальной. Время получается с точностью до миллисекунд, а может быть и несколько больше. Вторая группа функций - функции точного разрешения. С помощью этих функций можно получить промежутки с точностью до микро секунд. В Паскале, очевидно используются функции первой группы. Кстати, если заглянуть в документацию, то функции типа GetLocalTime или GetSystemTime вообще не рекомендуется использовать для точного измерения промежутков. У них другая задача. Для это используется функция GetTickCount. Но и эта функция дает только миллисекунды, т.е. относится к первой группе. Таким образом сравнение, которое было проведено в сообщении некорректно. Что же касается функций второй группы, то вот простая программа, которая демонстрирует их использование (на Си, конечно) и по сути аналогичная фрагментам, которые мы видели ранее.

Код: Выделить всё
#include <stdio.h>
#include <windows.h>


void main()
{
   LARGE_INTEGER i1,i2,j;
   int n=0;
   QueryPerformanceFrequency(&j);
   QueryPerformanceCounter(&i1);
   i2=i1;
   while(i1.QuadPart==i2.QuadPart)
   {
      QueryPerformanceCounter(&i2);
      n++;
   }
   double s = double(i2.QuadPart-i1.QuadPart)*1000.0/j.QuadPart;
   printf("%d    %f \n",n,s);
}


Результат выполнения (в миллисекундах, замечу)

1 0.000363
1 0.000356
1 0.000356
1 0.000351
1 0.000363
1 0.000361

и т.д.

Реализованы ли функции второй группы в Delphi, я не знаю. В стандартных библиотеках Си их тоже нет, но вот в библитеке .NET они уже представлены.
Аватара пользователя
Vladislav_133
Elite
 
Сообщения: 1386
Зарегистрирован: 13 дек 2008, 18:08
Полное имя: П.В.Ю.

Re: Экзотическое поведение функции time под Windows

Сообщение xdsl 16 дек 2008, 15:48

Хочу уточнить, что рассматриваемый код имеет отношение не к Delphi, а к freepascal, важным достоинством которого является кроссплатформенность (проект Kylix (delphi под линукс) разработчиками давно заброшен и не развивается).
Насколько я понимаю, системная функция, которая используется для получения момента времени возвращает время в микро секундах. Тогда как функция, которая используется в Windows - миллисекундах. Получается, что сравниваются несравнимые вещи.

Все-таки вещи сравниваются сравнимые, т.к. различаются ровно в 1000 раз. Достаточно добавить в код деление на 1000

Теперь снова по существу вопроса. То, что функция time под виндовс ведет себя некорректно, подтверждается для windows XP. Было-бы неплохо проверить этот факт под windows server и вистой.

Кстати, если заглянуть в документацию, то функции типа GetLocalTime или GetSystemTime вообще не рекомендуется использовать для точного измерения промежутков. У них другая задача. Для это используется функция GetTickCount.

Проверка показывает, что с GetTickCount - все столь-же печально, как и с time:
Код: Выделить всё
{$mode objfpc}
uses windows,sysutils;
var i:integer;
   c1,c2,counter:int64;   
begin
for i:=1 to 10 do begin
  c1:=gettickcount();
  counter:=0;
  repeat
   inc(counter);
   c2:=gettickcount();   
  until c2<>c1;
  writeln(format('Delta: %d; count: %d',[c2-c1,counter]));
end;
end.
Получается что-то вроде следующего:
Код: Выделить всё
Delta: 10; count: 1733767
Delta: 11; count: 1307723
Delta: 10; count: 1779348
Delta: 10; count: 950026
Delta: 10; count: 1782913
Delta: 10; count: 1227054
Delta: 10; count: 1961834
Delta: 10; count: 1783834
Delta: 10; count: 1909345
Delta: 10; count: 1407543

Это windows XP под виртуалбоксом. windows XP на реальной системе даёт худшие результаты, delta - 15-16 милисекунд. Можете проверить, разархивировав и запустив вложение.

Про queryperfomancecounter и иже с ним могу сказать, что в свете экзотики работы time и GetTickCount, корректность его поведения тоже следует проверить.
Вложения
1.exe.gz
Архивированный исполняемый файл для рассматриваемого кода.
(29.34 Кб) Скачиваний: 603
xdsl
 
Сообщения: 1236
Зарегистрирован: 09 дек 2008, 05:16
Откуда: ВЦ ШГПИ
Полное имя: Слинкин Д.А.

Re: Экзотическое поведение функции time под Windows

Сообщение xdsl 17 дек 2008, 14:56

Если будем тестировать время работы кода с помощью высокоточных счётчиков, а также функционирование самих счётчиков, то оставляю за собой право применять их и в линуксе. Например: posix-функция clock_gettime возвращает время в наносекундах. Дополнительно, в линуксе есть и свои собственные счетчики, posix-несовместимые, но думаю - следует остановиться на стандартах.
xdsl
 
Сообщения: 1236
Зарегистрирован: 09 дек 2008, 05:16
Откуда: ВЦ ШГПИ
Полное имя: Слинкин Д.А.

Re: Экзотическое поведение функции time под Windows

Сообщение Gemini 17 окт 2009, 16:24

У меня есть вопрос по трактовке лабораторной работы №0 по СВР (483 группа). В задании сказано:
Код: Выделить всё
Дан набор входных данных в количестве N значений. Модифицировать алгоритм пузырьковой сортировки таким образом, чтобы при любом наборе входных данных время их сортировки Tn было постоянным. Продемонстрировать разницу в работе исходного и модифицированныого алгоритма.
.

И я до сих пор не могу понять как иначе можно модифицировать алгоритм, кроме как сделать sleep после двойного цикла. Но ведь по сути это не меняет алгоритм никак. Так вот вопрос - Подобный ли способ имелся ввиду в качестве модификации алгоритма?
Не относитесь к этой жизни слишком серьезно,господа.Все равно вам из неё живым не выбраться.
Gemini
 
Сообщения: 90
Зарегистрирован: 13 янв 2009, 12:42
Откуда: Сейчас в Ша
Полное имя: Плешков Сергей Александрович

Re: Экзотическое поведение функции time под Windows

Сообщение Vladislav_133 17 окт 2009, 18:21

Насчет времени не могу сказать. Но можно в алгоритме сделать каждый проход от 1 до n, а не от 1 до n-i.

Да, не подумал. Это к делу не относится.
Последний раз редактировалось Vladislav_133 20 окт 2009, 10:52, всего редактировалось 1 раз.
Аватара пользователя
Vladislav_133
Elite
 
Сообщения: 1386
Зарегистрирован: 13 дек 2008, 18:08
Полное имя: П.В.Ю.

Re: Экзотическое поведение функции time под Windows

Сообщение Gemini 19 окт 2009, 09:45

Одним из вариантов(оооочень долгим) является вот такая реализация нового алгоритма
Код: Выделить всё
time1:=time;
    for i:=1 to n do
      begin
        for j:=1 to n do
          begin
            if GetEl(j)>GetEl(j+1) then
              begin
               a:=GetEl(j);
               SetEl(j,GetEl(j+1));
               SetEl(j+1,a);
              end;
          end;
        sleep(1);
      end;
  time2:=time;

Writeln(' on new algorithm = ',millisecondsbetween(time2,time1), ' milliseconds');


Тогда мы получаем прямую зависимость времени выполнения сортировки от количества элементов - показать такую зависимость Дмитрий Анатольевич сказал на прошлой лабе Михаилу.
Но хочется найти другие варианты....
Не относитесь к этой жизни слишком серьезно,господа.Все равно вам из неё живым не выбраться.
Gemini
 
Сообщения: 90
Зарегистрирован: 13 янв 2009, 12:42
Откуда: Сейчас в Ша
Полное имя: Плешков Сергей Александрович

Re: Экзотическое поведение функции time под Windows

Сообщение Vladislav_133 19 окт 2009, 11:56

Мне кажется, формулировка не совсем точна. Ведь количество перестановок определяется тем, какой массив сгенерирован, а следовательно, время будет все равно разным.
Аватара пользователя
Vladislav_133
Elite
 
Сообщения: 1386
Зарегистрирован: 13 дек 2008, 18:08
Полное имя: П.В.Ю.

Re: Экзотическое поведение функции time под Windows

Сообщение xdsl 20 окт 2009, 07:36

Gemini писал(а):Одним из вариантов(оооочень долгим) является вот такая реализация нового алгоритма
Код: Выделить всё
time1:=time;
    for i:=1 to n do
      begin
        for j:=1 to n do
          begin
            if GetEl(j)>GetEl(j+1) then
              begin
               a:=GetEl(j);
               SetEl(j,GetEl(j+1));
               SetEl(j+1,a);
              end;
          end;
        sleep(1);
      end;
  time2:=time;

Writeln(' on new algorithm = ',millisecondsbetween(time2,time1), ' milliseconds');


Тогда мы получаем прямую зависимость времени выполнения сортировки от количества элементов - показать такую зависимость Дмитрий Анатольевич сказал на прошлой лабе Михаилу.
Но хочется найти другие варианты....

Что-то вас, ребята, куда-то не туда ведет.
Вот код:
Код: Выделить всё
            if GetEl(j)>GetEl(j+1) then   begin
               a:=GetEl(j);  SetEl(j,GetEl(j+1));  SetEl(j+1,a);
              end;

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

P.S. Внутренний цикл сократите, плиз. Совершенно необязательно итерировать от 1 до n.
xdsl
 
Сообщения: 1236
Зарегистрирован: 09 дек 2008, 05:16
Откуда: ВЦ ШГПИ
Полное имя: Слинкин Д.А.

Re: Экзотическое поведение функции time под Windows

Сообщение Vladislav_133 20 окт 2009, 09:52

А как это можно сделать? Если условие выполняется, то меняем местами, а если нет - то не меняем. Т.е. если, например, сортируем уже отсортированный массив, то времени на это понадобится несколько меньше. Для того, чтобы уравнять времена, можно в случае не выполнения условия, выполнит некоторую фиктивную перестановку.
Аватара пользователя
Vladislav_133
Elite
 
Сообщения: 1386
Зарегистрирован: 13 дек 2008, 18:08
Полное имя: П.В.Ю.

Re: Экзотическое поведение функции time под Windows

Сообщение xdsl 21 окт 2009, 07:43

Можно перестановку сделать, дублирующую реальную, можно замерить время работы участка кода в наихудшем случае и обеспечить ожидание во всех остальных случаях. Последний вариант обладает определенным недостатком - нет возможности учесть текущую нагрузку на процессор(ы). Вообщем, вариантов много, в выборе студентов не ограничиваю, могут придумывать что угодно, лишь-бы задача была решена, а именно - сортировка пузырьковая, сортирует массив из N элементов всегда одинаковое время, вне зависимости от содержимого, но не дольше (разве-что на накладные расходы), чем при наихудшем для пуз. сортировки случае. Исходные данные для задачи - кол-во эл-в массива N.
xdsl
 
Сообщения: 1236
Зарегистрирован: 09 дек 2008, 05:16
Откуда: ВЦ ШГПИ
Полное имя: Слинкин Д.А.

Re: Экзотическое поведение функции time под Windows

Сообщение Gemini 14 ноя 2009, 08:06

Подскажите,почему у меня Freepascal на цикл For ругается? вставляешь цикл - выдает ошибку компиляции. Может этот цикл в каком то не подгружаемом по умолчанию unit'е лежит? цикл repeat работает.Они оба прописаны в Programmesrs reference. времени сейчас совсем нет,а то бы сам поискал ответ...
Не относитесь к этой жизни слишком серьезно,господа.Все равно вам из неё живым не выбраться.
Gemini
 
Сообщения: 90
Зарегистрирован: 13 янв 2009, 12:42
Откуда: Сейчас в Ша
Полное имя: Плешков Сергей Александрович

Re: Экзотическое поведение функции time под Windows

Сообщение Vladislav_133 14 ноя 2009, 17:08

Вы программу выложите, тогда всем понятно будет.
Аватара пользователя
Vladislav_133
Elite
 
Сообщения: 1386
Зарегистрирован: 13 дек 2008, 18:08
Полное имя: П.В.Ю.

Re: Экзотическое поведение функции time под Windows

Сообщение xdsl 16 ноя 2009, 08:42

Gemini писал(а):Подскажите,почему у меня Freepascal на цикл For ругается?

Во-первых, проверьте тип управляющей переменной. Он должен быть порядковым, причем не int64 и не qword (эти два типа в действительности не порядковые, вся арифметика с ними идет через FPU).
Во-вторых, изменение управляющей переменной внутри цикла for запрещено.
xdsl
 
Сообщения: 1236
Зарегистрирован: 09 дек 2008, 05:16
Откуда: ВЦ ШГПИ
Полное имя: Слинкин Д.А.

Re: Экзотическое поведение функции time под Windows

Сообщение Gemini 26 ноя 2009, 19:39

Чтож.Сменил тип счетчика на integer - заработало.

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

И еще. В lab0 погрешности при результате в линуксе допустимы?если все измерять в микросекундах.
Потому как запуск в fpc одного и того же участка кода последовательно приводит к разным результатам.
Вот этот участок кода запускаю 3 раза подряд в одной программе
Код: Выделить всё
for i:=1 to n do mas[i]:=n-i+1;

       fpgettimeofday(@tb,nil);
        for i:=1 to n do
                for j:=1 to n-i do
                begin
                     fpgettimeofday(@timeb,nil);
                        if GetEl(j)>GetEl(j+1) then
                        begin
                         pr:=GetEl(j);
                         SetEl(j,GetEl(j+1));
                         SetEl(j+1,pr);
                        end;
                       fpgettimeofday(@timef,nil);
                       mks1:=int64(timeb.tv_sec)*1000000+timeb.tv_usec;
                       mks2:=int64(timef.tv_sec)*1000000+timef.tv_usec;
                       if (mks2-mks1)>maxdt then maxdt:=mks2-mks1;
                end;
        fpgettimeofday(@tf,nil);
        mks1:=int64(tb.tv_sec)*1000000+tb.tv_usec;
        mks2:=int64(tf.tv_sec)*1000000+tf.tv_usec;
        writeln('New middle Buble sorting is '+inttostr(mks2-mks1));

writeln('time to one change operation is '+inttostr(maxdt));

и получаю
Код: Выделить всё
New middle Buble sorting is 323649
time to one change operation is 227
New middle Buble sorting is 323737
time to one change operation is 227
New middle Buble sorting is 323517
time to one change operation is 227


Дмитрий Анатольевич, почему нельзя приложить файлик с кодом программы?
Не относитесь к этой жизни слишком серьезно,господа.Все равно вам из неё живым не выбраться.
Gemini
 
Сообщения: 90
Зарегистрирован: 13 янв 2009, 12:42
Откуда: Сейчас в Ша
Полное имя: Плешков Сергей Александрович

Re: Экзотическое поведение функции time под Windows

Сообщение andy ice 23 сен 2010, 13:48

Ничего экзотического в таком поведении нет, ибо скорее всего как Delphi так и другие паскаль-клоны используют системную функцию time.

MSDN сообщает:
Windows time is the number of milliseconds elapsed since the system started running. This format exists primarily for backward compatibility with 16-bit Windows.
...
И уточняет: The system timer runs at approximately 10ms. (вот они эти пресловутые 10 мс)

Собственно для подавляющего числа пользовательских приложений этого достаточно. Если недостаточно, то "If you need a higher resolution timer, use a multimedia timer or a high-resolution timer."

Т.е., как Владислав уже сказал, используйте QueryPerformanceCounter.

Итого: скорее всего разработчикам паскалей была достаточна такая точность, разработчикам приложений нужно учитывать такую особенность паскалей.
andy ice
 
Сообщения: 2
Зарегистрирован: 23 сен 2010, 12:46
Полное имя: Андрей Морозов

Re: Экзотическое поведение функции time под Windows

Сообщение xdsl 23 сен 2010, 21:57

Паскали тут не при чем, в Time вызывается именно виндовая API-функция. А с высокоточным счетчиком только одна проблема - никогда не знаешь, с какого ядра он счетчик вернул. По крайней мере мне неизвестно, как это определить. Если выяснится - будет только лучше. Иначе на многоядерных системах иногда возникает абсурдная ситуация - очередное полученное значение счетчика меньше предыдущего. Поэтому эксперименты с QueryPerformanceCounter забросили.

В принципе, после того, как стал понятны причины люфта в 10-15 мс, восприняли этот факт как данность и считаем погрешностью.
xdsl
 
Сообщения: 1236
Зарегистрирован: 09 дек 2008, 05:16
Откуда: ВЦ ШГПИ
Полное имя: Слинкин Д.А.


Вернуться в Алгоритмизация и программирование

Кто сейчас на конференции

Сейчас этот форум просматривают: нет зарегистрированных пользователей и гости: 2

cron