openMP多线程编程
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
如下简单例子:
- //未使用OpenMP
- #include <stdio.h>
- #include <stdlib.h>
- void Test(int n) {
- for(int i = 0; i < 10000; ++i)
- {
- //do nothing, just waste time
- }
- printf("%d, ", n);
- }
- int main(int argc,char* argv[])
- {
- for(int i = 0; i < 16; ++i)
- Test(i);
- system("pause");
- }
结果为:
0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10,11,12,13,14,15,
- //使用OpenMP
- <pre name="code" class="cpp">#include <stdio.h>
- #include <stdlib.h>
- #include <omp.h>
- void Test(int n) {
- for(int i = 0; i < 10000; ++i) {
- //do nothing, just waste time
- }
- printf("%d, ", n);
- }
- int main(int argc,char* argv[])
- {
- #pragma omp parallel for
- for(int i = 0; i < 16; ++i)
- Test(i);
- system("pause");
- }
(我的笔记本为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
- #include <iostream>
- #include <omp.h>
- int main(){
- int sum = 0;
- int a[10] = {1,2,3,4,5,6,7,8,9,10};
- int coreNum = omp_get_num_procs();//获得处理器个数(其实获取的是线程的数量,我的笔记本为2核4线程,测试时获取的数字为4)</span>
- int* sumArray = new int[coreNum];//对应处理器个数,先生成一个数组
- for (int i=0;i<coreNum;i++)//将数组各元素初始化为0
- sumArray[i] = 0;
- #pragma omp parallel for
- for (int i=0;i<10;i++)
- {
- int k = <span style="color:#3366FF;">omp_get_thread_num();//获得每个线程的ID</span>
- sumArray[k] = sumArray[k]+a[i];
- }
- for (int i = 0;i<coreNum;i++)
- sum = sum + sumArray[i];
- std::cout<<"sum: "<<sum<<std::endl;
- return 0;
- }
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:
- #include<iostream>
- #include<sys/time.h>
- #include<unistd.h>
- using namespace std;
- void test(int n)
- {
- int a=0;
- struct timeval tstart,tend;
- double timeUsed;
- gettimeofday(&tstart,NULL);
- for(int i=0;i<1000000000;i++)
- {
- a=i+1;
- }
- gettimeofday(&tend,NULL);
- timeUsed=1000000*(tend.tv_sec-tstart.tv_sec)+tend.tv_usec-tstart.tv_usec;
- cout<<n<<" Time="<<timeUsed/1000<<" ms"<<endl;
- }
- int main()
- {
- struct timeval tstart,tend;
- double timeUsed;
- gettimeofday(&tstart,NULL);
- int j=0;
- for(j=0;j<4;j++)
- {
- test(j);
- }
- gettimeofday(&tend,NULL);
- timeUsed=1000000*(tend.tv_sec-tstart.tv_sec)+tend.tv_usec-tstart.tv_usec;
- cout<<" Total Time="<<timeUsed/1000<<" ms"<<endl;
- return 0;
- }
Parallel Version:
- #include<iostream>
- #include<sys/time.h>
- #include<unistd.h>
- #include<omp.h>
- using namespace std;
- void test(int n)
- {
- int a=0;
- struct timeval tstart,tend;
- double timeUsed;
- gettimeofday(&tstart,NULL);
- for(int i=0;i<1000000000;i++)
- {
- a=i+1;
- }
- gettimeofday(&tend,NULL);
- timeUsed=1000000*(tend.tv_sec-tstart.tv_sec)+tend.tv_usec-tstart.tv_usec;
- cout<<n<<" Time="<<timeUsed/1000<<" ms"<<endl;
- }
- int main()
- {
- struct timeval tstart,tend;
- double timeUsed;
- gettimeofday(&tstart,NULL);
- int j=0;
- #pragma omp parallel for
- for(j=0;j<4;j++)
- {
- test(j);
- }
- gettimeofday(&tend,NULL);
- timeUsed=1000000*(tend.tv_sec-tstart.tv_sec)+tend.tv_usec-tstart.tv_usec;
- cout<<" Total Time="<<timeUsed/1000<<" ms"<<endl;
- return 0;
- }
Result:
Sequential version:
- 0 Time=2064.69 ms
- 1 Time=2061.11 ms
- 2 Time=2076.32 ms
- 3 Time=2077.93 ms
- Total Time=8280.14 ms
Parallel version:
- 2 Time=2148.22 ms
- 3 Time=2151.72 ms
- 0 Time=2151.85 ms
- 1 Time=2151.77 ms
- Total Time=2158.81 ms
------------------------------------------------------------------------------------------------------------------------------------------------------------
Example2:矩阵拟合法计算Pi
Sequential Version:
- #include<iostream>
- #include<sys/time.h>
- #include<unistd.h>
- //#include <omp.h>
- using namespace std;
- int main ()
- {
- struct timeval tstart,tend;
- double timeUsed;
- static long num_steps =1000000000;
- double step;
- int i;
- double x, pi, sum = 0.0;
- step = 1.0/(double) num_steps;
- gettimeofday(&tstart,NULL);
- //#pragma omp parallel for reduction(+:sum) private(x) /*只加了这一句,其他不变*/
- for (i=0;i < num_steps; i++)
- {
- x = (i+0.5)*step;
- sum = sum + 4.0/(1.0+x*x);
- }
- pi = step * sum;
- gettimeofday(&tend,NULL);
- timeUsed=1000000*(tend.tv_sec-tstart.tv_sec)+tend.tv_usec-tstart.tv_usec;
- timeUsed=timeUsed/1000;
- cout<<"pi="<<pi<<" ("<<num_steps<<" ) "<<timeUsed<<" ms"<<endl;
- return 0;
- }
Parallel Version:
- #include<iostream>
- #include<sys/time.h>
- #include<unistd.h>
- #include <omp.h>
- using namespace std;
- int main ()
- {
- struct timeval tstart,tend;
- double timeUsed;
- static long num_steps = 1000000000;
- double step;
- int i;
- double x, pi, sum = 0.0;
- step = 1.0/(double) num_steps;
- gettimeofday(&tstart,NULL);
- #pragma omp parallel for reduction(+:sum) private(x) /*只加了这一句,其他不变*/
- for (i=0;i < num_steps; i++)
- {
- x = (i+0.5)*step;
- sum = sum + 4.0/(1.0+x*x);
- }
- pi = step * sum;
- gettimeofday(&tend,NULL);
- timeUsed=1000000*(tend.tv_sec-tstart.tv_sec)+tend.tv_usec-tstart.tv_usec;
- timeUsed=timeUsed/1000;
- cout<<"pi="<<pi<<" ("<<num_steps<<" ) "<<timeUsed<<" ms"<<endl;
- return 0;
- }
运行结果为:
- von@von-pc:~/test$ ./parrPI2
- pi=3.14159 (1000000000 ) 3729.68 ms
- von@von-pc:~/test$ ./seqPI2
- 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多线程编程的更多相关文章
- Openmp多线程编程练习
环境配置 一般使用Visual Studio2019来作为openmp的编程环境 调试-->属性-->C/C++-->所有选项-->Openmp支持改为 是(可以使用下拉菜单) ...
- 在C++中使用openmp进行多线程编程
在C++中使用openmp进行多线程编程 一.前言 多线程在实际的编程中的重要性不言而喻.对于C++而言,当我们需要使用多线程时,可以使用boost::thread库或者自从C++ 11开始支持的st ...
- OpenMP 并行编程
OpenMP 并行编程 最近开始学习并行编程,目的是为了提高图像处理的运行速度,用的是VS2012自带的OpenMP. 如何让自己的编译器支持OpenMP: 1) 点击 项目属性页 2)点击 配置 3 ...
- Web Worker javascript多线程编程(一)
什么是Web Worker? web worker 是运行在后台的 JavaScript,不占用浏览器自身线程,独立于其他脚本,可以提高应用的总体性能,并且提升用户体验. 一般来说Javascript ...
- Web Worker javascript多线程编程(二)
Web Worker javascript多线程编程(一)中提到有两种Web Worker:专用线程dedicated web worker,以及共享线程shared web worker.不过主要讲 ...
- windows多线程编程实现 简单(1)
内容:实现win32下的最基本多线程编程 使用函数: #CreateThread# 创建线程 HANDLE WINAPI CreateThread( LPSECURITY_ATTRIBUTES lpT ...
- Rust语言的多线程编程
我写这篇短文的时候,正值Rust1.0发布不久,严格来说这是一门兼具C语言的执行效率和Java的开发效率的强大语言,它的所有权机制竟然让你无法写出线程不安全的代码,它是一门可以用来写操作系统的系统级语 ...
- windows多线程编程星球(一)
以前在学校的时候,多线程这一部分是属于那种充满好奇但是又感觉很难掌握的部分.原因嘛我觉得是这玩意儿和编程语言无关,主要和操作系统的有关,所以这部分内容主要出现在讲原理的操作系统书的某一章,看完原理是懂 ...
- Java多线程编程核心技术---学习分享
继承Thread类实现多线程 public class MyThread extends Thread { @Override public void run() { super.run(); Sys ...
随机推荐
- AngularJS ui-router刷新子页面路由
网上有各种刷新子页面路由的方法,但是不知道为什么放到我的页面就不行了,尴尬! 网上的方法有: <a href="#" ui-sref="app.toMenu&quo ...
- [Android] 获取系统顶部状态栏(Status Bar)与底部导航栏(Navigation Bar)的高度
Android一些设备都有上下两条bar,我们可以获取这些bar的信息.下面放上获取高度的代码.代码注释和其他方法有空再放. 原文地址请保留http://www.cnblogs.com/rossone ...
- python第九十五天--js正则
定义正则表达式 /.../ 用于定义正则表达式 /.../g 表示全局匹配 /.../i 表示不区分大小写 /.../m 表示多行匹配 JS正则匹配时本身就是支持多行,此处多行匹配只是影响正则表达式^ ...
- [JSON_01] JSON 解析
0. 说明 介绍 && 测试 JSON 1. 介绍 XML 指可扩展标记语言(eXtensible Markup Language). XML 被设计用来传输和存储数据. JSON: ...
- xunit-ICollectionFixture
https://github.com/dmetzgar/dotnetcoreinaction
- Django框架的使用教程--mysql数据库[三]
Django的数据库 1.在Django_test下的view.py里面model定义模型 from django.db import models # Create your models here ...
- 反射型XSS+文件上传+CSRF—DVWA
在学习的过程中,想到将几种漏洞进行组合练习,记录下学习过程.大佬请绕过!谢谢!! 测试环境:DVWA,安装方法参考上一篇:https://www.cnblogs.com/aq-ry/p/9220584 ...
- 个人技术博客Alpha----Android Studio学习
项目联系: 本次项目我主要负责Android studio的后端,以及游戏文案游戏策划,结果后来事情太散了,Android studio学的不咋地,文案写完还有帮着写一写数据库的插入语句,然后就是跟队 ...
- Java JDK1.5、1.6、1.7新特性整理
转载请注明出处:http://www.cnblogs.com/tony-yang-flutter 一.Java JDK1.5的新特性 1.泛型: List<String> strs = n ...
- 添加xmlns:android="http://schemas.android.com/apk/res/android"的意思
http://www.cnblogs.com/lovely/archive/2013/01/17/2865192.html xmlns:android="http://schemas.and ...