OpenMP(Open Muti-Processing)

OpenMP缺点:

1:作为高层抽象,OpenMp并不适合需要复杂的线程间同步和互斥的场合;

2:另一个缺点是不能在非共享内存系统(如计算机集群)上使用。在这样的系统上,MPI使用较多。

关于openMP实现 临界区 与互斥锁 可参考 reference3

windows系统下使用

==========================WINDOWS系统中使用==========================

基本使用:

在visual C++2010中使用OpenMP

1:将 Project 的Properties中C/C++里Language的OpenMP Support开启(参数为 /openmp);

2:在编写使用OpenMP 的程序时,则需要先include OpenMP的头文件:omp.h;

3:在要并行化的for循环前面加上  #pragma omp parallel for

如下简单例子:

  1. //未使用OpenMP
  2. #include <stdio.h>
  3. #include <stdlib.h>
  4. void Test(int n) {
  5. for(int i = 0; i < 10000; ++i)
  6. {
  7. //do nothing, just waste time
  8. }
  9. printf("%d, ", n);
  10. }
  11. int main(int argc,char* argv[])
  12. {
  13. for(int i = 0; i < 16; ++i)
  14. Test(i);
  15. system("pause");
  16. }

结果为:

0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10,11,12,13,14,15,

  1. //使用OpenMP
  2. <pre name="code" class="cpp">#include <stdio.h>
  3. #include <stdlib.h>
  4. #include <omp.h>
  5. void Test(int n) {
  6. for(int i = 0; i < 10000; ++i) {
  7. //do nothing, just waste time
  8. }
  9. printf("%d, ", n);
  10. }
  11. int main(int argc,char* argv[])
  12. {
  13. #pragma omp parallel for
  14. for(int i = 0; i < 16; ++i)
  15. Test(i);
  16. system("pause");
  17. }

(我的笔记本为2核 4线程)

显示结果为:

0,12,4,8,1,13,5,9,2,14,6,10,3,15,7,11,

OpenMP将循环0-15拆分成0-3,4-7,8-11,12-15四个部分来执行。

当编译器发现#pragma omp parallel for后,自动将下面的for循环分成N份,(N为电脑CPU线程数),然后把每份指派给一个线程去执行,而且多线程之间为并行执行。

关于获取CPU核数与线程ID

  1. #include <iostream>
  2. #include <omp.h>
  3. int main(){
  4. int sum = 0;
  5. int a[10] = {1,2,3,4,5,6,7,8,9,10};
  6. int coreNum = omp_get_num_procs();//获得处理器个数(其实获取的是线程的数量,我的笔记本为2核4线程,测试时获取的数字为4)</span>
  7. int* sumArray = new int[coreNum];//对应处理器个数,先生成一个数组
  8. for (int i=0;i<coreNum;i++)//将数组各元素初始化为0
  9. sumArray[i] = 0;
  10. #pragma omp parallel for
  11. for (int i=0;i<10;i++)
  12. {
  13. int k = <span style="color:#3366FF;">omp_get_thread_num();//获得每个线程的ID</span>
  14. sumArray[k] = sumArray[k]+a[i];
  15. }
  16. for (int i = 0;i<coreNum;i++)
  17. sum = sum + sumArray[i];
  18. std::cout<<"sum: "<<sum<<std::endl;
  19. return 0;
  20. }

Ubuntu系统中使用

=================ubuntu系统中=====================================

Hands on FAQ:

*怎么在Linux上运行OpenMP程序? 
> 只需要安装支持OpenMP的编译器即可,比如GCC 4.2以上版本(好像Fedora Core带的部分4.1版本也支持),或者ICC(我用的version 9.1是支持的,其他没试过)。

*怎么缺点编译器是不是支持OpenMP? 
> 看编译器安装路径下/include目录里有没有omp.h。

*怎么区分OpenMP程序? 
> 程序中有没有以下内容: 
> #include <omp.h> 
> #pragma omp ...

*怎么编译OpenMP程序? 
> gcc -fopenmp [sourcefile]   -o [destination file] 
> icc   -openmp   [sourcefile]   -o [destination file]

*怎么运行OpenMP程序? 
> 编译后得到的文件和普通可执行文件一样可以直接执行。

