Скачиваний:
15
Добавлен:
01.05.2014
Размер:
81.92 Кб
Скачать

3. Профилирование программ «test_cyc» и «test_sub»

Программа «test_cyc» показала при профилировании следующие результаты:

Time Counts

#define Size 10000

int i, tmp, dim[Size];

0.0000 1 void main()

{

0.0000 1 for(i=0;i<Size/10;i++){ tmp=dim[0]; dim[0]=dim[i]; dim[i]=tmp

0.0000 1 for(i=0;i<Size/5;i++){ tmp=dim[0]; dim[0]=dim[i]; dim[i]=tmp;

0.0000 1 for(i=0;i<Size/2;i++){ tmp=dim[0]; dim[0]=dim[i]; dim[i]=tmp;

0.0000 1 for(i=0;i<Size;i++) { tmp=dim[0]; dim[0]=dim[i]; dim[i]=tmp;

0.0000 1 for(i=0;i<Size/10;i++)

0.0053 1000 { tmp=dim[0]; dim[0]=dim[i]; dim[i]=tmp; };

0.0000 1 for(i=0;i<Size/5;i++)

0.0634 2000 { tmp=dim[0]; dim[0]=dim[i]; dim[i]=tmp; };

0.0000 1 for(i=0;i<Size/2;i++)

0.0775 5000 { tmp=dim[0]; dim[0]=dim[i]; dim[i]=tmp; };

0.0000 1 for(i=0;i<Size;i++)

0.4288 10000 { tmp=dim[0]; dim[0]=dim[i]; dim[i]=tmp; };

0.0000 1 for(i=0;i<Size/10;i++)

0.0051 1000 { tmp=dim[0];

0.1148 1000 dim[0]=dim[i];

0.0054 1000 dim[i]=tmp;

};

0.0000 1 for(i=0;i<Size/5;i++)

0.0640 2000 { tmp=dim[0];

0.0086 2000 dim[0]=dim[i];

0.0084 2000 dim[i]=tmp;

};

0.0000 1 for(i=0;i<Size/2;i++)

0.4086 5000 { tmp=dim[0];

0.0726 5000 dim[0]=dim[i];

0.4607 5000 dim[i]=tmp;

};

0.0000 1 for(i=0;i<Size;i++)

0.4822 10000 { tmp=dim[0];

0.3185 10000 dim[0]=dim[i];

0.5402 10000 dim[i]=tmp;

};

0.0000 1 }

Анализируя полученные результаты, можно заметить следующие закономерности:

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

Программа «test_sub» показала при профилировании следующие результаты:

Time Counts

const unsigned Size = 1000;

0.0000 4 void TestLoop(int nTimes)

{

static int TestDim[Size];

int tmp;

int iLoop;

0.0570 882 while (nTimes > 0)

{

0.0020 879 nTimes --;

0.0570 879 iLoop = Size;

39.211 879797 while (iLoop > 0)

{

42.213 878918 iLoop -- ;

39.204 878918 tmp = TestDim[0];

39.137 878918 TestDim[0] = TestDim[nTimes];

42.591 878918 TestDim[nTimes] = tmp;

}

}

0.0000 3 } /* TestLoop */

0.0000 1 void main()

{

0.0000 1 TestLoop(Size / 10);

0.0000 1 TestLoop(Size / 5);

0.0000 1 TestLoop(Size / 2);

0.0000 1 TestLoop(Size / 1);

0 0 }

Использование процедуры приводит к тому, что количество вызовов, приходящихся на каждую из строк её кода, весьма велико. Процесс выполнения программы под управлением профилировщика занимает много времени и приводит к тому, что результаты такого профилирования крайне неточны. К сожалению, вычислительная мощность машины, на которой выполнялось профилирование, не позволила дождаться завершения процесса, поэтому приведённые результаты нельзя считать полностью достоверными.

4. Обработка собственной программы

Программа LABCPP .CPP

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

Исходная программа на Паскале показала следующие результаты:

Time Counts

uses Crt;

const max = 20;

cyc_count = 20;

type index = 1..max;

ary = array[index] of real;

var x,y : ary;

n : integer;

seed: real;

{-------------------}

sumx,sumy: real;

sumxy, sumx2: real;

k: integer;

resa,resb: real;

cycle: integer;

function random(dummy: integer): real;

const pi = 3.14159;

var x : real; i : integer;

0.0007 200 begin

0.0006 200 x:=seed+pi;

0.0008 200 x:=exp(5.0*ln(x));

0.0006 200 seed:=x-trunc(x);

0.0008 200 random:=seed

0.0018 200 end;

procedure get_data(var x,y: ary; var n: integer);

const a = 5.0; b = 2.0;

var i,j : integer;

fudge : real;

0.0000 20 BEGIN

0.0001 20 fudge := 0.5;

0.0000 20 n := 10;

0.0000 20 for i:=1 to n do begin

0.0019 200 j:=n+1-i;

0.0552 200 x[i]:=j;

0.0582 200 y[i]:=(a*j + b) * (1.0 + (2.0 * random(0) - 1.0) * fudge

0.0011 200 end

0.0000 20 END;

procedure write_data;

{ print out the answers }

var i : integer;

0.0000 20 BEGIN

0.0003 20 writeln;

0.0002 20 writeln(' I X Y');

0.0000 20 for i:=1 to n do

0.0036 200 writeln(i:3,x[i]:8:1,y[i]:9:2);

0.0002 20 writeln

0.0000 20 END;

0.1090 1 BEGIN

0.0000 1 for cycle := 1 to cyc_count do begin

0.0000 20 ClrScr;

0.0000 20 seed:=4.0;

0.0000 20 get_data(x,y,n);

0.0000 20 write_data;

{----------------------------------------- Calculative part star

{ Accumulating statistics }

0.0000 20 sumx := 0; sumy := 0; sumxy := 0; sumx2 := 0;

0.0000 20 for k:=1 to n do begin

0.0006 200 sumx := sumx + x[k];

0.0006 200 sumy := sumy + y[k];

0.0005 200 sumxy := sumxy + x[k] * y[k];

0.0001 200 sumx2 := sumx2 + x[k] * x[k];

0.0008 200 end;

{ Recieving verdict }

0.0000 20 resa := (sumxy - sumx*sumy/n) / (sumx2 - sumx*sumx/n);

0.0000 20 resb := (sumy - resa * sumx) / n;

0.0005 20 writeln('Approximated with y=ax+b where a = ',resa,', b=',resb);

{------------------------------------------- Calculative part en

0.0000 20 end;

0.0010 1 END.

Execution Profile

Total time: 0.2409 sec

% of total: 100%

Исходная программа на Си ++ показала следующие результаты:

Time Counts

#include <Math.h>

#include <IOStream.h>

#include <Conio.h>

const pi = 3.14159;

const max = 20;

const cyc_count = 20;

float seed;

0.0001 200 float random(float dummy) {

float x; int i;

0.0551 200 x = seed + pi;

0.0558 200 x = exp(5.0 * log(x));

0.0003 200 seed = x - int(x);

0.0551 200 return seed;

0.0001 200 }

0.0000 20 void get_data(float *x, float *y, int &n) {

0.0000 20 const a = 5.0;

0.0000 20 const b = 2.0;

int i,j;

0.0000 20 float fudge = 0.5;

0.0000 20 n = 10;

0.0000 20 for (i=1; i<=n; i++) {

0.0001 200 j = n + 1 - i;

0.0001 200 x[i] = j;

0.0003 200 y[i] = (a*j + b) * (1.0 + (2.0 * random(0) - 1.0) * fudge)

}

0.0000 20 }

0.0000 20 void write_data(float *x, float *y, int n) {

int i;

0.0000 20 for (i = 1; i <= n; i++)

0.1125 200 cout << "X[" << i << "]=" << x[i] << "\t\tY[" << i << "]=" <<

0.0000 20 }

0.0000 1 void main() {

float x[max];

float y[max];

int n;

float sumx,sumy;

float sumxy, sumx2;

int k;

float resa,resb;

int cycle;

0.0000 1 for(cycle = 0; cycle < cyc_count; cycle++) {

0.0000 20 clrscr();

0.0000 20 seed = 4.0;

0.0000 20 get_data(x,y,n);

0.0000 20 write_data(x,y,n);

//----------------------------------------- Calculative pa

// Accumulating statistics

0.0000 20 sumx = 0; sumy = 0; sumxy = 0; sumx2 = 0;

0.0000 20 for (k=1; k<=n; k++) {

0.0001 200 sumx += x[k];

0.0002 200 sumy += y[k];

0.0001 200 sumxy += x[k] * y[k];

0.0001 200 sumx2 += x[k] * x[k];

}

// Recieving verdict

0.0000 20 resa = (sumxy - sumx*sumy/n) / (sumx2 - sumx*sumx/n);

0.0000 20 resb = (sumy - resa * sumx) / n;

0.0000 20 cout << "Approximated with y=ax+b where a = " << resa << "

//------------------------------------------- Calculative

}

0.0000 1 }

Execution Profile

Total time: 1.6264 sec

% of total: 99 %

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

  • исключить вызов функции ClrScr(). Возможно, это приведёт к некоторому засорению экрана ненужной информацией, зато позволит выиграть несколько долей секунды при выполнении;

  • исключить вызов функции Write_Data(). Эта функция выполняет, по большому счёту, отладочные действия и не несёт принципиальной нагрузки;

  • убрать передачу параметра в функцию Random(). Назначение этого параметра до сих пор остаётся загадкой;

  • сократить текст, выводимый на экран при получении результатов вычислений. Достаточно выдать на экран просто два числа, разделённые пробелом.

Тем не менее, после выполнения всех этих улучшений время выполнения программы на Паскале сократилось по версии профилировщика с 0.2409 до 0.1572 секунд (в 1,5 раза). Время работы программы на Си ++ сократилось с 1.6264 до 0.1879 (!) секунд (в 8,5 раз).

Соседние файлы в папке Лабораторная работа №23