Помощь - Поиск - Пользователи - Календарь
Полная версия этой страницы: требуется кросплатформенный счётчик "тиков"
Форум на CrossPlatform.RU > Библиотеки > Другие библиотеки
Litkevich Yuriy
нужно средство для измерения относительного времени, быстрое.

У меня мысли только о неком счётчике "тиков", который, я думаю, есть в каждой ОСьке.
Возможно в стандарте Си/Си++ есть что-то такое, но я со стандартными вещами в этих языках плохо знаком.

Подкиньте идеи пожалуйста.
Kagami
Не совсем понял проблемы. Чем обычный QTimer не подходит?
Litkevich Yuriy
Цитата(Kagami @ 20.12.2009, 20:43) *
Чем обычный QTimer не подходит?
это довольно жирный класс, как следствие не быстрый.
Но самое главное это разрешающая способность - 1 мс. => 1 МГц, частота проца (ядра) сотни/тысячи мегагерц (единицы/десятки наносекунд)

Должен быть счётчик тикающий со скоростью 1/10 или 1/100 тактовой частоты ядра. Применять, например, в таком стиле:
...
int tic1, tic2, tic3;
tic1 = getTic();
// фрагмент кода
tic2 = getTic();
// фрагмент кода
tic3 = getTic();
// что-то сделать со снимками тиков
Нужно для тестовых измерений производительности.

Задача не позволяет делать измерительные циклы
BRE
Посмотри на исходники QTestLib, там вроде есть режим подсчета тиков процессора.

Цитата
The code insde the QBENCHMARK macro will be measured, and possibly also repeated several times in order to get an accurate measurement. This depends on the selected measurement back-end. Several back-ends are available an can be selected on the command line:
Имя Commmand-line Arguemnt Availability
Walltime (default) All platforms
CPU tick counter -tickcounter Windows, Mac OS X, Linux, many UNIX-like systems.
Valgrind/Callgrind -callgrind Linux (if installed)
Event Counter -eventcounter All platforms

Вот отсюда: http://doc.crossplatform.ru/qt/4.5.0/qtestlib-manual.html

Посмотри на файл src/testlib/3rdparty/cycle_p.h
ViGOur
Но так же нужно не забывать, что мы работаем не в ОС реального времени, потому тики будут точными на каждые 100 мс, на меньший промежуток времени нет. Ребята помнится уже как-то (достаточно давно) проверяли это дело на другом форуме.

И 100 мс справедливо помнится для винды, для никсов не помню проверяли или нет.
Litkevich Yuriy
Цитата(ViGOur @ 21.12.2009, 2:03) *
потому тики будут точными на каждые 100 мс
для системного (низкоуровнего) счётчика, тики будут соответствовать точности кварцевого резонатора (с соответствующим коэфф. деления).

Меня не интересует ширпотребный таймер/часы. именно счётчик тиков
trdm
Цитата(Litkevich Yuriy @ 20.12.2009, 23:50) *
Цитата(ViGOur @ 21.12.2009, 2:03) *
потому тики будут точными на каждые 100 мс
для системного (низкоуровнего) счётчика, тики будут соответствовать точности кварцевого резонатора (с соответствующим коэфф. деления).

Меня не интересует ширпотребный таймер/часы. именно счётчик тиков

GetTickCount
ы?
+
#include <sys/time.h>
unsigned long GetTickCount()
{
    struct timeval tv;
    gettimeofday(&tv,NULL);
    return (tv.tv_sec*1000+tv.tv_usec/1000);
}
Litkevich Yuriy
Цитата(trdm @ 21.12.2009, 5:29) *
GetTickCount
ы?
Цитата
The return value is the number of milliseconds that have elapsed since the system was started.


Там же нашёл, что-то похожее на то, что мне нужно: QueryPerformanceCounter

И ещё QueryUnbiasedInterruptTime про который написано:
Цитата
Points to a variable to receive the unbiased interrupt-time count in system time units of 100 nanoseconds.


Цитата(BRE @ 20.12.2009, 23:34) *
Посмотри на файл src/testlib/3rdparty/cycle_p.h
а вот это походу в яблочко. Буду штудировать
Iron Bug
полгода назад тот же вопрос меня мучил. нарыла в какой-то статье реализацию счётчика, маленько переделала под свои нужны. примерно вот так вышло (выкусываю куски кода, ибо весь он сильно объёмный и там не просто счётчики, а отдельный поток с организацией дилеев реализован для моих хардварных нужд):

 // это инициализация
  #ifndef __linux__
       ::QueryPerformanceFrequency(&frequency);
       simplistic_synchronize(ref_point);
  #endif

// это использование
        #ifdef __linux__
        // pt - типа boost::posix_time::ptime
        pt = microsec_clock::universal_time();  // это из boost - там под линём всё OK с таймерами
        #else
        pt = get_total_microseconds(); // под вендой начинаем извращаться через QueryPerformanceCounter
        #endif


детали реализации счётчика под венду:

это файл для счётчика под венду (идея в замерах по счётчику и периодической синхронизации его с системным временем для устранения набежавшей погрешности). взято хоть убей не помню откуда, возможно, что-то я ещё переделывала потом - уже плохо помню чего там было, но код работает:
typedef ptime time_type; // это boost::posix_time::ptime
struct reference_point
{
  FILETIME file_time;
  LARGE_INTEGER counter;
};

reference_point ref_point;
LARGE_INTEGER   frequency;
mutex           mtx;

