Субмиллисекундная точность синхронизации в C или С++

Какие методы/методы существуют для получения субмиллисекундных данных синхронизации времени на C или С++, и какую точность и точность они предоставляют? Я ищу методы, которые не требуют дополнительного оборудования. Приложение предполагает ожидание примерно 50 микросекунд +/- 1 микросекунду, а некоторые внешние аппаратные средства собирают данные.

EDIT: ОС - это Wndows, возможно, с VS2010. Если я смогу получить драйверы и SDK для оборудования в Linux, я могу пойти туда, используя последний GCC.

Ответ 1

При работе с готовыми операционными системами точное время - чрезвычайно сложная и сложная задача. Если вы действительно нуждаетесь гарантированное время, единственным реальным вариантом является полная операционная система реального времени. Однако, если "почти всегда" достаточно хорошо, вот несколько трюков, которые вы можете использовать, что обеспечит хорошую точность под товарными Windows и Linux.

  • Используйте Sheilded CPU В основном это означает отключить сродство IRQ к выбранному процессору и установить маску аффинации процессора для всех других процессов на чтобы игнорировать ваш целевой процессор. В своем приложении установите совместимость процессора для работы только на вашем защищенном CPU. Эффективно это должно помешать ОС приостанавливать ваше приложение, поскольку оно всегда будет единственным выполняемым процессом для этого процессора.
  • Никогда не позволяйте вашему процессу охотно подчиняться ОС (который по своей сути не является детерминированным для операционных систем без реального времени). Нет выделения памяти, нет сокетов, нет мьютексов, нада. Используйте RDTSC для вращения в цикле while, ожидающего вашего целевого времени. Он будет потреблять 100% процессор, но это самый точный способ.
  • Если номер 2 немного драконен, вы можете "спать коротко", а затем записывать ЦП до вашего целевого времени. Здесь вы воспользуетесь тем фактом, что ОС планирует процессор с установленными интервалами. Обычно 100 раз в секунду или 1000 раз в секунду в зависимости от вашей ОС и конфигурации (в окнах вы можете изменить период планирования по умолчанию от 100/с до 1000/с с помощью мультимедийного API). Это может быть немного трудно получить, но по существу вам нужно определить, когда происходят периоды планирования ОС и рассчитать один до вашего целевого времени бодрствования. Спите на эту длительность, а затем, после пробуждения, вращайтесь на RDTSC (если вы используете один процессор... используйте QueryPerformanceCounter или эквивалент Linux, если нет), пока не наступит ваше целевое время. Иногда планирование ОС вызывает у вас промахи, но, вообще говоря, этот механизм работает очень хорошо.

Похоже, что это простой вопрос, но достижение "хороших" сроков становится экспоненциально более сложным, чем жестче ограничения времени. Удачи!

Ответ 2

Аппаратное обеспечение (и, следовательно, разрешение) варьируется от машины к машине. В Windows, в частности (я не уверен в других платформах), вы можете использовать QueryPerformanceCounter и QueryPerformanceFrequency, но имейте в виду, что вы должны вызывать оба из одного потока, и нет никаких строгих гарантий относительно разрешения (QueryPerformanceFrequency разрешено возвращать 0, что означает, что таймер с высоким разрешением не доступен). Однако на большинстве современных настольных компьютеров должно быть одно точное с микросекундами.

Ответ 3

boost:: datetime имеет часы с микросекундной точностью, но его точность зависит от платформы.

В документации указано:

ptime microsec_clock:: local_time() "Получите локальное время, используя часы второй секунды. В Unix-системах это реализовано с использованием GetTimeOfDay. На большинстве плат Win32 оно реализовано с использованием ftime. Системы Win32 часто не достигают разрешения по микросекундам через этот API. Если более высокое разрешение имеет решающее значение для вашего приложение проверит вашу платформу, чтобы увидеть достигнутое разрешение".

http://www.boost.org/doc/libs/1_43_0/doc/html/date_time/posix_time.html#date_time.posix_time.ptime_class

Ответ 4

Вы можете попробовать следующее:

struct timeval t; gettimeofday (& т, 0x0);

Это дает вам текущую временную метку в микросекундах. Я не уверен в точности.

Ответ 5

Вы можете попробовать технику, описанную здесь здесь, но она не переносима.

Ответ 6

Большинство современных процессоров имеют регистры для синхронизации или других целей. Например, на x86 с дней Pentium есть инструкция RDTSC, например. Компилятор может предоставить вам доступ к этой инструкции.

Подробнее см. wikipedia.

Ответ 7

timeval в sys/time.h имеет член 'tv_usec', который представляет собой микросекунды.

Эта ссылка и приведенный ниже код помогут проиллюстрировать:

http://www.opengroup.org/onlinepubs/000095399/basedefs/sys/time.h.html

timeval start;
timeval finish;

long int sec_diff;
long int mic_diff;

gettimeofday(&start, 0);
cout << "whooo hooo" << endl;
gettimeofday(&finish, 0);

sec_diff = finish.tv_sec - start.tv_sec;
mic_diff = finish.tv_usec - start.tv_usec;

cout << "cout-ing 'whooo hooo' took " << sec_diff << "seconds and " << mic_diff << " micros." << endl;

gettimeofday(&start, 0);
printf("whooo hooo\n");
gettimeofday(&finish, 0);

sec_diff = finish.tv_sec - start.tv_sec;
mic_diff = finish.tv_usec - start.tv_usec;

cout << "fprint-ing 'whooo hooo' took " << sec_diff << "seconds and " << mic_diff << " micros." << endl;

Ответ 8

Удачи, пытаясь сделать это с помощью MS Windows. Вам нужна операционная система реального времени, то есть одна, где время гарантировано повторяемо. Windows может переключиться на другой поток или даже на другой процесс в неподходящий момент. Вы также не сможете контролировать промахи в кэше.

Когда я выполнял роботизированное управление в реальном времени, я использовал очень легкую ОС под названием OnTime RTOS32, у которой есть частичный эмуляционный слой Windows API. Я не знаю, подходит ли она для того, что вы делаете. Однако в Windows вы, вероятно, никогда не сможете доказать, что он никогда не сможет дать своевременный ответ.

Ответ 9

Комбинация GetSystemTimeAsFileTime и QueryPerformanceCounter может привести к надежному набору кода для получения услуг времени с разрешением микросекунд в окнах.

См. этот комментарий в другом разделе здесь.