МІНІСТЕРСТВО ОСВІТИ І НАУКИ УКРАЇНИ
НАЦІОНАЛЬНИЙ УНІВЕРСИТЕТ “ЛЬВІВСЬКА ПОЛІТЕХНІКА”
ЗВІТ
З лабораторної роботи №3
з дисципліни “Алгоритми та методі обчислень”
на тему: “Використання потокового графу алгоритму для паралельних обчислень.”
Варіант 8
2.Варіант завдання:
Номер варіанту – 8
Вхідні дані: c = -265; b = 266; a = 261
3.Результат виконання програми:
Рис.1. Результат виконання програми
4.Висновок:
На даній лабораторній роботі я дізнався про паралельне програмування, та використовував алгоритм потокового графу для вирішення квадратного рівняння двома методами паралельно.
5.Код програми:
// don't forget to use compilation key for Linux: -lm
//-fno-tree-vectorize
//gcc -O3 -no-tree-vectorize
//gcc -O3 -ftree-vectorizer-verbose=6 -msse4.1 -ffast-math
//__attribute__((optimize("no-tree-vectorize")))
//extern "C" __attribute__ ((optimize("no-tree-vectorize")))
#include <stdio.h>
#include <stdlib.h>
#include <x86intrin.h> // Linux
//#include <intrin.h> // Windows
#include <math.h>
#include <time.h>
#define A 261.
#define B 266.
#define C -265.
#pragma GCC push_options
#pragma GCC optimize ("no-unroll-loops")
#define REPEAT_COUNT 1000000
#define REPEATOR(count, code) \
for (unsigned int indexIteration = (count); indexIteration--;){ code; }
#define TWO_VALUES_SELECTOR(variable, firstValue, secondValue) \
(variable) = indexIteration % 2 ? (firstValue) : (secondValue);
double getCurrentTime(){
clock_t time = clock();
if (time != (clock_t)-1) {
return ((double)time / (double)CLOCKS_PER_SEC);
}
return 0.; // else
}
#pragma GCC push_options
#pragma GCC target ("no-sse2")
//__attribute__((__target__("no-sse2")))
void run_native(double * const dArr){
double * const dAC = dArr;
double * const dA = &dAC[0];
double * const dC = &dAC[1];
double * const dB = &dArr[2];
double * const dResult = &dArr[4];
double * const dX1 = &dResult[1];
double * const dX2 = &dResult[0];
REPEATOR(REPEAT_COUNT,
TWO_VALUES_SELECTOR(*dA, 4., A);
TWO_VALUES_SELECTOR(*dB, 3., B);
TWO_VALUES_SELECTOR(*dC, 1., C);
double vD = sqrt((*dB)*(*dB) - 4.*(*dA)*(*dC));
(*dX1) = (-(*dB) + vD) / (2.*(*dA));
(*dX2) = (-(*dB) - vD) / (2.*(*dA));
)
}
#pragma GCC pop_options
void run_SSE2(double * const dArr){
double * const dAC = dArr;
double * const dA = &dAC[0];
double * const dC = &dAC[1];
double * const dB = &dArr[2];
double * const dResult = &dArr[4];
double * const dX1 = &dResult[1];
double * const dX2 = &dResult[0];
__m128d r__zero_zero, r__c_a, r__uORb_b, r__2cORbOR2a_2a,
r__zero_bb, r__sqrtDiscriminant_zero, r_result;
r__zero_zero = _mm_set_pd(0., 0.); // init
REPEATOR(REPEAT_COUNT,
TWO_VALUES_SELECTOR(*dA, 4., A);
TWO_VALUES_SELECTOR(*dB, 3., B);
TWO_VALUES_SELECTOR(*dC, 1., C);
r__c_a = _mm_load_pd(dAC);
// r__uORb_b = _mm_load_pd1(dB);
r__uORb_b = _mm_load1_pd(dB);
// b b
r__uORb_b = _mm_unpacklo_pd(r__uORb_b, r__uORb_b);
// (etap 1)
r__2cORbOR2a_2a = _mm_add_pd(r__c_a, r__c_a);
// b 2c
r_result = _mm_unpackhi_pd(r__2cORbOR2a_2a, r__uORb_b);
// b 2a
r__2cORbOR2a_2a = _mm_unpacklo_pd(r__2cORbOR2a_2a, r__uORb_b);
// bb 4ac (etap 2)
r_result = _mm_mul_pd(r_result, r__2cORbOR2a_2a);
r__zero_bb = _mm_unpackhi_pd(r_result, r__zero_zero);
// zero Discriminant (etap 3)
r_result = _mm_sub_sd(r__zero_bb, r_result);
// zero sqrtDiscriminant (etap 4)
r_result = _mm_sqrt_sd(r_result, r_result);
...