OpenMP 并行编程
OpenMP 并行编程
最近开始学习并行编程,目的是为了提高图像处理的运行速度,用的是VS2012自带的OpenMP。
如何让自己的编译器支持OpenMP: 1) 点击 项目属性页 2)点击 配置 3)点击 [C/C++] 4)点击 语言 5)选中OpenMP支持
OpenMP 的构成:编译器指令 + 运行时例程;
编译器指令: 以 #pragma omp 开头,用以告知编译器哪一段代码需要并行。
运行时例程:必须包括omp.h 设置和获取执行环境相关的信息,也包括一系列用以同步的API;
编译器指令格式如下: #pragma omp <directive> [clause[ [,] clause]…] #pragma omp <指令> [子句,子句....]
dierctive(指令)包含如下几种:parallel,for,parallel for,section,sections,single,master,criticle,flush,ordered和atomic。这些指令指定要么是用以工作共享要么是用以同步。
对指令而言,子句是可选的,子句可以影响到指令的行为。五个指令(master,cirticle,flush,ordered和atomic)不能使用子句!!
最常用,最重要的指令: parallel
parallel:这条指令为动态长度的结构化程序块创建一个并行区域。
这条指令告知编译器这一程序块应被多线程并行执行。每一条指令都执行一样的指令流,但可能不是完全相同的指令集合。这可能依赖于if-else这样的控制流语句
int i = ;
#pragma omp parallel {
i++;
printf(" %d ",i); }
Sleep();
这一段代码的输出可以判断自己的电脑是几个核的;
#pragma omp for:工作共享指令 告诉OpenMP将紧随的for循环的迭代工作分给线程组并行处理;
如
#pragma omp parallel {
#pragma omp for
for(int i = ; i < size; ++i) x[i] = (y[i-] + y[i+])/; } //下面一段代码是上面一段代码的简写
#pragma omp parallel for
for(int i = 1; i < size; ++i)
x[i] = (y[i-1] + y[i+1])/2;
这一程序在并行区域的结束处需要同步,即所有的线程将阻塞在并行区域结束处,直到所有线程都完成。
注意:::
如果前面的代码没有使用#pragma omp for指令,那么每一个线程都将完全执行这个循环,造成的后果就是线程冗余计算;
要使用并行循环,必须你必须确保没有循环依赖,即循环中的某一次迭代不依赖于其它迭代的结果。
另外,OpenMP对在#pragma omp for或#pragma omp parallel for里的循环体有形式上的限制,循环必须使用下面的形式:
for([integer type] i = loop invariant value;
i {<,>,=,<=,>=} loop invariant value;
i {+,-}= loop invariant value)
这样OpenMP才能知道在进入循环时需要执行多少次迭代。
共享数据与私有数据:
OpenMP让共享和私有的差别显而易见,并且你能手动干涉。
共享变量在线程组内的所有线程间共享。因此在并行区域里某一条线程改变的共享变量可能被其它线程访问。反过来说,在线程组的线程都拥有一份私有变量的拷贝,所以在某一线程中改变私有变量对于其它线程是不可访问的。
默认地,并行区域的所有变量都是共享的。
除非如下三种特别情况:
一、在并行for循环中,循环变量是私有的。
如下里面的例子,变量i是私有的,变量j默认是共享的,但使用了firstprivate子句将其声明为私有的。
#pragma omp parallel { #pragma omp for firstprivate(j) lastprivate(i) reduction(+: sum)//变量i,j和sum是线程组里每一个线程的私有变量,它们将被拷贝到每一个线程。 for(i = ; i < count; ++i) { int doubleI = * i; for(; j < doubleI; ++j) { sum += myMatrix.GetElement(i, j); } } }
二、并行区域代码块里的本地变量是私有的。
三、所有通过private,firstprivate,lastprivate和reduction子句声明的变量为私有变量。
这四个子句每个都有一序列的变量,但它们的语义完全不同。private子句说明变量序列里的每一个变量都应该为每一条线程作私有拷贝。这些私有拷贝将被初始化为默认值(使用适当的构造函数),例如int型的变量的默认值是0。
firstprivate有着与private一样的语义外,它使用拷贝构造函数在线程进入并行区域之前拷贝私有变量。
lastprivate有着与private一样的语义外,在工作共享结构里的最后一次迭代或者代码段执行之后,lastprivate子句的变量序列里的值将赋值给主线程的同名变量,如果合适,在这里使用拷贝赋值操作符来拷贝对象。
reduction与private的语义相近,但它同时接受变量和操作符(可接受的操作符被限制为图4列出的这几种之一),并且reduction变量必须为标量变量(如浮点型、整型、长整型,但不可为std::vector,int[]等)。reduction变量初始化为图4表中所示的值。在代码块的结束处,为变量的私有拷贝和变量原值一起应用reduction操作符。
循环嵌套:
omp_set_nested()用于设置是否允许OpenMP进行嵌套并行,默认的设置为false。
什么是嵌套并行?就是在并行区域中嵌套另一个并行区域,如下:
#pragma omp parallel num_threads(5)
{
#pragma omp parallel num_threads(5) {/*do sth */}
}
该如何执行?是执行5次?还是5×5次?这就是由是否嵌套并行来决定的,默认设置为不允许(false),所以会执行5次。
int main()
{
omp_set_nested(); // none zero value is OK! #pragma omp parallel num_threads(2)
{
printf("ID: %d, Max threads: %d, Num threads: %d \n",omp_get_thread_num(), omp_get_max_threads(), omp_get_num_threads());
#pragma omp parallel num_threads(5)
printf("Nested, ID: %d, Max threads: %d, Num threads: %d \n",omp_get_thread_num(), omp_get_max_threads(), omp_get_num_threads());
} return ;
}
由调试结果可以看出来,运行过程中,先生成两个线程,再由这个两个线程各分出五个线程。
omp_get_thread_num,获取的ID是在当前嵌套层所在的线程组的ID。
omp_get_num_threads,获取的也是当前所在层的线程组的线程数量。
omp_get_max_threads,与线程的数量和执行等都无关,这是一个可以分析出来的值。
非循环并行
OpenMP经常用以循环层并行,但它同样支持函数层并行,这个机制称为OpenMP sections。sections的结构是简明易懂的,并且很多例子都证明它相当有用。
#pragma omp parallel sections
{
#pragma omp section
//......一个并行区域
#pragma omp section
//......另一个并行区域
}
参考链接:http://blog.csdn.net/augusdi/article/details/8807699
http://blog.csdn.net/gzlaiyonghao/article/details/1503817
http://blog.csdn.net/augusdi/article/details/8807119
OpenMP 并行编程的更多相关文章
- OpenMP并行编程
什么是OpenMP?“OpenMP (Open Multi-Processing) is an application programming interface (API) that support ...
- OpenMP并行编程应用—加速OpenCV图像拼接算法
OpenMP是一种应用于多处理器程序设计的并行编程处理方案,它提供了对于并行编程的高层抽象.仅仅须要在程序中加入简单的指令,就能够编写高效的并行程序,而不用关心详细的并行实现细节.减少了并行编程的难度 ...
- OpenMP共享内存并行编程详解
实验平台:win7, VS2010 1. 介绍 平行计算机可以简单分为共享内存和分布式内存,共享内存就是多个核心共享一个内存,目前的PC就是这类(不管是只有一个多核CPU还是可以插多个CPU,它们都有 ...
- C++ OpenMp的并行编程
基于OpenMp的并行编程 功能:并行处理比较耗时的for循环 在OpenMP中,对for循环并行化的任务调度使用schedule子句来实现: 使用格式:schedule(type[,size]) t ...
- 【并行计算】基于OpenMP的并行编程
我们目前的计算机都是基于冯偌伊曼结构的,在MIMD作为主要研究对象的系统中,分为两种类型:共享内存系统和分布式内存系统,之前我们介绍的基于MPI方式的并行计算编程是属于分布式内存系统的方式,现在我们研 ...
- 并行编程OpenMP基础及简单示例
OpenMP基本概念 OpenMP是一种用于共享内存并行系统的多线程程序设计方案,支持的编程语言包括C.C++和Fortran.OpenMP提供了对并行算法的高层抽象描述,特别适合在多核CPU机器上的 ...
- 在fortran下进行openmp并行计算编程
最近写水动力的程序,体系太大,必须用并行才能算的动,无奈只好找了并行编程的资料学习了.我想我没有必要在博客里开一个什么并行编程的教程之类,因为网上到处都是,我就随手记点重要的笔记吧.这里主要是open ...
- OpenMP并行程序设计——for循环并行化详解
在C/C++中使用OpenMP优化代码方便又简单,代码中需要并行处理的往往是一些比较耗时的for循环,所以重点介绍一下OpenMP中for循环的应用.个人感觉只要掌握了文中讲的这些就足够了,如果想要学 ...
- Openmp多线程编程练习
环境配置 一般使用Visual Studio2019来作为openmp的编程环境 调试-->属性-->C/C++-->所有选项-->Openmp支持改为 是(可以使用下拉菜单) ...
随机推荐
- STM32F042开发板学习实践
之前有粗略地学习过stm32F103的理论知识,但仅GPIO的配置.时钟配置就让人望而却步.现在手头有Nucleo STM32F042的开发板,而且ST已经推出STM32CubeMx图形化的工具软件, ...
- python - 辨识alert、window以及操作
selenium之 辨识alert.window以及操作 原创 2016年08月24日 11:01:04 4820 0 2 更多关于python selenium的文章,请关注我的专栏:Python ...
- JavaScript学习整理(转载)
JavaScript的学习整理(一) 目录: 1.换皮肤功能2.显示/隐藏(点击切换)3.显示/隐藏(onmouseover/onmouseout)4.选项卡5.全选/不选/反选(checkbox)6 ...
- java,根据输入的月和日,计算出是本年的第几天。
package study01; import java.util.Scanner; public class TestDay { /* * 输入2017年的月和日:month=?,day=? 输出输 ...
- B1002 写出这个数
读入一个正整数 n,计算其各位数字之和,用汉语拼音写出和的每一位数字. 输入格式: 每个测试输入包含 1 个测试用例,即给出自然数 n 的值.这里保证 n 小于 1. 输出格式: 在一行内输出 n 的 ...
- Latex使用笔记,中文,字号等
中文 编译器选择的xelatex 或者lualatex 我试过的两种方式(都是基于ctex的). 直接使用ctex的基本documentclass \documentclass[UTF8]{ctexa ...
- Django项目SECRET_KEY等敏感信息保存
在我们做完django项目后,向生产环境部署时,为了避免一些敏感信息被有心人利用,我们应该将其保护起来,比如说在settings配置中的一些密码等内容存在操作系统内,通过调用来使用,比如下面这种做法: ...
- Beyond Compare 4 30天试用期后,破解方法
Beyond Compare 4 30天试用期后,破解方法. 方法一:在安装目录下找到文件BCUnrar.dll,比如:D:\software\Beyond Compare 4,重命名该文件即可. 重 ...
- Hibernate知识梳理
一.SessionFactory接口 是单个数据库映射关系(ORM)经过编译后的内存镜像.SessionFactory(的实例)作为应用中的一个全局对象(工厂),可以随处打开/创建一个session, ...
- cygwin的使用
参考资料: 对话 UNIX: 在 Windows 上使用 Cygwin Cygwin使用指南