*怎么设置线程数? 
>:在程序中写入set_num_threads(n); 
> Method2:export OMP_NUM_THREADS=n; 
> 两种方法各有用处,前者只对该程序有效,后者不用重新编译就可以修改线程数。

Example1:并行与串行时间差别

Sequetial Version:

  1. #include<iostream>
  2. #include<sys/time.h>
  3. #include<unistd.h>
  4. using namespace std;
  5. void test(int n)
  6. {
  7. int a=0;
  8. struct timeval tstart,tend;
  9. double timeUsed;
  10. gettimeofday(&tstart,NULL);
  11. for(int i=0;i<1000000000;i++)
  12. {
  13. a=i+1;
  14. }
  15. gettimeofday(&tend,NULL);
  16. timeUsed=1000000*(tend.tv_sec-tstart.tv_sec)+tend.tv_usec-tstart.tv_usec;
  17. cout<<n<<" Time="<<timeUsed/1000<<" ms"<<endl;
  18. }
  19. int main()
  20. {
  21. struct timeval tstart,tend;
  22. double timeUsed;
  23. gettimeofday(&tstart,NULL);
  24. int j=0;
  25. for(j=0;j<4;j++)
  26. {
  27. test(j);
  28. }
  29. gettimeofday(&tend,NULL);
  30. timeUsed=1000000*(tend.tv_sec-tstart.tv_sec)+tend.tv_usec-tstart.tv_usec;
  31. cout<<" Total Time="<<timeUsed/1000<<" ms"<<endl;
  32. return 0;
  33. }

Parallel Version:

  1. #include<iostream>
  2. #include<sys/time.h>
  3. #include<unistd.h>
  4. #include<omp.h>
  5. using namespace std;
  6. void test(int n)
  7. {
  8. int a=0;
  9. struct timeval tstart,tend;
  10. double timeUsed;
  11. gettimeofday(&tstart,NULL);
  12. for(int i=0;i<1000000000;i++)
  13. {
  14. a=i+1;
  15. }
  16. gettimeofday(&tend,NULL);
  17. timeUsed=1000000*(tend.tv_sec-tstart.tv_sec)+tend.tv_usec-tstart.tv_usec;
  18. cout<<n<<" Time="<<timeUsed/1000<<" ms"<<endl;
  19. }
  20. int main()
  21. {
  22. struct timeval tstart,tend;
  23. double timeUsed;
  24. gettimeofday(&tstart,NULL);
  25. int j=0;
  26. #pragma omp parallel for
  27. for(j=0;j<4;j++)
  28. {
  29. test(j);
  30. }
  31. gettimeofday(&tend,NULL);
  32. timeUsed=1000000*(tend.tv_sec-tstart.tv_sec)+tend.tv_usec-tstart.tv_usec;
  33. cout<<" Total Time="<<timeUsed/1000<<" ms"<<endl;
  34. return 0;
  35. }

Result:

Sequential version:

  1. 0 Time=2064.69 ms
  2. 1 Time=2061.11 ms
  3. 2 Time=2076.32 ms
  4. 3 Time=2077.93 ms
  5. Total Time=8280.14 ms

Parallel version:

  1. 2 Time=2148.22 ms
  2. 3 Time=2151.72 ms
  3. 0 Time=2151.85 ms
  4. 1 Time=2151.77 ms
  5. Total Time=2158.81 ms

------------------------------------------------------------------------------------------------------------------------------------------------------------

Example2:矩阵拟合法计算Pi

Sequential Version:

  1. #include<iostream>
  2. #include<sys/time.h>
  3. #include<unistd.h>
  4. //#include <omp.h>
  5. using namespace std;
  6. int main ()
  7. {
  8. struct timeval tstart,tend;
  9. double timeUsed;
  10. static long num_steps =1000000000;
  11. double step;
  12. int i;
  13. double x, pi, sum = 0.0;
  14. step = 1.0/(double) num_steps;
  15. gettimeofday(&tstart,NULL);
  16. //#pragma omp parallel for reduction(+:sum) private(x) /*只加了这一句,其他不变*/
  17. for (i=0;i < num_steps; i++)
  18. {
  19. x = (i+0.5)*step;
  20. sum = sum + 4.0/(1.0+x*x);
  21. }
  22. pi = step * sum;
  23. gettimeofday(&tend,NULL);
  24. timeUsed=1000000*(tend.tv_sec-tstart.tv_sec)+tend.tv_usec-tstart.tv_usec;
  25. timeUsed=timeUsed/1000;
  26. cout<<"pi="<<pi<<"  ("<<num_steps<<" )   "<<timeUsed<<" ms"<<endl;
  27. return 0;
  28. }

