OpenMP程序的编译和运行.docx
《OpenMP程序的编译和运行.docx》由会员分享,可在线阅读,更多相关《OpenMP程序的编译和运行.docx(25页珍藏版)》请在冰点文库上搜索。
OpenMP程序的编译和运行
SHANGHAIUNIVERSITY
学院
计算机工程与科学学院
实
姓
学
教
时
验
名
号
师
间
OpenMP 程序的编译和运行
陈帅
12122208
刘芳芳
2015.05.06
报告成绩
实验 2-1.OpenMP 程序的编译和运行
1. 实验目的
1) 在 Linux 平台上编译和运行 OpenMP 程序;
2) 在 Windows 平台上编译和运行 OpenMP 程序。
3) 掌握 OpenMP 并行编程基础。
2. 实验环境
1) 硬件环境:
计算机一台;
2) 软件环境:
Linux、Win2003、GCC、MPICH、VS2008 或其他版本 Visual Studio;
3. 实验内容
1. Linux 下 OpenMP 程序的编译和运行。
OpenMP 是一个共享存储并行系统上的应用编程接
口,支持 C/C++和 FORTRAN 等语言,编译和运行简单的"Hello World"程序。
在 Linux 下编辑
hellomp.c 源程序,或在 Windows 下编辑并通过附件中的 FTP 工具(端口号:
1021)上传,
用"gcc -fopenmp -O2 -o hellomp.out hellomp.c"命令编译,用"./hellomp.out"命令运行程序。
注:
在虚拟机中当使用 vi 编辑文件时,不是以 ESC 键退出插入模式,可以使用“Ctrl+c”进
入命令模式,然后输入 wq 进行存盘退出。
代码如下:
#include
#include
int main()
{
int nthreads,tid;
omp_set_num_threads(8);
#pragma omp parallel private(nthreads,tid)
{
tid=omp_get_thread_num();
printf("Hello World from OMP thread %d\n",tid);
if(tid==0)
{
nthreads=omp_get_num_threads();
printf("Number of threads is %d\n",nthreads);
}
}
}
安装 gcc
检查 GCC 是否安装完成
编写 hellomp.c
编译运行
2. 控制并行执行的线程数。
根据算法的要求和硬件情况,例如 CPU 数量或者核数,选择适合的线程数可以加速程序的
运行。
请按照下列的方法进行线程数量的设置。
//设置线程数为 10
[xuyc@sv168 openmp]$ OMP_NUM_THREADS=10
//将线程数添加为环境变量
[xuyc@sv168 openmp]$ export OMP_NUM_THREADS
//运行
修改 hellomp.c 程序,删除 omp_set_num_threads(8);语句
如果不定义 OMP_NUM_THREADS,默认会等于 CPU 数量,在 8 核心的机器上,会打印
出 8 行"Hello World".
omp_set_num_threads(8); 设置了子线程数为8,即是可以有 8 个子线程并行运行。
#pragma omp parallel private(nthreads,tid) 为编译制导语句,每个线程都自己的 nthreads
和 tid 两个私有变量,线程对私有变量的修改不影响其它线程中的该变量。
程序的功能是对于每个线程都打印出它的 id 号,对于 id 号为 0 的线程打印出线
程数目。
2. Windows 下 OpenMP 程序的编译和运行。
用 VS2013 编辑上述的 hellomp.c 源程序,
注意在菜单“项目->属性->C/C++->语言”选中“OpenMP 支持”,编译并运行程序。
打 开 或 者 新 建 一 个 c++ 项 目 , 依 次 选 择 Project -> 属 性 -> 配 置 属 性
(configuration property) -> c/c++ -> 语言(Language),打开 OpenMP 支持;
设置环境变量 OMP_NUM_THREADS。
设置环境变量:
我的电脑 -> 属性 -> 高级 -> 环境变量,新建一个
OMP_NUM_THREADS 变量,值设为 2,即为程序执行的线程
数。
图 3 VS2013 使用界面
使用 VS2013 进行并行程序设计,图 3 为 VS2013 使用界面,图 4 为运行结果截图。
图 4 程序运行结果截图
虽然线程都是一起开始运行,但实验中每次运行的结果都不一样,这个是因为每次每个
线程结束的先后可能不一样的。
所以每次运行的结果都是随机的。
这是串行程序和并行程序
不同的地方:
串行程序可以重新运行,结果和之前一样;并行程序却因为执行次序无法控制
可能导致每次的结果都不一样。
实验 2-2 矩阵乘法的 OpenMP 实现及性能分析
1. 实验目的
1) 用 OpenMP 实现最基本的数值算法“矩阵乘法”
2) 掌握 for 编译制导语句
3) 对并行程序进行简单的性能调优
2. 实验内容
1) 运行并测试 OpenMP 编写两个 n 阶的方阵 a 和 b 的相乘程序,结果存放在方阵 c 中,其
中乘法用 for 编译制导语句实现并行化操作,并调节 for 编译制导中 schedule 的参数,使得
执行时间最短。
要求在 window 环境(不用虚拟机),在 linux 环境(用和不用虚拟机情况下)
测试程序的性能,并写出详细的分析报告。
源代码如下:
#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*y+x] = A[4*y+0]*B[4*0+x] + A[4*y+1]*B[4*1+x] +
[4A y+2]*B[4*2+x] + A[4*y+3]*B[4*3+x]
}
}
}
int main()
{
doubleduration
clock_t s f
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]
= clock()
//#pragma omp parallel if(false)
for(n=0 n<1000000 n++)
{
computA,B,C)
}
=clock()
duration= (double)(fs)/CLOCKS_PER_SEC
printf "s---1,000,000 :
%f\n",duration)
for(y=0 y<4 y++)
{
for(x=0 x<4 x++)
{
printf"%f,",C[y*4+x])
}
printf"\n")
}
printf "\n======================\n")
s = clock()
//parallel 2
#pragma omp parallel for
for(n=0 n<2 n++)////CPU 是核线程的
{
for(k=0 k<1000000 k++)//每个线程管个循环
{
comput,B,C)
}
}
f = clock()
duration = (double)(fs)/CLOCKS_PER_SEC
printf "p2- 1,000,000:
%f\n",duration)
//parallel 3
s = clock()
#pragma omp parallel for
for(n=0 n<4 n++)//CPU 是核线程的
{
for(k=0 k<1000000 k++)//每个线程管个循环
{
comput B,C)
}
}
f = clock()
duration = (double)(fs)/CLOCKS_PER_SEC
printf "p3- 1,000,000:
%f\n",duration)
//parallel 1
s = clock()
#pragma omp parallel for
for(n=0 n<1000000 n++)
{
computA,B,C)
}
f = clock()
duration = (double)(fs)/CLOCKS_PER_SEC
printf "p1-1,000,000 :
%f\n",duration)
for(y=0 y<4 y++)
{
for(x=0 x<4 x++)
{
printf"%f,",C[y*4+x])
}
printf"\n")
}
return 0
}
程序运行结果:
分析报告:
由运行结果可以看出串行运算 1000000 次 s-1 的时间是 0.030000,
并行运算 1000000 次 p-1 的时间是 0.040000,并行的时间比串行还要久一点,原因在于
对计算机来说计算 1000000 万次的此矩阵计算是非常 easy 的事情,计算量很小,在这
种情况下 OMP 多线程计算时,线程的创建和销毁的开销会变成主要的消耗时间。
p-2 是 2 线程运算,p-3 是 4 线程运算,所以在同样运算 1000000 次的情况下,p-2 的时
间要比 p-3 的时间多出来 0.010000 秒。
2)请自己找一个需要大量计算但是程序不是很长的程序,实现 OMP 的多线程并行计算,要
求写出并行算法,并分析并行的效果(注:
必须核对串行和并行的计算结果,保证正确性)
#include
#include
#include
using namespace std
void qh (int i)
{
float sum = 0
int j
for (int j = 1j <= ij++)
sum += sqrt(j)
}
void qh1(int i)//计算 1 到 i 平方根的和
{
float sum = 0
int j
for (int j = 1j <= ij++)
sum+= sqrt(j)
cout<< "sum=" << sum<}
int main()
{
int i = 10
clock_t , f
s= clock()
doubleduration
int x = 0
int y = 0
int n = 0
int k = 0
//#pragma omp parallel if(false)
for (n = 0n<1000000n++)
{
qh)
}
qh1i)
f= clock()
duration= (double)(fs) / CLOCKS_PER_SEC
printf"s---1,000,000 :
%f\n", duration)
printf"\n======================\n" )
s= clock()
//parallel 2
#pragma omp parallel for
for (n = 0n<2n++)////CPU 是核线程的
{
for (k = 0k<500000k++)//每个线程管个循环
{
(qh
}
}
qh1i)
f= clock()
duration= (double)(fs) / CLOCKS_PER_SEC
printf"p2-500,000:
%f\n", duration)
//parallel 3
s= clock()
#pragma omp parallel for
for (n = 0n<4n++)//CPU 是核线程的
{
for (k = 0k<250000k++)//每个线程管个循环
{
(qh
}
}
qh1i)
f= clock()
duration= (double)(fs) / CLOCKS_PER_SEC
printf"p3- 250,000:
%f\n", duration);
//parallel 4
s = clock();
#pragma omp parallel for
for (n = 0; n<4; n++)//CPU 是核线程的
{
for (k = 0; k<500000; k++)//每个线程管个循环
{
qh(i);
}
}
qh1(i);
f = clock();
duration = (double)(f - s) / CLOCKS_PER_SEC;
printf("p4-500,000:
%f\n", duration);
//parallel 1
s= clock();
#pragma omp parallel for
for (n = 0; n<1000000; n++)
{
qh);
}
qh1i);
f= clock();
duration= (double)(f - s) / CLOCKS_PER_SEC;
printf"p1-1,000,000 :
%f\n", duration);
system"pause");
return 0;
}
运行结果:
结果分析:
程序计算的是 1 到 10 的平方根的和,由运行结果可以看出,串行运算 s-1 的时间比并
行运算 p-1 的时间要稍短一些,这是因为并行运算有创建和销毁线程的时间,当计算量比较
少时,这部分的时间就变为主要的消耗时间。
p-2 是以 2 线程运算 500000 次,p-4 是以 4 线程运算 500000 次,由 p-4 比 p-2 多出的
0.438000 时间可以看出多创建 2 个线程是非常消耗时间的(运算量较少时)。
P-3 是以 4 线
程运算 250000 次,耗时同 p-2 相同,说明在计算量小的情况下使用 OMP 多核线程是非常划
不来的。