You are on page 1of 10

Київський національний університет імені Тараса Шевченка

Факультет комп'ютерних наук та кібернетики

ЛАБОРАТОРНА РОБОТА №1
з теми
"Визначення швидкодії обчислювальної системи"

Виконав
студент 1-ого курсу
групи К-16
спеціальності "Інформатика"
Савчук Олександр Юрійович
Київ – 2023
Постановка задачі
Лабораторна робота передбачає розробку спрощеної системи тестів, без
побудови генеральної виборки, опитування експертів, проведення
статистичних вимірювань.
Необхідно розробити програму, яка вимірює кількість виконуваних базових
операцій (команд) за секунду конкретною ОбСист (комп’ютер + ОС +
Система програмування). Вимірювання "чистої" команди процесора не
потрібне (як і є у реальних програмних комплексах, що типово
розробляються на мовах високого рівня, часто навіть на платформенно
незалежних) і фактично не має сенсу.
До базового набору операцій достатньо включити операції додавання,
віднімання, множення та ділення для кожного з базових типів
даних (символьний, варіанти цілого, дійсний тощо, як це є в тій чи тій мові
чи системі програмування). Інші операції, команди та типи – за бажанням.
Наприклад, для С/С++ потрібно взяти типи char, int, long, float та double.
Враховуючи, що для всіх типів процесорів характерне апаратне
об’єднання команди додавання та віднімання у одну команду за рахунок
відповідної зміни знаку одного з операндів (але для зручності кодування на
рівні командного набору ці операції фігурують як окремі команди), не можна
проводити вимірювання лише для однієї з цих двох команд.
Точність вимірювання - 2%. Достатньо на рівні вимірювань для
лабораторної вважати, що для коротких операцій (додавання/віднімання для
цілих слів) кількість операцій приблизно відповідає тактовій частоті
процесора комп’ютера. Від цієї величини беремо 2%, і це значення
буде ±похибка між однойменними результатами для серії запусків програми.
Наприклад, при тактовій частоті у 2 ГГц, 2% дорівнюватиме 40 МГц, або це
приблизно 40 млн. коротких оп./с; отже, похибка між однойменними
результатами ±40 млн. оп./с. Тобто найшвидший результат (наприклад, для
операції додавання) беремо за 100%, а подібна операція (тоді нехай
віднімання) може відстати від додавання на 40 млн. операцій.
Програма має демонструвати стабільність вимірювань для серії запусків.
Потрібно враховувати, що при роботі на платформі MS Windows під час
вимірювання за тестом може початися процес  свопінгу системи, тому в
такому випадку сусідні вимірювання у серії можуть відрізнятися на порядок.
Такі запуски потрібно виключати з розгляду.
Результати мають бути представлені у табличній формі з відображенням для
кожного тесту:
1. назви команди/операції,
2. типу/формату даних,
3. кількості операцій за секунду (зайві знаки у мантисі для заданої
точності не відображати),
4. лінійної діаграми значення швидкості у відсотках відносно
найшвидшої команди/операції, яка береться за 100%,
5. значення у відсотках (можна округляти до цілого).
Результати виконання

Як бачимо, найшвидше виконується операція множення, а не очікуване


додавання; це може бути пов'язано із застосуванням оптимізаційних
алгоритмів при множенні.
Додаток із кодом програми
#include <iostream>
#include <time.h>
#include <Windows.h>
#include <string>
#include <sstream>
#include <iomanip>

using namespace std;

auto op_amount_ = 10000000;


auto op_amount_add = 1000000000;
auto op_amount_sub = 1000000000;
auto op_amount_mul = 100000000;
auto op_amount_div = 100000000;
string signs[20];
string types[20];
string freqs[20];
string diagramLines[20];
string freqPercents[20];
int counter = 0;

// Time elapsed by 2,000,000,000 cycle conditions' checks


double empty()
{
double time = clock();
for (auto i = 0; i < op_amount_; i++)
{

}
time = ((clock() - time) / CLOCKS_PER_SEC) / op_amount_;
return time;
}

// Time elapsed by 2,000,000,000 assignments and 'for' cycle conditions checks


double assignment(double empty)
{
int a1, a2 = 3;
double time = clock();
for (auto i = 0; i < op_amount_; i++)
{
a1 = a2;
a1 = a2;
a1 = a2;
a1 = a2;
a1 = a2;
a1 = a2;
a1 = a2;
a1 = a2;
a1 = a2;
a1 = a2;
a1 = a2;
a1 = a2;
a1 = a2;
a1 = a2;
a1 = a2;
a1 = a2;
a1 = a2;
a1 = a2;
a1 = a2;
a1 = a2;
}
time = ((clock() - time) / CLOCKS_PER_SEC - empty) / 20;
return time;
}

// Time elapsed by 20,000,000,000 additions of chosen type


