OpenMP的学习

这些天接触到了一个新的概念,并行计算,概念新了点,不过思想日常生活中比比皆是,通俗的说也就是大家一起同时做某个事情,说学习就学习,昨天我就登了一下OpenMP的官方网站,找到一篇“A Hands-On Introduction to OpenMP ” 大家可以直接下载,这个对于入门还是一个很好的选择,然后看了下编辑器Compilers,很好的是在VS2008上直接可以使用,于是乎,开始测试一下OpenMP的神奇,于是乎根据上面的介绍写了一个Hello World的程序

#include <stdio.h>
#include <omp.h>
int main() {	
#pragma omp parallel
	{
		int ID = omp_get_thread_num();
		printf("hello(%d) ", ID);
		printf("world(%d) \n", ID);
	}	
}
没反应,既然还就是只出现了

hello(0) world(0)
请按任意键继续. . .

想想我的电脑也是双核的,跟展示的四核的不一样,也不至于是一个吧,估计那个地方不对,查了下原来在语言中要选择OpenMP支持

image

好的不错 出现了

hello(0) hello(1) worl
world(1)
请按任意键继续. . .

这个结果,看来程序是可以并行了,下面就来了,这是一个简简单单的一个HelloWorld,复杂的怎么搞了,最起码要把基本的函数库要看一下吧

看看能不能找到,到网上查了查,官方提供一个,3百多页,纯英文,英语太差,看看有没有翻译好的,找了找,发现周伟明老师的博客中很有多关于这方面的介绍,慢慢看了下。大致了解了下,再接再厉,也要搞点东西。

 

那就试一试,看看并行计算到底快多少,于是先做一个并行求和。在这之前先写了串行的试试

#include <stdio.h>
#include<time.h>
#define  N 100000000
void main()
{
	int sum=0;
	clock_t t1 = clock();
	for(int i=0;i<N;i++)
	{
		sum +=i;
	}
	clock_t t2 = clock();
	printf("time=%d",t2-t1);
}

time=453请按任意键继续. . .

在对于加法,乘法运算可结合,可交换。对于并行计算,我们一开始也是要找到独立计算,然后再将这些独立计算重新组织成并行代码,一般就是两种组织方式,就是任务分解,一种就是数据分解,我想这个也很直观,而对于这个求和的话,分解任务的话,感觉不可能,想想看sum的值依赖于之前sum上执行的加法运算,这也就是任务之间存在在依赖,存在依赖的话就会可能存在数据竞争,这个也就是我们要避免的。

然后想一想数据分解,程序如下

#include<stdio.h>
#include<omp.h>
#define N 100000000
void main()
{
	int * x;//开辟数组空间
	x=new int[N];//这边分配的空间
	int sum=0;
	double start,end;
	//初始化数组
	int i=0;
	for (i=0;i<N;i++)
	{
		x[i]=i;
	}
	start = omp_get_wtime();
#pragma omp parallel for reduction(+:sum)	
	for (int i=0;i<N;i++)
	{
		sum=sum+x[i];
	}
	
	end = omp_get_wtime();
	 printf("time: %f \n", end - start);

}
结果显示:

time: 0.352276
请按任意键继续. . .

时间是快了一点。。。

这边用了reduction,reduction子句将确保每个线程得到的sum保存为一个副本,再一次的叠加,我以N=10为例

#include<stdio.h>
#include<omp.h>
#define N 10
void main()
{
	int * x;//开辟数组空间
	x=new int[N];//这边分配的空间
	int sum=0;
	double start,end;
	//初始化数组
	int i=0;
	for (i=0;i<N;i++)
	{
	    x[i]=i;
	}
	start = omp_get_wtime();
#pragma omp parallel for reduction(+:sum)	
	for (int i=0;i<N;i++)
	{
		printf("Num:%d %d+%d=%d\n",omp_get_thread_num(),sum,x[i],sum+x[i]);
		sum=sum+x[i];		
	}
	printf("sum=%d\n",sum);
	end = omp_get_wtime();
	printf("time: %f \n", end - start);

}

显示结果

Num:0 0+0=0
Num:1 0+5=5
Num:0 0+1=1
Num:1 5+6=11
Num:0 1+2=3
Num:1 11+7=18
Num:0 3+3=6
Num:1 18+8=26
Num:0 6+4=10
Num:1 26+9=35
sum=45
time: 0.001591
请按任意键继续. . .

最终等所有的线程执行完之后,reduction子句会将算到的部分加起来10+35=45(这个就是通过(+:sum)中的加号运算符)

我们来测试一下去掉reduction之句会有什么效果代码如下:

#include<stdio.h>
#include<omp.h>
#define N 10
void main()
{
	int * x;//开辟数组空间
	x=new int[N];//这边分配的空间
	int sum=0;
	double start,end;
	//初始化数组
	int i=0;
	for (i=0;i<N;i++)
	{
		x[i]=i;
	}
	start = omp_get_wtime();
#pragma omp parallel for //reduction(+:sum)	
	for (int i=0;i<N;i++)
	{
		printf("Num:%d %d+%d=%d\n",omp_get_thread_num(),sum,x[i],sum+x[i]);
		sum=sum+x[i];
	}
	printf("sum=%d\n",sum);
	end = omp_get_wtime();
	printf("time: %f \n", end - start);

}
显示结果如下:

Num:0 0+0=0
Num:1 0+5=5
Num:0 0+1=1
Num:1 5+6=11
Num:0 6+2=8
Num:1 12+7=19
Num:0 14+3=17
Num:1 21+8=29
Num:0 24+4=28
Num:1 32+9=41
sum=45
time: 0.001677
请按任意键继续. . .

 

再执行一遍显示结果如下:

Num:0 0+0=0
Num:1 0+5=5
Num:1 5+6=11
Num:1 11+7=18
Num:1 18+8=26
Num:1 26+9=35
Num:0 35+1=36
Num:0 36+2=38
Num:0 38+3=41
Num:0 41+4=45
sum=45
time: 0.001965
请按任意键继续. . .

虽然结果都是正确,但是极有可能出现错误,两个执行结果不是相同的方式,具体参考了

http://www.cnblogs.com/me115/archive/2011/01/27/1946129.html

 

OK,先了解了个大概,下面慢慢学习。。。

posted @ 2011-11-19 15:32  越影&逐日而行  阅读(367)  评论(0编辑  收藏  举报