Измерение времени высокой точности C++ в Windows

Ctrl + ] для соответствия фигурным скобкам и круглым скобкам.

Ctrl + Сдвиг + ] выбирает код между парными скобками.

30
задан Gabriel Rodriguez 5 September 2012 в 07:33
поделиться

8 ответов

Если у вас есть многопоточное приложение, работающее на многоядерном компьютере QueryPerformanceCounter может (и будет) возвращать различные значения в зависимости от того, на каком ядре выполняется код. См. эту статью MSDN. ( rdtsc имеет ту же проблему)

Это не просто теоретическая проблема; мы столкнулись с этим в нашем приложении и пришли к выводу, что единственный надежный источник времени - это timeGetTime , который имеет точность только в миллисекундах (что, к счастью, было достаточно в нашем случае). Мы также попытались исправить привязку потоков для наших потоков, чтобы гарантировать, что каждый поток всегда будет получать согласованное значение из QueryPerformanceCounter , это сработало, но полностью убило производительность в приложении.

Подводя итог, нет '

34
ответ дан 27 November 2019 в 23:29
поделиться

Вот класс Timer, который будет работать как для Windows, так и для Linux:

#ifndef INCLUDE_CTIMER_HPP_
#define INCLUDE_CTIMER_HPP_

#if defined(_MSC_VER)
#  define NOMINMAX // workaround a bug in windows.h
#  include <windows.h>
#else
#  include <sys/time.h>
#endif

namespace Utils
{
   class CTimer
   {
   private:
#     if defined(_MSC_VER)
         LARGE_INTEGER m_depart;
#     else
         timeval m_depart;
#     endif

   public:
      inline void start()
      {
#        if defined(_MSC_VER)
            QueryPerformanceCounter(&m_depart);
#        else
            gettimeofday(&m_depart, 0);
#        endif
      };

      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
      };
   };
}
#endif // INCLUDE_CTIMER_HPP_
0
ответ дан 27 November 2019 в 23:29
поделиться

rdtsc инструкция является наиболее точной.

0
ответ дан 27 November 2019 в 23:29
поделиться

Что касается ответа Конрада Рудольфа, обратите внимание, что по моему опыту частота счетчика производительности составляет около 3,7 МГц, что составляет субмикросекунду, но определенно не наносекундную точность. Фактическая частота зависит от оборудования (и от режима энергосбережения). Наносекундная точность в любом случае несколько неразумна, поскольку задержки прерывания и время переключения контекста процесса / потока намного больше, чем это, и это также порядок величины отдельных машинных инструкций.

0
ответ дан 27 November 2019 в 23:29
поделиться

Что ж, большинству людей не нравятся парадигмы пользовательского интерфейса, которые ведут себя как учитель (который умнее, чем вы сами),

помощь должна предоставляться, когда пользователь об этом просит. 1212] полезная вырезка http://middaysoftware.com/MinhsBlogs/DirectGallery/bad_clippy.

0
ответ дан 27 November 2019 в 23:29
поделиться

Вы можете использовать API счетчика производительности, как предложил Конрад Рудольф, но следует предупредить, что он основан на частоте процессора. Эта частота нестабильна, например, когда включен режим энергосбережения. Если вы хотите использовать этот API, убедитесь, что ЦП работает с постоянной частотой.

В противном случае вы можете создать некую «статистическую» систему, коррелирующую тактовые импульсы ЦП с часами BIOS ПК. Последний вариант менее точен, но постоянен.

1
ответ дан 27 November 2019 в 23:29
поделиться

Windows имеет API высокопроизводительного счетчика .

Вам нужно получить форму тиков QueryPerformanceCounter и разделить на частоту процессора , предоставляется QueryPerformanceFrequency .

LARGE_INTEGER frequency;
if (::QueryPerformanceFrequency(&frequency) == FALSE)
    throw "foo";

LARGE_INTEGER start;
if (::QueryPerformanceCounter(&start) == FALSE)
    throw "foo";

// Calculation.


LARGE_INTEGER end;
if (::QueryPerformanceCounter(&end) == FALSE)
    throw "foo";

double interval = static_cast<double>(end.QuadPart - start.QuadPart) / frequency.QuadPart;

Этот интервал должен быть в секундах.

14
ответ дан 27 November 2019 в 23:29
поделиться

Спасибо за ввод ... хотя я не смог получить нано или микросекундное разрешение, которое могло бы все прошло хорошо, однако я смог придумать это ... может быть, кто-то еще сочтет это полезным.

    class N_Script_Timer
{
    public:
        N_Script_Timer()
        {
            running = false;
            milliseconds = 0;
            seconds = 0;
            start_t = 0;
            end_t = 0;
        }
        void Start()
        {
            if(running)return;
            running = true;
            start_t = timeGetTime();
        }
        void End()
        {
            if(!running)return;
            running = false;
            end_t = timeGetTime();
            milliseconds = end_t - start_t;
            seconds = milliseconds / (float)1000;
        }
        float milliseconds;
        float seconds;

    private:
        unsigned long start_t;
        unsigned long end_t;
        bool running;
};
0
ответ дан 27 November 2019 в 23:29
поделиться
Другие вопросы по тегам:

Похожие вопросы: