Синхронизация C++, миллисекунды с последней секунды
Я работаю над приложением C++, которое нуждается в подробной информации о времени, вплоть до миллисекундного уровня.
Мы намерены собрать время до второй точности, используя стандарт time()
функция в <ctime>
, Мы хотели бы дополнительно собрать миллисекунды, прошедшие с последней секунды, заданной time()
,
Кто-нибудь знает удобный способ получения этой информации?
10 ответов
Boost.DateTime имеет представление в миллисекундах и наносекундах, ЕСЛИ базовая платформа поддерживает их. В то время как он использует специфичный для платформы код, он скрывает эти детали от вашего кода.
Если это большое дело, у них есть другой способ сделать независимое от платформы разрешение за секунду. На этой странице пара абзацев ниже рассказывается о том, как это сделать.
(Со страницы)
Например, предположим, что мы хотим построить с использованием счетчика, который представляет десятые доли секунды. То есть каждый тик составляет 0,1 секунды.
int number_of_tenths = 5;
//create a resolution independent count -- divide by 10 since there are
//10 tenths in a second.
int count = number_of_tenths*(time_duration::ticks_per_second()/10);
time_duration td(1,2,3,count); //01:02:03.5 //no matter the resolution settings
Существует не переносимое решение этой проблемы, поскольку ANSI C не определяет стандартную функцию времени с точностью до миллисекунды. Если вы используете Windows, вы можете использовать GetTickCount(), timeGetTime() или QueryPerformanceCounter()/QueryPerformanceFrequency(). Имейте в виду, что они имеют разную точность и разные затраты времени выполнения.
Есть другие подобные функции в других операционных системах; Я не уверен, что они с моей головы.
GetTickCount в Windows gettimeofday в * nix QueryPerformanceCounter в Windows для лучшего разрешения (хотя GetTickCount должен это делать)
Высокое разрешение и низкие затраты времени для процессоров Intel
Если вы используете аппаратное обеспечение Intel, вот как прочитать счетчик команд процессора в режиме реального времени. Он сообщит вам количество циклов ЦП, выполненных с момента загрузки процессора. Это, вероятно, самый точный счетчик, который вы можете получить для измерения производительности.
Обратите внимание, что это количество циклов ЦП. В Linux вы можете получить скорость процессора из / proc / cpuinfo и разделить, чтобы получить количество секунд. Преобразование этого в двойное довольно удобно.
Когда я запускаю это на своей коробке, я получаю
11867927879484732 11867927879692217 это заняло так много времени, чтобы вызвать printf: 207485
Вот руководство Intel для разработчиков, которое дает массу деталей.
#include < stdio.h > // stackru bug: pre tag eats the filenames,
#include < stdint.h > // so i had to put spaces in the angle brackets
inline uint64_t rdtsc() {
uint32_t lo, hi;
__asm__ __volatile__ (
"xorl %%eax, %%eax\n"
"cpuid\n"
"rdtsc\n"
: "=a" (lo), "=d" (hi)
:
: "%ebx", "%ecx");
return (uint64_t)hi << 32 | lo;
}
main()
{
unsigned long long x;
unsigned long long y;
x = rdtsc();
printf("%lld\n",x);
y = rdtsc();
printf("%lld\n",y);
printf("it took this long to call printf: %lld\n",y-x);
}
Как уже говорили другие, нет портативного способа сделать это.
Что я делаю (в msvC++ и linux/g++) - я использую следующий класс, который использует QueryPerformanceCounter в Windows и gettimeofday в Linux. Это класс таймера, который может дать вам истекшее время между двумя вызовами. Возможно, вы захотите изменить его в соответствии с вашими потребностями.
#if defined(_MSC_VER)
# define NOMINMAX // workaround un bug dans windows.h qui define des macros
// "min" et "max" qui entrent en conflit avec la STL.
# include <windows.h>
#else
# include <sys/time.h>
#endif
namespace Utils
{
/**
* Implémente un chronométre qui mesure le temps etre deux appels.
*/
class CTimer
{
private:
# if defined(_MSC_VER)
LARGE_INTEGER m_depart;
# else
timeval m_depart;
# endif
public:
/**
* Démarre le timer.
*
* Cette fonction sert à démarrer le timer. Si le timer est déja
* démarrer, elle le redémarre simplement.
*/
inline void start()
{
# if defined(_MSC_VER)
QueryPerformanceCounter(&m_depart);
# else
gettimeofday(&m_depart, 0);
# endif
};
/**
* Retourne le nombre de secondes depuis le départ du timer.
*
* @return Nombre de secondes écoulés depuis le départ du timer
*/
inline float GetSecondes() const
{
# if defined(_MSC_VER)
LARGE_INTEGER now;
LARGE_INTEGER freq;
QueryPerformanceCounter(&now);
QueryPerformanceFrequency(&freq);
return (now.QuadPart - m_depart.QuadPart) / static_cast<float>(freq.QuadPart);
# else
timeval now;
gettimeofday(&now, 0);
return now.tv_sec - m_depart.tv_sec + (now.tv_usec - m_depart.tv_usec) / 1000000.0f;
# endif
};
};
}
Если вы работаете в Unix, gettimeofday () вернет секунды и микросекунды, вплоть до разрешения системных часов.
int gettimeofday(struct timeval *tv, struct timezone *tz);
struct timeval {
time_t tv_sec; /* seconds */
suseconds_t tv_usec; /* microseconds */
};
#include <ctime>
clock_t elapsed = static_cast<double>(clock() / CLOCKS_PER_SEC);
истекшее время процессора, в секундах.
разрешение зависит от операционной системы, но в большинстве систем оно лучше, чем разрешение в миллисекундах.
Все, что не в (c)time.h
заголовок требует специфических для ОС методов. Я считаю, что все эти методы являются вторым решением.
В какой ОС вы работаете?
Библиотека Intel http://www.threadingbuildingblocks.org/ имеет функцию для этого, но TBB в настоящее время доступен только для Intel и клонов (то есть она недоступна для SPARC, PowerPC, ARM и т. Д.)
Посмотрите на методы QueryPerformanceCounter, если это для Windows.