Professional Documents
Culture Documents
1
Mục lục
2
Lời mở đầu
Mô hình xử lý song song đã và đang phát triển mạnh mẽ, giải quyết những vấn đề bế tắc mà
mô hình xử lý tuần tự gặp phải như: vấn đề thời gian thực hiện chương trình, tốc độ xử lý, khả
năng lưu trữ của bộ nhớ.
Dưới đây là bài báo cáo thực hành OpenMP, bao gồm 4 chương trình:
•1 bài thực hành nhóm(Gồm code, bảng kết quả và nhận xét)
I Thực hành chung
4
Sử dụng 6 luồng để thực hiện tính toán song song ta thu được bảng sau:
5
Sử dụng 8 luồng để thực hiện tính toán song song ta thu được bảng sau:
6
Sử dụng 6 luồng để thực hiện tính toán song song ta thu được bảng sau:
Sử dụng 8 luồng để thực hiện tính toán song song ta thu được bảng sau:
7
1.3 Ma trận nhân ma trận
Sử dụng 4 luồng để thực hiện tính toán song song ta thu được bảng sau:
Sử dụng 6 luồng để thực hiện tính toán song song ta thu được bảng sau:
8
Sử dụng 8 luồng để thực hiện tính toán song song ta thu được bảng sau:
2 Mã nguồn
2.1 Ma trận nhân vector
#include <iostream>
#include <stdio.h>
#include <stdlib.h>
#include <windows.h>
#include <omp.h>
#include <time.h>
double GetTime()
{
LARGE_INTEGER lpFrequency, lpPerfomanceCount;
QueryPerformanceFrequency(&lpFrequency);
QueryPerformanceCounter(&lpPerfomanceCount);
return LiToDouble(lpPerfomanceCount) / LiToDouble(lpFrequency);
}
9
// function for simple definition of matrix and vector elements
void DummyDataInitialization(double* pMatrix, double* pVector, int Size){
int i, j;
for (i = 0; i < Size; i++){
pVector[i] = 1;
for (j = 0; j < Size; j++)
pMatrix[i * Size + j] = i;
}
}
10
void ParallelResultCalculation(double *pMatrix, double *pVector, double *pResult,
int Size)
{
int i, j; // Loop variables
#pragma omp parallel for private(j)
for (i = 0; i < Size; i++)
{
pResult[i] = 0;
for (j = 0; j < Size; j++)
pResult[i] += pMatrix[i * Size + j] * pVector[j];
}
}
11
printf("\nThe results of serial and parallel algorithms are "
"identical.");
delete[] pSerialResult;
}
int main()
{
double *pMatrix; // The first argument - initial matrix
double *pVector; // The second argument - initial vector
double *pResult_Serial; // Result vector for matrix-vector multiplication
double *pResult_Parallel;
int Size, p; // Sizes of initial matrix and vector
double Start, Finish, Duration_Serial, Duration_Parallel;
double Efficiency;
printf("Parallel matrix-vector multiplication program\n");
ProcessInitialization(pMatrix, pVector, Size);
pResult_Serial = new double[Size];
pResult_Parallel = new double[Size];
Start = GetTime();
SerialResultCalculation(pMatrix, pVector, pResult_Serial, Size);
Finish = GetTime();
Duration_Serial = Finish - Start;
p = omp_get_num_threads();
Start = GetTime();
ParallelResultCalculation(pMatrix, pVector, pResult_Parallel, Size);
Finish = GetTime();
Duration_Parallel = Finish - Start;
// printf("\nParallel Result:\n");
// PrintVector(pResult_Parallel, Size);
12
return 0;
}
#include <windows.h>
#include <omp.h>
#include <time.h>
#include <iostream>
#include <bits/stdc++.h>
13
return a;
}
bigint operator+(bigint a, bigint b) {
a.resize(max(a.size(), b.size()));
for (int i = 0; i < b.size(); ++i)
a[i] += b[i];
fix(a);
return a;
}
bigint operator-(bigint a, bigint b)
{
for (int i = 0; i < b.size(); ++i)
a[i] -= b[i];
fix(a);
return a;
}
ostream &operator<<(ostream &cout, const bigint &a)
{
printf("%d", a.back());
for (int i = a.size() - 2; i >= 0; i--)
printf("%d", a[i]);
return cout;
}
double LiToDouble(LARGE_INTEGER x)
{
double result =
((double)x.HighPart) * 4.294967296E9 + (double)((x).LowPart);
return result;
}
double GetTime()
{
LARGE_INTEGER lpFrequency, lpPerfomanceCount;
QueryPerformanceFrequency(&lpFrequency);
QueryPerformanceCounter(&lpPerfomanceCount);
return LiToDouble(lpPerfomanceCount) / LiToDouble(lpFrequency);
}
14
{
bigint *c = new bigint[4];
c[0] = x[0] * y[0] + x[1] * y[2];
c[1] = x[0] * y[1] + x[1] * y[3];
c[2] = x[2] * y[0] + x[3] * y[2];
c[3] = x[2] * y[1] + x[3] * y[3];
15
{
c[2] = x[2] * y[0] + x[3] * y[2];
c[3] = x[2] * y[1] + x[3] * y[3];
}
}
#pragma omp parallel for
for (int i = 0; i < 4; i++)
y[i] = c[i];
// delete c;
}
16
int main()
{
int p;
double Start, Finish, Duration_Serial, Duration_Parallel, Efficiency;
long long int n;
bigint Fibonacci_Serial, Fibonacci_Parallel;
bigint result;
Start = GetTime();
Fibonacci_Serial = SerialFibonacci(n);
Finish = GetTime();
Duration_Serial = Finish - Start;
Start = GetTime();
Fibonacci_Parallel = ParallelFibonacci(n);
Finish = GetTime();
Duration_Parallel = Finish - Start;
#include <iostream>
#include <stdio.h>
#include <stdlib.h>
#include <windows.h>
#include <omp.h>
#include <time.h>
17
double LiToDouble(LARGE_INTEGER x)
{
double result =
((double)x.HighPart) * 4.294967296E9 + (double)((x).LowPart);
return result;
}
double GetTime()
{
LARGE_INTEGER lpFrequency, lpPerfomanceCount;
QueryPerformanceFrequency(&lpFrequency);
QueryPerformanceCounter(&lpPerfomanceCount);
return LiToDouble(lpPerfomanceCount) / LiToDouble(lpFrequency);
}
18
int i, j, k; // Loop variables
}
}
}
}
19
int Size)
{
// Buffer for storing the result of serial matrix-vector multiplication
double *pSerialResult;
int equal = 0; // Flag, that shows wheather the vectors are identical
int i; // Loop variable
pSerialResult = new double[Size*Size];
SerialResultCalculation(pMatrix1, pMatrix2, pSerialResult, Size);
for (i = 0; i < Size*Size; i++)
{
if (pResult[i] != pSerialResult[i])
{
equal = 1;
}
}
if (equal == 1)
printf("\nThe results of serial and parallel algorithms "
"are NOT identical. Check your code.");
else
printf("\nThe results of serial and parallel algorithms are "
"identical.");
delete[] pSerialResult;
}
int main()
{
double *pMatrix1; // The first argument - initial matrix
double *pMatrix2; // The second argument - initial vector
double *pResult_Serial; // Result vector for matrix-vector multiplication
double *pResult_Parallel;
int Size, p; // Sizes of initial matrix and vector
double Start, Finish, Duration_Serial, Duration_Parallel;
double Efficiency;
printf("Parallel matrix-vector multiplication program\n");
ProcessInitialization(pMatrix1, pMatrix2, Size);
Start = GetTime();
SerialResultCalculation(pMatrix1, pMatrix2, pResult_Serial, Size);
Finish = GetTime();
Duration_Serial = Finish - Start;
// printf("\nSerial Result:\n");
20
// PrintMatrix(pResult_Serial, Size);
Start = GetTime();
ParallelResultCalculation(pMatrix1, pMatrix2, pResult_Parallel, Size);
Finish = GetTime();
Duration_Parallel = Finish - Start;
// omp_set_num_threads(4);
#pragma omp parallel num_threads(8)
p = omp_get_num_threads();
Efficiency = Duration_Serial / (Duration_Parallel * p);
printf("num threads: %d", p);
printf("\nTime of execution serial: %f\n", Duration_Serial);
printf("Time of execution parallel: %f\n", Duration_Parallel);
printf("Efficiency of execution: %f%\n", Efficiency * 100);
delete[] pResult_Serial;
delete[] pResult_Parallel;
ProcessTermination(pMatrix1, pMatrix2);
return 0;
}
21
II Thực hành nhóm
Sử dụng 6 luồng để thực hiện tính toán song song ta thu được bảng sau:
22
Sử dụng 8 luồng để thực hiện tính toán song song ta thu được bảng sau:
23
Sử dụng 6 luồng để thực hiện tính toán song song ta thu được bảng sau:
Sử dụng 8 luồng để thực hiện tính toán song song ta thu được bảng sau:
2 Mã nguồn
2.1 Mã nguồn trên hệ điều hành Windows.
#include <stdio.h>
#include <stdlib.h>
#include <conio.h>
#include <windows.h>
#include <omp.h>
24
//----------------------
// Function that converts numbers form LongInt type to double type
double LiToDouble(LARGE_INTEGER x)
{
double result = ((double)x.HighPart) * 4.294967296E9 + (double)((x).LowPart);
return result;
}
25
printf("\nSize of objects must be greater than 0!\n");
}
while (Size <= 0);
26
void TestResult(double* pVector1, double* pVector2, double *pResult, int Size)
{ // Buffer for storing the result of serial matrix-vector multiplication
double* pSerialResult;
if (*pResult != *pSerialResult)
printf("\nThe results of serial and parallel algorithms " "are NOT
identical. Check your code.");
else
printf("\nThe results of serial and parallel algorithms are " "identical.");
delete pSerialResult;
}
int main()
{
double* pVector2;
Start = GetTime();
SerialResultCalculation(pVector1, pVector2, pResult, Size);
Finish = GetTime();
Serial_Duration = Finish-Start;
printf("Serial result: %f \n", *pResult);
27
// TestResult(pVector1, pVector2, pResult, Size);
28
2.2 Mã nguồn trên hệ điều hành Linux.
#include <vector>
#include<omp.h>
#include<time.h>
#include <stdio.h>
#include <linux/types.h>
#include <iostream>
using namespace std;
29
void PrintVector(double* pVector, int Size)
{
int i;
for (i=0; i<Size; i++)
printf("%7.4f ", pVector[i]);
}
if (*pResult != *pSerialResult)
30
printf("\nThe results of serial and parallel algorithms " "are NOT
identical. Check your code.");
else
printf("\nThe results of serial and parallel algorithms are " "identical.");
delete pSerialResult;
}
int main()
{
double* pVector2;
Start = clock();
SerialResultCalculation(pVector1, pVector2, pResult, Size);
Finish = clock();
Serial_Duration = (double)(Finish-Start)/CLOCKS_PER_SEC;
printf("Serial result: %f \n", *pResult);
31
III Nhận xét
Từ bảng số liệu và kết quả chạy các chương trình trên, nhóm có một số nhận xét về thời gian
thực thi và hiệu suất của tính toán song song so với tính toán tuần tự thực hiện chương trình
trên Windows và Linux như sau:
• Tất cả các bảng số liệu trên đều cho thấy với dữ liệu đầu vào nhỏ thì thời gian thực hiện
thuật toán tuần tự thực hiện nhanh hơn so với thuật toán song song.
• Với dữ liệu đầu vào lớn, ta thấy hiệu suất ổn định hơn đối với số luồng cố định và thời
gian chạy thuật toán song song nhanh hơn so với thực hiện tuần tự.
• Nhìn chung, hiệu suất của chương trình tính toán tích vô hướng vector nhân vector không
được cao. Hiệu suất rơi vào khoảng từ 20% đến 30%.
• Qua quá trình thực hành, nhóm thấy hiệu suất và thời gian khi thực thi trên Windows và
Linux chệnh lệch nhau không nhiều. Nhưng Linux không thực thi được với dữ liệu đầu
vào 30000000.
• Đối với chương trình trên, ta thấy thực thi với 4 luồng thì thu được hiệu suất tốt hơn so
với 6 luồng và 8 luồng với dữ liệu đầu vào trên.
32
Phân chia nhiệm vụ
IV
33