Суб-миллисекундной точности синхронизации в C или C++
какие существуют методы / методы для получения субмиллисекундных точных данных синхронизации в C или C++, и какую точность и точность они обеспечивают? Я ищу методы, которые не требуют дополнительного оборудования. Приложение включает в себя ожидание примерно 50 микросекунд + / - 1 микросекунд, в то время как некоторые внешние аппаратные средства собирают данные.
EDIT: OS - это Wndows, возможно, с VS2010. Если я могу получить драйверы и SDK для оборудования на Linux, я могу пойти туда, используя последний GCC.
9 ответов
при работе с готовыми операционными системами точное время является чрезвычайно сложной и сложной задачей. Если вы действительно нужно гарантированное время, единственный реальный вариант полная операционная система в реальном времени. Однако, если "почти всегда" достаточно хорошо, вот несколько трюков, которые вы можете использовать, которые обеспечат хорошую точность под товарными Windows & Linux
- использовать Sheilded CPU в основном, это означает отключить сродство IRQ для выбранного CPU & установите маску сходства процессора для всех других процессов на машине, чтобы игнорировать целевой процессор. В приложении установите сродство ЦП для запуска только на экранированном ЦП. Фактически, это должно предотвратить приостановку вашего приложения, поскольку оно всегда будет единственным выполняемым процессом для этого процессора.
- никогда не позволяйте, чтобы ваш процесс добровольно отдавал управление ОС (которая по своей сути недетерминирована для ОС не в реальном времени). Ни выделения памяти, ни сокетов, ни мьютексов, ничего. Используйте RDTSC для вращения в цикле while, ожидая прибытия вашего целевого времени. Он будет потреблять 100% CPU, но это самый точный способ пойти.
- если номер 2 немного слишком драконовский, вы можете "спать коротко", а затем записать процессор до вашего целевого времени. Здесь вы используете тот факт,что ОС планирует CPU с заданными интервалами. Обычно 100 раз в секунду или 1000 раз в секунду в зависимости от вашей ОС и конфигурации (в windows вы можете изменить период планирования по умолчанию От 100/s до 1000 / s с помощью мультимедийного API). Это может быть немного трудно получить право, но по существу вам нужно определить, когда периоды планирования ОС происходят и вычислить один до вашего целевого времени пробуждения. Спите в течение этого времени, а затем, проснувшись, вращайтесь на RDTSC (если вы находитесь на одном процессоре... используйте QueryPerformanceCounter или эквивалент Linux, если нет), пока не придет ваше целевое время. Иногда планирование ОС заставит вас пропустить, но, вообще говоря, этот механизм работает довольно хороший.
Это кажется простым вопросом,но достижение "хорошего" времени получить экспоненциально сложнее, чем плотнее ваши временные ограничения. Удачи!
оборудование (и, следовательно, разрешение) варьируется от машины к машине. В Windows, в частности (я не уверен в других платформах), вы можете использовать QueryPerformanceCounter и QueryPerformanceFrequency, но имейте в виду, что вы должны вызывать оба из одного потока, и нет строгих гарантий разрешения (QueryPerformanceFrequency разрешено возвращать 0, что означает, что таймер высокого разрешения недоступен). Однако на большинстве современных настольных компьютеров будьте одним точным до микросекунд.
boost:: datetime имеет микросекундные часы точности, но его точность зависит от платформы.
в документации:
ptime microsec_clock:: local_time() "Получите местное время, используя часы с субсекундным разрешением. В системах Unix это реализовано с использованием GetTimeOfDay. На большинстве платформ Win32 он реализован с использованием ftime. Системы Win32 часто не достигают разрешения микросекунды через этот API. Если более высокое разрешение имеет решающее значение для вашего приложения платформа для просмотра достигнутого разрешения."
вы можете попробовать следующее:
структура timeval t; gettimeofday (&t,0x0);
Это дает вам текущую метку времени в микро-секунд. Я не уверен в точности.
вы можете попробовать описанную технику здесь, но это не портативный.
большинство современных процессоров имеют регистры для синхронизации или других целей инструментирования. На x86 с Pentium дней есть RDTSC
инструкции, например. Компилятор может предоставить вам доступ к этой инструкции.
посмотреть Википедия для получения дополнительной информации.
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;
удачи, пытаясь сделать это с MS Windows. Вам нужна операционная система в реальном времени, то есть такая, где время гарантировано повторяемо. Windows можно переключиться на другой поток или даже другой процесс в неподходящий момент. Вы также не будете иметь никакого контроля над промахами кэша.
когда я занимался роботизированным управлением в реальном времени, я использовал очень легкую ОС под названием OnTime RTOS32, которая имеет частичный уровень эмуляции Windows API. Не знаю, подойдет ли она для чего ты делаешь. Однако с Windows вы, вероятно, никогда не сможете доказать, что он никогда не даст своевременного ответа.
сочетание GetSystemTimeAsFileTime
и QueryPerformanceCounter
может привести к надежному набору кода для получения служб времени разрешения микросекунды в windows.
посмотреть этой комментарий в другом потоке здесь.