Parallel Version:

  1. #include<iostream>
  2. #include<sys/time.h>
  3. #include<unistd.h>
  4. #include <omp.h>
  5. using namespace std;
  6. int main ()
  7. {
  8. struct timeval tstart,tend;
  9. double timeUsed;
  10. static long num_steps = 1000000000;
  11. double step;
  12. int i;
  13. double x, pi, sum = 0.0;
  14. step = 1.0/(double) num_steps;
  15. gettimeofday(&tstart,NULL);
  16. #pragma omp parallel for reduction(+:sum) private(x) /*只加了这一句,其他不变*/
  17. for (i=0;i < num_steps; i++)
  18. {
  19. x = (i+0.5)*step;
  20. sum = sum + 4.0/(1.0+x*x);
  21. }
  22. pi = step * sum;
  23. gettimeofday(&tend,NULL);
  24. timeUsed=1000000*(tend.tv_sec-tstart.tv_sec)+tend.tv_usec-tstart.tv_usec;
  25. timeUsed=timeUsed/1000;
  26. cout<<"pi="<<pi<<"  ("<<num_steps<<" )   "<<timeUsed<<" ms"<<endl;
  27. return 0;
  28. }

运行结果为:

  1. von@von-pc:~/test$ ./parrPI2
  2. pi=3.14159  (1000000000 )   3729.68 ms
  3. von@von-pc:~/test$ ./seqPI2
  4. pi=3.14159  (1000000000 )   13433.1 ms

我的电脑为2核,4线程 提升速度为13433/3739=3.6 。因为这个程序本身具有良好的并发性,循环间几乎没有数据依赖,除了sum,但是用reduction(+:sum)把对于sum的相关也消除了。

关于reduction , private具体请到references 7中查看。

需要特别注意的一点是:

上述的计时方法使用的是gettimeofday() 而原博客给出的计时方法是time_t (使用time_t是没法达到作者所说的速度的,你会发现 并行的时间比串行还慢)。

主要原因:计时方法不一样,具体请看两者的区别(另一篇博客)

reference:

1:http://baike.baidu.com/view/1687659.htm

2:http://www.cnblogs.com/yangyangcv/archive/2012/03/23/2413335.html

-----------------------------------------------------------------------------------------------------------------

3:http://www.ibm.com/developerworks/cn/aix/library/au-aix-openmp-framework/index.html

4:http://openmp.org/wp/openmp-compilers/(官网)

5:http://blog.163.com/zl_dream1106/blog/static/84286020105210012295/   (linux 系统中OpenMP)

6:http://blog.163.com/zl_dream1106/blog/static/842860201052952352/?suggestedreading&wumii(OpenMP编程指南)

7:http://blog.163.com/zl_dream1106/blog/static/84286020105293213869/?suggestedreading&wumii(OpenMP 入门)

