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

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

Править: ОС является Wndows, вероятно, с VS2010. Если я могу получить драйверы и SDK для аппаратных средств на Linux, я могу пойти туда с помощью последнего GCC.

10
задан BЈовић 21 September 2011 в 21:02
поделиться

8 ответов

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

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

Кажется, что это простой вопрос, но добиться «хорошего» тайминга тем труднее, чем жестче ваши временные ограничения. Удачи!

14
ответ дан 3 December 2019 в 17:57
поделиться

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

2
ответ дан 3 December 2019 в 17:57
поделиться

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

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

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

1
ответ дан 3 December 2019 в 17:57
поделиться

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

См. википедию для получения дополнительной информации.

0
ответ дан 3 December 2019 в 17:57
поделиться

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

0
ответ дан 3 December 2019 в 17:57
поделиться

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;
0
ответ дан 3 December 2019 в 17:57
поделиться

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

5
ответ дан 3 December 2019 в 17:57
поделиться

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

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

0
ответ дан 3 December 2019 в 17:57
поделиться