OberonCore

Библиотека  Wiki  Форум  BlackBox  Компоненты  Проекты
Текущее время: Суббота, 27 Апрель, 2024 10:42

Часовой пояс: UTC + 3 часа




Начать новую тему Ответить на тему  [ Сообщений: 10 ] 
Автор Сообщение
 Заголовок сообщения: Kernel.Time
СообщениеДобавлено: Четверг, 18 Декабрь, 2008 15:49 
Аватара пользователя

Зарегистрирован: Пятница, 25 Ноябрь, 2005 18:55
Сообщения: 2272
Откуда: Россия, Нижний Новгород
Как известно, тики в Блэкбоксе 64-битные и получаются из 32-битных KERNEL32.GetTickCount() по следующему алгоритму:
Код:
PROCEDURE Time* (): LONGINT;
   VAR t: INTEGER;
BEGIN
   t := KERNEL32.GetTickCount();
   IF t < told THEN INC(shift) END;
   told := t;
   RETURN shift * 100000000L + t
END Time;

(Я этот алгоритм передрал к себе в C#)

Так вот. Есть подозрение, что с функцией KERNEL32.GetTickCount() могут быть грабли...

Подозрения основаны на том, что в .Net ей соответствует функция System.Environment.TickCount, а её значения могут плавать на многопроцессорной машине, в чём я сегодня убедился лично.

На 16 процессорной машине (Intel Xeon E7340, Linux SS 2.6.18, Mono 1.2), несколько раз в секунду функция System.Environment.TickCount выдаёт значение на 1 тик меньше значения которое она только что выдала в другом потоке.

У меня был код аналогичный приведёному выше (разумеется с блокировками) так вот когда время шло на 1 тик вспять, то глобальный счётчик инкрементировался на четыре миллиарда :twisted: :twisted: :twisted:


Вернуться к началу
 Профиль  
 
 Заголовок сообщения: Re: Kernel.Time
СообщениеДобавлено: Четверг, 18 Декабрь, 2008 17:20 

Зарегистрирован: Понедельник, 30 Июль, 2007 10:53
Сообщения: 1538
Откуда: Беларусь, Минск
Непонятно что-то. Там несколько машин или несколько процессоров? Если несколько процессоров, то причём тут время? Они же ко времени отношения не имеют. Или там было много потоков, дёргавших счётчик? Хотя всё равно не понятна разница на 1 мс. Контекст, вроде, так быстро переключиться не может.


Вернуться к началу
 Профиль  
 
 Заголовок сообщения: Re: Kernel.Time
СообщениеДобавлено: Пятница, 19 Декабрь, 2008 13:57 
Аватара пользователя

Зарегистрирован: Пятница, 25 Ноябрь, 2005 18:55
Сообщения: 2272
Откуда: Россия, Нижний Новгород
Одна машина. У неё 8 процессоров с гипертредингом, итого 16 логических процессоров. Работают несколько потоков. Каждый поток хочет знать сколько сейчас 64-битных тиков. Поток обращается к этой функции (из предыдущего сообщения). Функция разумеется защищена эксклюзивным блоком (одновременно к ней разрешено обращение только из одного потока). Несколько раз в секунду значение возвращаемое функцией прыгает вверх на четыре миллиарда тиков. Стал разбираться. Оказалось, что значения выдаваемые функцией System.Environment.TickCount не растут монотонно, а несколько раз в секунду бывают на 1 тик меньше предыдущего, т.е. плавают.


Вернуться к началу
 Профиль  
 
 Заголовок сообщения: Re: Kernel.Time
СообщениеДобавлено: Пятница, 19 Декабрь, 2008 14:03 
Аватара пользователя

Зарегистрирован: Пятница, 25 Ноябрь, 2005 18:55
Сообщения: 2272
Откуда: Россия, Нижний Новгород
>> Контекст, вроде, так быстро переключиться не может.

Может. Вызываете в одном потоке Sleep(0) и контекст переключается на второй поток. Во втором потоке опять вызываете Sleep(0) и контекст переключается на третий поток и т.д.. Так за 1 ms несколько сотен раз можно контекст переключить.


Вернуться к началу
 Профиль  
 
 Заголовок сообщения: Re: Kernel.Time
СообщениеДобавлено: Пятница, 19 Декабрь, 2008 15:04 

Зарегистрирован: Понедельник, 30 Июль, 2007 10:53
Сообщения: 1538
Откуда: Беларусь, Минск
По-моему, скорость переключения потоков в лучшем случае - один такт системной шины. Чтобы переключиться на другой поток потребуется обратиться к ОЗУ. В вырожденном случае контекст может сохраниться в кэше (и восстановиться оттуда), но я не знаю, будет ли это влиять на скорость переключения потоков.

По поводу времени в обратном направлении. А не могут ли потоки не вовремя засыпать? Сначала отпишется последний поток, затем предпоследний, затем первый из обращавшихся к счётчику времени...


Вернуться к началу
 Профиль  
 
 Заголовок сообщения: Re: Kernel.Time
СообщениеДобавлено: Пятница, 19 Декабрь, 2008 19:14 
Аватара пользователя

Зарегистрирован: Пятница, 25 Ноябрь, 2005 18:55
Сообщения: 2272
Откуда: Россия, Нижний Новгород
>> А не могут ли потоки не вовремя засыпать?

Внутри критической секции-то? Да могут, но это ни на что не влияет. Всё равно внутрь критической секции никто не войдёт пока он не проснётся и не выйдет из неё.

Инициализация:
Код:
long ticks = 0;
uint old = (uint)GetTickCount();

Вычисление нового значения ticks устойчивое к ошибке операционной системы:
Код:
Lock();
uint t = (uint)GetTickCount();
uint dt = t - old;
if (dt < int.MaxValue)
{
  old = t;
  tiks += dt;
}
else
{
  Log.Fatal("Floating time system error.");
}
Unlock();

Предполагается, что этот код вызывается чаще чем один раз в две недели, так что разницы dt >= int.MaxValue в обычной ситуации быть не может.


Вернуться к началу
 Профиль  
 
 Заголовок сообщения: Re: Kernel.Time
СообщениеДобавлено: Суббота, 20 Декабрь, 2008 13:28 

Зарегистрирован: Понедельник, 30 Июль, 2007 10:53
Сообщения: 1538
Откуда: Беларусь, Минск
Как я понимаю, в целях отладки Вы получаете время и выводите его в лог. В данной критической секции в лог вывода нет, значит можно допустить, что поток выходит из неё и засыпает (до вывода в лог). Затем время получает второй поток, выходит из секции, печатается и завершается. Просыпается первый поток...
Или такая ситуация в Вашем конкретном случае невозможна (скажем, это было предусмотрено)?


Вернуться к началу
 Профиль  
 
 Заголовок сообщения: Re: Kernel.Time
СообщениеДобавлено: Суббота, 20 Декабрь, 2008 21:28 
Аватара пользователя

Зарегистрирован: Пятница, 25 Ноябрь, 2005 18:55
Сообщения: 2272
Откуда: Россия, Нижний Новгород
1) Я, разумеется, печатал тики в лог внутри эксклюзивного блока. Просто в приведённом здесь коде этого не написал, так как...
2) В приведённом примере кода, доказательством плавания тикометра является осуществляющееся несколько раз в секунду событие вывода Log.Fatal("Floating time system error.");


