Временная точность до миллисекунды в C или C ++ - PullRequest
10 голосов
/ 25 мая 2010

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

РЕДАКТИРОВАТЬ: ОС является Wndows, вероятно, с VS2010. Если я смогу получить драйверы и SDK для аппаратного обеспечения в Linux, я смогу использовать последнюю версию GCC.

Ответы [ 9 ]

14 голосов
/ 25 мая 2010

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

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

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

5 голосов
/ 25 мая 2010

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

2 голосов
/ 25 мая 2010

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

1 голос
/ 25 мая 2010

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

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

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

0 голосов
/ 13 июля 2012

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

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

0 голосов
/ 25 мая 2010

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

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

0 голосов
/ 25 мая 2010

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 голосов
/ 25 мая 2010

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

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

0 голосов
/ 25 мая 2010

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...