В поисках точного пути к микропроцессорному тестированию небольших путей кода, написанных на C ++ и работающих в Linux / OSX - PullRequest
5 голосов
/ 10 ноября 2010

Я собираюсь сделать несколько очень простых микро-бенчмарков для небольших путей кода, таких как узкие циклы, которые я написал на C ++. Я работаю на Linux и OSX и использую GCC. Какие средства есть для точности до миллисекунды? Я думаю, что простой тест многократного выполнения пути к коду (несколько десятков миллионов?) Даст мне достаточно последовательности, чтобы получить хорошее чтение. Если кто-нибудь знает о предпочтительных методах, пожалуйста, не стесняйтесь их предлагать.

Ответы [ 4 ]

6 голосов
/ 10 ноября 2010

Вы можете использовать "rdtsc" инструкцию процессора на x86 / x86_64.Для многоядерных систем проверьте возможность «constant_tsc» в CPUID (/ proc / cpuinfo в linux) - это будет означать, что все ядра используют один и тот же счетчик тиков, даже при динамическом изменении частоты и спящем режиме.

Если ваш процессор делаетне поддерживает constant_tsc, не забудьте связать вашу программу с ядром (taskset утилита в Linux).

При использовании rdtsc на ЦП с ошибками (все, кроме Intel Atom, могут иметь некоторые другиеend cpus), добавьте инструкцию «ordering» перед, например, «cpuid» - это временно отключит переупорядочение команд.

Кроме того, в MacOsX есть «Shark», который может измерять некоторые аппаратные события в вашем коде.

RDTSC и неисправные процессоры.Подробнее в разделе 18 руководства 2-го великого тумана по оптимизации: Оптимизация подпрограмм на языке ассемблера: руководство по оптимизации для платформ x86 (основной сайт со всеми пятью руководствами - http://www.agner.org/optimize/)

http://www.scribd.com/doc/1548519/optimizing-assembly

На всех процессорах с не по порядку выполнением необходимо вставить XOR EAX, EAX / CPUID до и после каждого чтенияСчетчик для предотвращения его параллельного выполнения с чем-либо еще. CPUID является командой сериализации, что означает, что он очищает конвейер и ожидает завершения всех ожидающих операций, прежде чем продолжить. Это очень полезно для целей тестирования.

0 голосов
/ 02 декабря 2013

Microbenchmark должен запускать один и тот же код в цикле, предпочтительно в течение большого количества итераций.Я использовал следующее и запустил его с помощью утилиты time (1);

наблюдались следующие предостережения

  • , если тест не выдает вычисление, которое выводится на печать, то код удаляется оптимизацией - это делает gcc с -O3.

  • тестовые функции test () и lookup () должны быть реализованы в другом исходном файле, чем цикл итерации;если они находятся в одном и том же файле и функция поиска возвращает постоянное значение, то оптимизация кода не вызовет его, ни разу, просто умножит возвращаемое значение на количество итераций!

файл main.c

#include <stdio.h>

#define RUN_COUNT 10000000

void init();
int  lookup();


main()
{
  int sum = 0;
  int i;

  init();


  for(i = 0; i < RUN_COUNT; i++ ) {
    sum  += lookup();
  }

  printf("%d", sum );
}
0 голосов
/ 10 ноября 2010

Cachegrind / kCachegrind хороши для очень мелкозернистого профилирования. Я не верю, что они доступны для OS X, но результаты, которые вы получаете в Linux, должны быть репрезентативными.

0 голосов
/ 10 ноября 2010

Это то, что я использовал в прошлом:

inline double gettime ()
{
    timeval tv;
    gettimeofday (&tv, NULL);
    return double (tv.tv_sec) + 0.000001 * tv.tv_usec;
}

А потом:

double startTime = gettime();
// your code here
double runTime = gettime() - startTime;

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

...