Вернуться к началу
 Профиль  
 
 Заголовок сообщения: Re: Kernel.Time
СообщениеДобавлено: Понедельник, 22 Декабрь, 2008 11:49 

Зарегистрирован: Понедельник, 30 Июль, 2007 10:53
Сообщения: 1538
Откуда: Беларусь, Минск
Ну тогда хочется, чтобы это был баг .NET, а не проблемы железа...


Вернуться к началу
 Профиль  
 
 Заголовок сообщения: Re: Kernel.Time
СообщениеДобавлено: Понедельник, 22 Декабрь, 2008 13:06 

Зарегистрирован: Четверг, 12 Июль, 2007 23:18
Сообщения: 1982
Откуда: Узбекистан, Чирчик
Возможно даже, что это проблема не .NET, а Mono.
А Вы не пробовали ставить Mono 2?


Вернуться к началу
 Профиль  
 
Показать сообщения за:  Поле сортировки  
Начать новую тему Ответить на тему  [ Сообщений: 10 ] 

Часовой пояс: UTC + 3 часа


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

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


Вы не можете начинать темы
Вы не можете отвечать на сообщения
Вы не можете редактировать свои сообщения
Вы не можете удалять свои сообщения
Вы не можете добавлять вложения

Найти:
Вся информация, размещаемая участниками на конференции (тексты сообщений, вложения и пр.) © 2005-2024, участники конференции «OberonCore», если специально не оговорено иное.
Администрация не несет ответственности за мнения, стиль и достоверность высказываний участников, равно как и за безопасность материалов, предоставляемых участниками во вложениях.
Без разрешения участников и ссылки на конференцию «OberonCore» любое воспроизведение и/или копирование высказываний полностью и/или по частям запрещено.
Powered by phpBB® Forum Software © phpBB Group
Русская поддержка phpBB