Работа с таймером процессора

Результаты традиционного измерения очень маленьких интервалов времени часто оказываются неточными из-за того, что какое-то время тратиться на выполнение промежуточных фоновых операций операционной системы и функций определения системного времени. Для получения более точного результата можно определить начальное и конечное время интервала с помощью непосредственного обращения к таймеру процессора, а затем вычесть время, затрачиваемое на обработку прерывания.

В архитектурах POWER и POWER2 таймер процессора реализован в виде пары специальных регистров. Архитектура С процессором POWER включает в себя 64-разрядный регистр TimeBase. К этим регистрам могут обращаться только программы, написанные на ассемблере.
Прим.: Таймер процессора отсчитывает абсолютное время. Если в промежуток времени между обращениями к таймеру произойдет прерывание, вычисленная продолжительность интервала будет содержать время обработки прерывания, а также, возможно, время работы других процессов, которые могли быть выполнены до того, как управление было возвращено анализируемой программе. Все результаты измерений, полученные с помощью таймера процессора, являются неточными. Их можно использовать только после тщательной проверки.

Для обращения к регистрам TimeBase предусмотрены три библиотечные функции, не зависящие от архитектуры. Ниже приведено описание этих функций:

read_real_time()
Эта функция получает точное время из соответствующего источника и сохраняет его в виде двух 32-разрядных значений.
read_wall_time()
Эта функция получает значение TimeBase из соответствующего источника и сохраняет его в виде двух 32-разрядных значений.
time_base_to_time()
Эта функция преобразует содержимое регистра TimeBase в секунды и наносекунды.

Для определения времени и преобразования значения в обычный формат предусмотрено две разные функции, что позволяет минимизировать объем ресурсов, необходимых для получения значения времени.

Ниже приведен пример применения функций read_real_time() и time_base_to_time() для определения времени выполнения некоторой программы:
#include <stdio.h>
#include <sys/time.h>

int main(void) {
   timebasestruct_t start, finish;
   int val = 3;
   int w1, w2;
   double time;

   /* считывание времени перед началом операции */
   read_real_time(&start, TIMEBASE_SZ);

   /* начало контролируемого фрагмента кода */
   printf("This is a sample line %d \n", val);
   /* конец контролируемого фрагмента кода */

   /* считывание времени после завершения операции
   read_real_time(&finish, TIMEBASE_SZ);

   /* безусловный вызов процедур преобразования, гарантирующий, что */
   /* оба значения представлены в  */
   /* секундах и наносекундах */
   /* независимо от аппаратной платформы.                                  */
   time_base_to_time(&start, TIMEBASE_SZ);
   time_base_to_time(&finish, TIMEBASE_SZ);

   /* Вычисление разности конечного и начального времени */
   w1 = finish.tb_high - start.tb_high; /* возможно, ноль */
   w2 = finish.tb_low - start.tb_low;

   /* Если при измерении произошел перенос из младших разрядов в */
   /* старшие, результаты могут оказаться неверными                  */
   if (w2 < 0) {
      w1--;
      w2 += 1000000000;
   }

   /* преобразование чистого времени исполнения в число микросекунд в */
   /* формате с плавающей точкой */
   time = ((double) w2)/1000.0;
   if (w1 > 0)
      time += ((double) w1)*1000000.0;

   printf("Время исполнения %9.3f мкс \n", time);
   exit(0);
}

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

Если эти тесты дают близкие к истинным показатели производительности, то измерения кода будут повторяемыми. Зная это время, можно рассчитать среднее время операции, однако это среднее время может включать затраты на обработку прерываний и другие посторонние операции. При измерении времени выполнения для каждого отдельного запуска можно проанализировать результаты и выбрать наиболее разумные, однако при этом в каждом измерении будут присутствовать отклонения, связанные с доступом к таймеру. Иногда бывает полезно объединить оба подхода и сравнить результаты. В любом случае при выборе метода измерения следует учитывать, с какой целью они проводятся.