void simplistic_synchronize(reference_point& ref_point)
{
  FILETIME      ft0 = { 0, 0 },
                ft1 = { 0, 0 };
  LARGE_INTEGER li;

  //
  // Spin waiting for a change in system time. Get the matching
  // performance counter value for that time.
  //
  ::GetSystemTimeAsFileTime(&ft0);
  do
  {
    ::GetSystemTimeAsFileTime(&ft1);
    ::QueryPerformanceCounter(&li);
  }
  while ((ft0.dwHighDateTime == ft1.dwHighDateTime) &&
         (ft0.dwLowDateTime == ft1.dwLowDateTime));

  ref_point.file_time = ft1;
  ref_point.counter = li;
}

void get_time(LARGE_INTEGER frequency, const reference_point&
    reference, FILETIME& current_time)
{
  LARGE_INTEGER li;

  ::QueryPerformanceCounter(&li);

  //
  // Calculate performance counter ticks elapsed
  //
  LARGE_INTEGER ticks_elapsed;

  ticks_elapsed.QuadPart = li.QuadPart -
      reference.counter.QuadPart;

  //
  // Translate to 100-nanoseconds intervals (FILETIME
  // resolution) and add to
  // reference FILETIME to get current FILETIME.
  //
  ULARGE_INTEGER filetime_ticks,
                 filetime_ref_as_ul;

  filetime_ticks.QuadPart =
      (ULONGLONG)((((double)ticks_elapsed.QuadPart/(double)
      frequency.QuadPart)*10000000.0)+0.5);
  filetime_ref_as_ul.HighPart = reference.file_time.dwHighDateTime;
  filetime_ref_as_ul.LowPart = reference.file_time.dwLowDateTime;
  filetime_ref_as_ul.QuadPart += filetime_ticks.QuadPart;

  //
  // Copy to result
  //
  current_time.dwHighDateTime = filetime_ref_as_ul.HighPart;
  current_time.dwLowDateTime = filetime_ref_as_ul.LowPart;
}

time_type create_time(FILETIME& ft) {
      // offset is difference (in 100-nanoseconds) from
      // 1970-Jan-01 to 1601-Jan-01
      boost::uint64_t c1 = 27111902;
      boost::uint64_t c2 = 3577643008UL; // 'UL' removes compiler warnings
      const boost::uint64_t OFFSET = (c1 << 32) + c2;

      boost::uint64_t filetime = ft.dwHighDateTime;
      filetime = filetime << 32;
      filetime += ft.dwLowDateTime;
      filetime -= OFFSET;
      // filetime now holds 100-nanoseconds since 1970-Jan-01

      // microseconds -- static casts supress warnings
      boost::uint32_t sub_sec = static_cast<boost::uint32_t>((filetime % 10000000) / 10);

      std::time_t t = static_cast<time_t>(filetime / 10000000); // seconds since epoch

      std::tm *curr_ptr = 0;
      curr_ptr = std::gmtime(&t);//, &curr);

      ptime::date_type d(curr_ptr->tm_year + 1900,
                  curr_ptr->tm_mon + 1,
                  curr_ptr->tm_mday);

      //The following line will adjusts the fractional second tick in terms
      //of the current time system.  For example, if the time system
      //doesn't support fractional seconds then res_adjust returns 0
      //and all the fractional seconds return 0.
      int adjust = static_cast<int>(ptime::time_duration_type::rep_type::res_adjust()/1000000);

      ptime::time_duration_type td(curr_ptr->tm_hour,
                            curr_ptr->tm_min,
                            curr_ptr->tm_sec,
                            sub_sec * adjust);
      return time_type(d,td);

    }


time_type get_total_microseconds(void)
{
     FILETIME  ft;
     {
        mutex::scoped_lock l(mtx);
        get_time(frequency, ref_point, ft);
     }
     return create_time(ft);
}


P.S. я тут быстро из кода навыдирала кусочков и комменты маленько добавила, могла чего-нить забыть. но в общем, я думаю, идея понятна.
Iron Bug
убираю копию... чота сеть глюканула - два раза послалось. сорри.
Litkevich Yuriy
собственно, в результате использовал это:
Цитата(BRE @ 20.12.2009, 23:34) *
Посмотри на файл src/testlib/3rdparty/cycle_p.h
DEADHUNT
#include <ctime>
clock_t clock();

не пробовал?
Litkevich Yuriy
Цитата(DEADHUNT @ 25.9.2010, 19:14) *
не пробовал?
неа, меня полностью устроило решение предложенное BRE
Iron Bug
Сегодня заговорили про таймеры на лине, и я вспомнила про один глючок таймеров на венде. Глючок противный, может, кому понадобится инфа про него. Конечно, на новых чипсетах этот глюк наверняка не присутствует, но знать полезно, а то напорешься - хрен догадаешься, что и почему.
Суть в том, что на некоторых материнках из-за проблем с южным мостом при нагрузке на PCI имеют место внезапные скачки счётчика QueryPerformanceCounter вперёд аж на несколько секунд. Так что нужно делать доп. проверку, сравнивая ещё и секундные показания с других таймеров.
Вот инфа от мелкософта, там и пример кода, как дополнительную проверку делать, и список глюкавых мостов:
http://support.microsoft.com/kb/274323

Для просмотра полной версии этой страницы, пожалуйста, пройдите по ссылке.
Форум IP.Board © 2001-2024 IPS, Inc.