openMP多线程编程的更多相关文章

  1. Openmp多线程编程练习

    环境配置 一般使用Visual Studio2019来作为openmp的编程环境 调试-->属性-->C/C++-->所有选项-->Openmp支持改为 是(可以使用下拉菜单) ...

  2. 在C++中使用openmp进行多线程编程

    在C++中使用openmp进行多线程编程 一.前言 多线程在实际的编程中的重要性不言而喻.对于C++而言,当我们需要使用多线程时,可以使用boost::thread库或者自从C++ 11开始支持的st ...

  3. OpenMP 并行编程

    OpenMP 并行编程 最近开始学习并行编程,目的是为了提高图像处理的运行速度,用的是VS2012自带的OpenMP. 如何让自己的编译器支持OpenMP: 1) 点击 项目属性页 2)点击 配置 3 ...

  4. Web Worker javascript多线程编程(一)

    什么是Web Worker? web worker 是运行在后台的 JavaScript,不占用浏览器自身线程,独立于其他脚本,可以提高应用的总体性能,并且提升用户体验. 一般来说Javascript ...

  5. Web Worker javascript多线程编程(二)

    Web Worker javascript多线程编程(一)中提到有两种Web Worker:专用线程dedicated web worker,以及共享线程shared web worker.不过主要讲 ...

  6. windows多线程编程实现 简单(1)

    内容:实现win32下的最基本多线程编程 使用函数: #CreateThread# 创建线程 HANDLE WINAPI CreateThread( LPSECURITY_ATTRIBUTES lpT ...

  7. Rust语言的多线程编程

    我写这篇短文的时候,正值Rust1.0发布不久,严格来说这是一门兼具C语言的执行效率和Java的开发效率的强大语言,它的所有权机制竟然让你无法写出线程不安全的代码,它是一门可以用来写操作系统的系统级语 ...

  8. windows多线程编程星球(一)

    以前在学校的时候,多线程这一部分是属于那种充满好奇但是又感觉很难掌握的部分.原因嘛我觉得是这玩意儿和编程语言无关,主要和操作系统的有关,所以这部分内容主要出现在讲原理的操作系统书的某一章,看完原理是懂 ...

  9. Java多线程编程核心技术---学习分享

    继承Thread类实现多线程 public class MyThread extends Thread { @Override public void run() { super.run(); Sys ...

随机推荐

  1. 《Inside C#》笔记(五) 方法

    方法用来体现类的行为. 一 相关概念 a) ref和out 通常一个方法只能返回一个值,但如果确实需要返回多个值时,可以使用ref或out.如果方法的参数被标注为ref或out,在调用该方法时,会传递 ...

  2. Android系统启动流程 总结

    整体流程大致如下:   Android系统的启动,主要是指Android手机关机后,长按电源键后,Android手机开机的过程.从系统角度看,Android的启动程序可分为:   1.bootload ...

  3. BigDecimal遇到的问题,大伙也说说

    一:相除精度丢失的问题 BigDecimal的api除法相对加减乘要实现的复杂多了,只介绍常用的我遇到的问题: 问题:两数相除,如果9/3=3整除没问题,但是10/3=0.33333333...... ...

  4. unresolved external symbol boost::throw_exception

    使用boost库,VS生成的时候一直报错, error LNK2019: 无法解析的外部符号 "void __cdecl boost::throw_exception(class std:: ...

  5. 3.5Python数据处理篇之Numpy系列(五)---numpy文件的存取

    目录 目录: (一)以文本形式存取 1.说明: 2.语法解释: 3.实例(以.csv文件为例) 4.效果展示 (二)以任意的形式存取 1.说明: 2.语法解释: 3.实例(以.bat二进制文件为例) ...

  6. python学习-判断是否是私网IP地址

    判断是否是私网IP地址 私网IP地址范围如下: 192.168.0.0-192.168.255.255 172.16.0.0-172.31.255.255 10.0.0.0-10.255.255.25 ...

  7. 解决win10系统dpi放大后,部分网页文字颜色很浅的问题

    前段时间,换了个27寸的4k显示器.原始分辨率下文字太小,眼睛估计得看瞎 放大dpi后,这问题,那问题,好多 百度知道,淘宝,这网页文字颜色也非常的浅,看着眼睛很累人 看了半天是字体若的祸 暂时发现A ...

  8. React学习笔记_01

    使用Facebook的create-react-app快速构建React开发环境 前言: create-react-app:来自Facebook官方的零配置命令行工具 create-react-app ...

  9. golang xorm框架的使用

    1.创建engine engine, err := xorm.NewEngine(driverName, dataSourceName) 上述代码创建了一个数据库引擎,可以在一个程序中创建多个engi ...

  10. js从数组中删除指定值(不是指定位置)的元素

    RT: js从数组中删除指定值的元素,注意是指定值,而不是指定位置. 比如数组{1,2,3,4,5},我要删除其中的元素3,但是这个3的位置我是不知道的,只知道要删除值为3的这一个元素,请问要怎么写? ...