实验二 omp 并行编程实验报告
16122931 傅宇豪
1 实验环境
硬件环境: 4 核 CPU、8G 内存计算机;
软件环境: Windows10+VS2017
2 实验目的
1) 用 OpenMP 实现最基本的数值算法“矩阵乘法”
2) 掌握 for 编译制导语句
3) 对并行程序进行简单的性能调优
实验内容
1) 运行并测试 OpenMP 编写两个 n 阶的方阵 a 和 b 的相乘程序,结
果存放在方阵 c 中,其中乘法用 for 编译制导语句实现并行化操作,
并调节 for 编译制导中 schedule 的参数,使得执行时间最短。要求在
window 环境(不用虚拟机),在 linux 环境(用和不用虚拟机情况下)
测试程序的性能,并写出详细的分析报告。
2)请自己找一个需要大量计算但是程序不是很长的程序,实现 OMP
的多线程并行计算,要求写出并行算法,并分析并行的效果(注:必
须核对串行和并行的计算结果,保证正确性)
3 实验步骤
(1) 运行并测试 OpenMP 编写两个 n 阶的方阵 a 和 b 的相乘程序,结
果存放在方阵 c 中,其中乘法用 for 编译制导语句实现并行化操
作,并调节 for 编译制导中 schedule 的参数分别设置线程数为 1、
2、4、8、16、32,使得执行时间最短。
(2)分别计算串行计算的执行时间和单线程、双线程和四线程的执行
时间和加速比。
4 实验结果与分析(需要图表分析)
1. Windows 环境程序运行结果
CentOS 运行结果:
2.以 CentOS 环境结果分析矩阵相乘程序的执行时间、加速比和效率:
为 了 更 加 直 观 的 看 到 串 行 和 并 行 的 区 别 , 我 将 执 行 次 数 改 为
100,000,000 次,线程数分别为 1、2、4、8、16、32。
串行执行时程序的执行时间为:
T = 2.860s
(1)串行和 4 个线程的并行程序运行时间对比图
分析:从图表可以看到单线程并行时的执行时间比串行执行时间长,
是因为单线程单线程会有额外创建线程时间,比串行计算速度慢。
分析: 对于多线程来说,可以发现随着线程数的增加,程序的执行时
间减少,大概可以从结果中得出,随着线程数的增加一倍,执行时间
减少一半。
分析:随着线程数的增加,程序的加速比增加,大概可以从结果中得
出,随着线程数的增加一倍,加速相应的增加接近一倍。
2)请自己找一个需要大量计算但是程序不是很长的程序,实现 OMP
的多线程并行计算,要求写出并行算法,并分析并行的效果(注:必
须核对串行和并行的计算结果,保证正确性)
找了一个实现计算 1 到 50 的平方根之和的程序,执行 100000 次。实
现结果如下:
其中 s 表示串行,p1 表示单线程,p2 表示双线程,p4 表示四线程
并行比串行执行时间大大减少。随着线程数的增加,程序的执行时间
减少,大概可以从结果中得出,随着线程数的增加一倍,执行时间减
少一半。
5 实验感想
本次实验让我从零开始认识和学习了 OMP 编程,并且了解到了
并行计算对于减少时间的重要性,虽然此次的计算量不大,差别也只
是秒上的,如果涉及到庞大的计算量,并行计算可以解决很多问题。
此外还发现了单线程运行程序时对于程序的串行其实会有额外的开
销,反而降低了执行的效率。但是并不是线程数越多越好,因为线程
数增加反而会降低效率。
6 附录(代码):
(1)源代码:
#include
#include
#include
#include
void comput(float* A, float* B, float* C)//两个矩阵相乘传统方法
{
}
int x, y;
for (y = 0; y<4; y++)
{
}
for (x = 0; x<4; x++)
{
}
C[4 * y + x] = A[4 * y + 0] * B[4 * 0 + x] + A[4 * y + 1] * B[4 * 1 + x] +
A[4 * y + 2] * B[4 * 2 + x] + A[4 * y + 3] * B[4 * 3 + x];
int main()
{
double
duration, durations,speedrate;
clock_t start, finalt;
int x = 0;
int y = 0;
int n = 0;
int k = 0;
float A[] = { 1, 2, 3, 4,
5, 6, 7, 8,
9, 10, 11, 12,
13, 14, 15, 16 };
float B[] = { 0.1f, 0.2f, 0.3f, 0.4f,
0.5f, 0.6f, 0.7f, 0.8f,
0.9f, 0.10f, 0.11f, 0.12f,
0.13f, 0.14f, 0.15f, 0.16f };
float C[16];
start = clock();
//#pragma omp parallel if(false)
for (n = 0; n<100000000; n++)
{
}
comput(A, B, C);
finalt = clock();
durations = (double)(finalt - start) / CLOCKS_PER_SEC;
//duration 表示持续的时间
printf("100,000,000次串行时间是:%f:%f\n", durations);
//输出矩阵相乘结果
printf("\n串行输出矩阵相乘结果:\n");
for (y = 0; y<4; y++)
{
}
for (x = 0; x<4; x++)
{
}
printf("%f,", C[y * 4 + x]);
printf("\n");
printf("\n======================\n");
//parallel 1 单线程并行
start = clock();
#pragma omp parallel for num_threads(1)
for (n = 0; n<100000000; n++)
{
}
comput(A, B, C);
finalt = clock();
duration = (double)(finalt - start) / CLOCKS_PER_SEC;
speedrate = (durations / duration) * 100;
printf("p1:100,000,000次单线程并行时间是:%f
加速比是:%f\n", duration,
speedrate);
//parallel 2 双线程并行
start = clock();
#pragma omp parallel for num_threads(2)
for (n = 0; n<2; n++)
//CPU是核2线程的
{
}
for (k = 0; k<50000000; k++)
//每个线程管个循环
{
}
comput(A, B, C);
finalt = clock();
duration = (double)(finalt - start) / CLOCKS_PER_SEC;
speedrate = (durations / duration) * 100;
printf("p2:100,000,000次双线程并行时间是:%f
加速比是:%f\n",
duration,speedrate);
//parallel 3
四线程并行
start = clock();
#pragma omp parallel for num_threads(4)
for (n = 0; n<4; n++) //CPU是核4线程的
{
}
for (k = 0; k<25000000; k++)//每个线程管个循环
{
}
comput(A, B, C);
finalt = clock();
duration = (double)(finalt - start) / CLOCKS_PER_SEC;
speedrate = (durations / duration)*100;
printf("p3:100,000,000次四线程并行时间是:%f
加速比是:%f\n", duration,
speedrate);