template <typename T>
double addition(T a1, T a2, T a3, T a4, T a5, T a6, T a7, T a8, T a9, T a10)
{
T x;
double time = clock();
for (auto i = 0; i < op_amount_add; i++)
{
x = a1 + a5;
x = a7 + a3;
x = a4 + a2;
x = a5 + a10;
x = a2 + a6;
x = a8 + a1;
x = a9 + a2;
x = a1 + a3;
x = a10 + a7;
x = a2 + a5;
x = a8 + a4;
x = a9 + a1;
x = a5 + a7;
x = a3 + a2;
x = a1 + a4;
x = a1 + a2;
x = a7 + a5;
x = a5 + a6;
x = a6 + a4;
x = a8 + a2;
x = a6 + a3;
x = a1 + a5;
x = a1 + a3;
x = a5 + a1;
x = a10 + a9;
x = a1 + a8;
x = a5 + a6;
x = a3 + a2;
x = a1 + a4;
x = a7 + a10;
}
time = (clock() - time) / CLOCKS_PER_SEC;
return time;
}

// Time elapsed by 20,000,000,000 subtractions of chosen type


template <typename T>
double subtraction(T a1, T a2, T a3, T a4, T a5, T a6, T a7, T a8, T a9, T a10)
{
T x;
double time = clock();
for (auto i = 0; i < op_amount_sub; i++)
{
x = a1 - a5;
x = a7 - a3;
x = a4 - a2;
x = a5 - a10;
x = a2 - a6;
x = a8 - a3;
x = a9 - a2;
x = a1 - a3;
x = a10 - a7;
x = a2 - a5;
x = a8 - a4;
x = a9 - a1;
x = a5 - a7;
x = a3 - a2;
x = a1 - a4;
x = a1 - a2;
x = a7 - a5;
x = a5 - a6;
x = a6 - a8;
x = a8 - a2;
x = a6 - a3;
x = a1 - a5;
x = a1 - a3;
x = a5 - a1;
x = a10 - a9;
x = a1 - a8;
x = a5 - a6;
x = a3 - a2;
x = a1 - a4;
x = a7 - a4;
}
time = (clock() - time) / CLOCKS_PER_SEC;
return time;
}

// Time elapsed by 20,000,000,000 multiplications of chosen type


template <typename T>
double multiplication(T a1, T a2, T a3, T a4, T a5, T a6, T a7, T a8, T a9, T a10)
{

T x;
double time = clock();
for (auto i = 0; i < op_amount_mul; i++)
{
x = a1 * a5;
x = a7 * a3;
x = a4 * a2;
x = a5 * a10;
x = a2 * a6;
x = a8 * a7;
x = a9 * a2;
x = a1 * a3;
x = a10 * a7;
x = a2 * a5;
x = a8 * a4;
x = a9 * a1;
x = a5 * a7;
x = a3 * a2;
x = a1 * a4;
x = a1 * a2;
x = a7 * a5;
x = a5 * a6;
x = a6 * a3;
x = a8 * a2;
x = a6 * a3;
x = a1 * a5;
x = a1 * a3;
x = a5 * a1;
x = a10 * a9;
x = a1 * a8;
x = a5 * a6;
x = a3 * a2;
x = a1 * a4;
x = a7 * a9;
}
time = (clock() - time) / CLOCKS_PER_SEC;
return time;
}

// Time elapsed by 20,000,000,000 divisions of chosen type


template <typename T>
double division(T a1, T a2, T a3, T a4, T a5, T a6, T a7, T a8, T a9, T a10)
{
T x;
double time = clock();
for (auto i = 0; i < op_amount_div; i++)
{
x = a1 / a5;
x = a7 / a3;
x = a4 / a2;
x = a5 / a10;
x = a2 / a6;
x = a8 / a7;
x = a9 / a2;
x = a1 / a3;
x = a10 / a7;
x = a2 / a5;
x = a8 / a4;
x = a9 / a1;
x = a5 / a7;
x = a3 / a2;
x = a1 / a4;
x = a1 / a2;
x = a7 / a5;
x = a5 / a6;
x = a6 / a1;
x = a8 / a2;
x = a6 / a3;
x = a1 / a5;
x = a1 / a3;
x = a5 / a1;
x = a10 / a9;
x = a1 / a8;
x = a5 / a6;
x = a3 / a2;
x = a1 / a4;
x = a7 / a10;
}
time = (clock() - time) / CLOCKS_PER_SEC;
return time;
}

template <typename ParamType>


