Синхронизация 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.

Другие вопросы по тегам