Нравится? Делимся информацией!

четверг, 20 декабря 2012 г.

Измерение времени выполнения алгоритма _ профилирование


Применительно к Windows.
Полезные ссылки:
Из­ме­ре­ние ин­тер­ва­лов вре­ме­ни в Windows
Максимально точное измерение кода  Хабр
Оптимизация длинной арифметики на C++
Как можно подсчитать время работы алгоритма (части программы) __ простенько
C/C++. Измерение времени работы кода с точностью до такта.
Измеряем время выполнения
__rdtsc MSDN
Опрос показаний часов процессорного времени


Пока что изыскания в данной области закончились на создании программы  по измерению времени выполнения алгоритма извлечения квадратного корня.

#include <iostream>
#include <ctime>
#include <intrin.h> // для  __rdtsc()
#pragma intrinsic(__rdtsc)
int isqrt (unsigned x);
int main() {

double time;
int result;
//константа для задания верхнего предела для цикла for
const int max = 1000000;
const clock_t start = clock();

for(int i = 0; i < max; ++i)
result
= isqrt( 10);

time = static_cast< double >( clock() - start ) / CLOCKS_PER_SEC;

std
::cout<< "sqrt result:  " << result  << "  avarage time is " << time << std::endl;
std
::cout << "CLOCKS_PER_SEC: " << CLOCKS_PER_SEC << std::endl;
std
::cout << " time for one isqrt(): " << time / max <<std::endl;

unsigned __int64 startTick, stopTick, ticks;

startTick
= __rdtsc();
result
= isqrt( 10);
stopTick
= __rdtsc();

ticks
= stopTick - startTick;
std
::cout << " time in Ticks for one isqrt(): " << ticks << std::endl;

std
::cin.get();
return 0;
}
int isqrt (unsigned x)
{
unsigned m, y, b;
m
= 0x40000000;
y
= 0;
while (m != 0) { //16 раз
b
= y | m;
y
= y >> 1;
if (x >= b) {
x
= x - b;
y
= y | m;
}
m
= m >> 2;
}
return y;
}

Разница в измерениях получилась примерно в 2-3 раза. Максимум около 1000 тиков, минимум около 400. Причем я не уверен, что 400 - это минимум времени исполнения алгоритма.


Тоже самое примерно делается при помощи профилирования кода, где информация о производительности выводится в лог файл. За примером сюда .  
Профилирование - дело хорошее, но там все равно используется функция time(NULL) , которая требуемой точности не выдает:

void
__cyg_profile_func_enter (void *func,  void *caller)
{
if(fp_trace != NULL) {
fprintf(fp_trace, "e %p %p %lu\n", func, caller, time(NULL) );
}
}
А в итоге все сводится к поиску методов точного измерения интервалов времени в программах. И эти методы после можно использовать и в профилировании. ( Один из методов приведен по ссылке Profiling code on an embedded platform )

виды профайлеров.
По материалам ссылки было выбрано средство для профилирования AMD CodeAnalyst . Он может работать как на Линукс, так и под Windows. На этих платформах CodeAnalyst бесплатен. Программа может запускаться на процессорах фирмы Intel (правда, с некой потерей функциональности - не проверял). ссылка How I ran AMD CodeAnalyst on an Intel CPU




Core i7  есть APIC ( ссылка ), поэтому ожидается, что разрешающая способность профилирования будет достигать 100 мкс.

Вывод: так что можно производить профилирование кода специальными программами, а можно ваять “на коленке” и пользоваться собственным профайлингом.  

Еще вариант собственного профайлера:

#include <iostream>
// для профилирования
typedef unsigned long DWORD;
DWORD profile_code
();
//объявление профилируемого алгоритма
int isqrt (unsigned x);
//объявление вспомогательных данных
int res = 0;
int main()
{
std
::cout << " Result = " << profile_code() << std::endl;
std
::cin.get();
return 0;
}

DWORD profile_code
()
{
DWORD
clock, result;

_asm
{
xor eax, eax
cpuid
// снимаем все инструкции с конвейера
rdtsc
mov
[clock], eax
}
// профилируемый код
res
= isqrt( 10 );
// конец профилируемого кода

_asm
{
xor eax, eax
cpuid
rdtsc
sub eax,
[clock]
mov
[result], eax
}

return result;
}
int isqrt (unsigned x)
{
unsigned m, y, b;
m
= 0x40000000;
y
= 0;
while (m != 0) { //16 раз
b
= y | m;
y
= y >> 1;
if (x >= b) {
x
= x - b;
y
= y | m;
}
m
= m >> 2;
}
return y;
}

Тоже не ахти как:




Статья оказалась сумбурной, т.к. многое неясно, поэтому
поиск продолжается!!

Комментариев нет:

Отправить комментарий