void testOperation(string type, string sign, ParamType a1, ParamType a2, double
emptyTime, double assignmentTime)
{
ParamType c3, c4, c5, c6, c7, c8, c9, c10;
if (type._Equal("char"))
{
c3 = 'C', c4 = 'F', c5 = '8', c6 = '*', c7 = '/', c8 = 'U', c9 = 'a', c10 =
' ';
}
if (type._Equal("int"))
{
c3 = 11948143, c4 = 34242442, c5 = 48939843, c6 = 55453099, c7 = 52942999,
c8 = 42299299, c9 = 294289999, c10 = 428929977;
}
if (type._Equal("long"))
{
c3 = 423894129L, c4 = 4331313L, c5 = 2931317L, c6 = 24131313L, c7 =
181442149L, c8 = 4424191L, c9 = 442424421L, c10 = 424234533L;
}
if (type._Equal("float"))
{
c3 = 4842145.0F, c4 = 44242214.5F, c5 = 49424241.1F, c6 = 1222424.5F, c7 =
1412494.247F, c8 = 199113.25F, c9 = 375128519.0F, c10 = 1344149499.12F;
}
if (type._Equal("double"))
{
c3 = 41491813.319, c4 = 41041894894.2345, c5 = 32141413.452, c6 =
41414190.4, c7 = 11414143.5, c8 = 141415.447, c9 = 141894195.1, c10 = 42314141.7;
}
double dif;
if (sign._Equal("+"))
{
dif = op_amount_add * emptyTime + 30 * assignmentTime;
freqs[counter] = to_string(30 * (op_amount_add / (addition(a1, a2, c3, c4,
c5, c6, c7, c8, c9, c10) - dif)));
}
if (sign._Equal("-"))
{
dif = op_amount_sub * emptyTime + 30 * assignmentTime;
freqs[counter] = to_string(30 * (op_amount_sub / (subtraction(a1, a2, c3,
c4, c5, c6, c7, c8, c9, c10) - dif)));
}
if (sign._Equal("*"))
{
dif = op_amount_mul * emptyTime + 30 * assignmentTime;
freqs[counter] = to_string(30 * (op_amount_mul / (multiplication(a1, a2,
c3, c4, c5, c6, c7, c8, c9, c10) - dif)));
}
if (sign._Equal("/"))
{
dif = op_amount_div * emptyTime + 30 * assignmentTime;
freqs[counter] = to_string(30 * (op_amount_div / (division(a1, a2, c3, c4,
c5, c6, c7, c8, c9, c10) - dif)));
}

signs[counter] = sign;
types[counter] = type;
cout << signs[counter] <<
" " << types[counter] << " " << setprecision(4) << scientific <<
stod(freqs[counter]) << endl;
counter++;
}

int findMaxLen(string where[])


{
int maxLen = where[0].length();
for (int i = 1; i < 20; i++)
if (where[i].length() > maxLen)
maxLen = where[i].length();
return maxLen;
}

double findMaxFreq()
{
double max = stod(freqs[0]);
for (int i = 1; i < 20; i++)
if (stod(freqs[i]) > max)
max = stod(freqs[i]);
return max;
}
void fillPercents()
{
double maxFreq = findMaxFreq();
for (int i = 0; i < 20; i++)
freqPercents[i] = to_string((int) round((stod(freqs[i]) / maxFreq) * 100));
}

void format(string what[])


{
int maxLen = findMaxLen(what);
for (int i = 0; i < 20; i++)
if (what[i].length() < maxLen)
for (int j = 0; j < maxLen - what[i].length(); j++)
what[i] += " ";
}

void makeDiagramLines()
{
for (int i = 0; i < 20; i++) {
int amount = stoi(freqPercents[i]);
for (int j = 0; j < amount; j++)
diagramLines[i] += "X";
}
}

// Test all the operations for chosen type


template <typename Type>
void testAll(string type, Type a1, Type a2, double emptyTime, double assignmentTime)
{
testOperation(type, "+", a1, a2, emptyTime, assignmentTime);
testOperation(type, "-", a1, a2, emptyTime, assignmentTime);
testOperation(type, "*", a1, a2, emptyTime, assignmentTime);
testOperation(type, "/", a1, a2, emptyTime, assignmentTime);
}

int main()
{
SetConsoleDisplayMode(GetStdHandle(STD_OUTPUT_HANDLE), CONSOLE_FULLSCREEN_MODE,
0);
double emptyTime = empty();
double assignmentTime = assignment(emptyTime);
// double dif = emptyTime + 30 * assignmentTime;
testAll("long", 123L, 111L, emptyTime, assignmentTime);
testAll("float", 123.0F, 111.0F, emptyTime, assignmentTime);
testAll("double", 123.0, 111.0, emptyTime, assignmentTime);
testAll("char", '{', 'o', emptyTime, assignmentTime);
testAll("int", 123, 111, emptyTime, assignmentTime);

fillPercents();
makeDiagramLines();
format(types);
format(freqs);
format(diagramLines);
for (int i = 0; i < 20; i++)
cout << signs[i] << "\t" << types[i] << "\t" << setprecision(4) <<
scientific << stod(freqs[i]) << "\t" << freqPercents[i] << "%" << "\t" << diagramLines[i]
<< endl;
return 0;
}

You might also like