OpenMp 基本

OpenMp是由OpenMP Architecture Review Board牵头提出的,并已被广泛接受的,用于共享内存并行系统的多线程程序设计的一套指导性的编译处理方案(Compiler Directive)。OpenMP支持的编程语言包括C语言C++Fortran;而支持OpenMp的编译器包括Sun Compiler,GNU Compiler和Intel Compiler等。OpenMp提供了对并行算法的高层的抽象描述,程序员通过在源代码中加入专用的pragma来指明自己的意图,由此编译器可以自动将程序进行并行化,并在必要之处加入同步互斥以及通信。当选择忽略这些pragma,或者编译器不支持OpenMp时,程序又可退化为通常的程序(一般为串行),代码仍然可以正常运作,只是不能利用多线程来加速程序执行。

中文名

共享存储并行编程

外文名

Open Multi-Processing

提出人

OpenMP Architecture

类    型

程序设计

支    持

C语言C++Fortran

目录


1简介


2基本使用


3相关信息

1简介编辑

OpenMp提供的这种对于并行描述的高层抽象降低了并行编程的难度和复杂度,这样程序员可以把更多的精力投入到并行算法本身,而非其具体实现细节。对基于数据分集的多线程程序设计,OpenMP是一个很好的选择。同时,使用OpenMP也提供了更强的灵活性,可以较容易的适应不同的并行系统配置。线程粒度和负载平衡等是传统多线程程序设计中的难题,但在OpenMp中,OpenMp库从程序员手中接管了部分这两方面的工作。

但是,作为高层抽象,OpenMp并不适合需要复杂的线程间同步和互斥的场合。OpenMp的另一个缺点是不能在非共享内存系统(如计算机集群)上使用。在这样的系统上,MPI使用较多。

2基本使用编辑

要在Visual C++2005 中使用OpenMP其实不难,只要将 Project 的Properties中C/C++里Language的OpenMP Support开启(参数为 /openmp),就可以让VC++2005 在编译时支持OpenMP 的语法了;而在编写使用OpenMP 的程序时,则需要先include OpenMP的头文件:omp.h。

而要将 for 循环并行化处理,该怎么做呢?非常简单,只要在前面加上一行

#pragma omp parallel for

就够了!

也可以实际用一段简单的程序,来弄清楚它的运作方式。

#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 < 10; ++i)

Test(i);

system("pause");

}

上面的程序,在 main() 是一个很简单的回圈,跑十次,每次都会调用Test()这个函数,并把是回圈的执行次数(i)传进Test() 并打印出来。想当然,它的结果会是:

0, 1, 2, 3, 4, 5, 6, 7, 8, 9,

而如果想利用 OpenMP把 main() 里面的回圈平行化处理呢?只需要修改成下面的样子:

#include <omp.h>

#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[]) {

#pragma omp parallel for

for(int i = 0; i < 10; ++i)

Test( i );

system("pause");

}

够简单吧?重头到尾,只加了两行!而执行后,可以发现结果也变了!

0, 5, 1, 6, 2, 7, 3, 8, 4, 9,

可以从结果很明显的发现,他没有照着0到9的顺序跑了!而上面的顺序怎么来的?其实很简单,OpenMP只是把回圈 0 - 9 共十个步骤,拆成 0 - 4, 5 - 9 两部份,丢给不同的执行绪去跑,所以数字才会出现这样交错性的输出~

而要怎么确定真的有跑多执行绪呢?如果本来有多处理器多核心处理器或有 Hyper Thread 的话,一个单执行绪程序,最多只会把一颗核心的使用量吃完;像比如说在 Pentium 4 HT 上跑,单一执行绪的程序,在工作管理员中看到的 CPU使用率最多就是 50%。而利用 OpenMP 把回圈进行平行化处理后,就可以在执行回圈时,把两颗核心的 CPU 都榨光了!也就是CPU使用率是100%。

3相关信息编辑

多执行绪的概念

OpenMP是作为共享存储标准而问世的。它是为在多处理机上编写并行程序而设计的一个应用编程接口。它包括一套编译指导语句和一个用来支持它的函数库。

当今双核、四核的 CPU 当道,而六核的CPU也已经面世多时,所以在多处理机上编写、运行并行程序会变得相当普遍。

对于一般单一执行绪(single thread)的程式,多核心处理器并没有办法提升它的处理效能;不过对於多执行绪(multi thread)的程式,就可以透过不同的核心同时计算,来达到加速的目的了!简单的例子,以单执行绪的程式来说,一件事做一次要十秒的话,要做十次,都丢给同一颗核心做的话,自然就是 10 秒 * 10 次,也就是 100 秒了;但是以多执行绪的程式来说,它可以把这一件事,分给两颗核心各自做,每颗核心各做 5 次,所以所需要的时间就只需要 50 秒!

当然,多执行绪的程式实际上没这么简单。在工作的切割、结合上,也是要多花时间的,所以在现实中,即使最佳状况,双核心的效能也不会是 1 + 1 = 2 这样的理想化。除此之外,也不是所有工作都是可以切割的!很多工作是有关联性的,这样如果直接切割给不同的处理核心各自去并行运算,出来的结果是肯定有问题的。而且,多执行绪的程式在编写、维护上,也都比单一执行绪的程式复杂上不少。

不过,如果电脑本身是多处理器多核心处理器,或是处理器拥有像 IntelHyper-ThreadingTechnology 这类的能在同一个时间处理多个执行绪的功能的话,那把各自独立的工作由单一执行绪改成多执行绪,在执行的效率上,大多还是会有增进的!

多执行绪的程式

写程序的时候该怎么去写多线程的程序呢?一般的方法,就是真的利用线程的控制,去实际在程式中去产生其他的线程来处理。像 POSIX Threads 这套 library,就是用来产生、控制执行绪的函式库。而像 Microsoft VisualStudio 2005 中,也有提供控制线程的功能。这种方法,大多就是产生多个 thread,而再由主线程把工作拆开,分给子线程去运算,最后再由主线程回收结果、整合。

但是,实际上要去控制线程是蛮麻烦的,在程序的编写上,也会复杂不少;而如果我们只是想要把一些简单的循环并行化处理,用线程库来控制,实在有点杀鸡用牛刀的感觉。这时候,用Open MP就简单多了!OpenMP 是一种能透过高阶指令,很简单地将程式并行化、多线程化的 API;在最简单的情形,甚至可以只加一行指令,就可以将循环内的程序并行化处理了!

并行计算

概论
高性能计算 计算机集群 分布式计算 网格计算
云端运算      
 
方式
Bit-level parallelism Instruction level parallelism Data parallelism 任务并行
 
理论
Speedup Amdahl定理 Flynn‘s taxonomy Cost efficiency
Gustafson定理 Karp-Flatt metric    
 
元素
进程 线程 Fiber PRAM模型
 
协调
多处理 多执行绪 超执行绪 内存一致性
Cache coherency Barrier 同步化 Application checkpointing
 
编程
Programming model Implicit parallelism Explicit parallelism  
 
硬件
贝奥武夫机群 对称多处理机 Asymmetric multiprocessing Simultaneous multithreading
非均匀访存模型 Cache only memory architecture 共享内存 Distributed memory
Distributed shared memory 超纯量 向量处理机 超级计算机
Stream processing 通用图形处理器 (GPGPU)    
 
APIs
POSIX Threads OpenMP 讯息传递接口 (MPI) Intel Threading Building Blocks
 
问题
Embarrassingly parallel Grand Challenge Software lockout 可扩放性
竞争危害 死锁 确定性算法
时间: 2024-10-11 16:19:42

OpenMp 基本的相关文章

OpenMp多线程编程计时问题

在做矩阵乘法并行化测试的时候,在利用<time.h>的clock()计时时出现了一点问题. 首先看串行的程序: // matrix_cpu.c #include <stdio.h> #include <stdlib.h> #include <time.h> #define NUM 2048 void matrixMul(float *A, float *B, float *C, int M, int K, int N) {     int i, j, k;

基于OpenMP的矩阵乘法实现及效率提升分析

一.  矩阵乘法串行实现 例子选择两个1024*1024的矩阵相乘,根据矩阵乘法运算得到运算结果.其中,两个矩阵中的数为double类型,初值由随机数函数产生.代码如下: #include <iostream> #include <omp.h> // OpenMP编程需要包含的头文件 #include <time.h> #include <stdlib.h> using namespace std; #define MatrixOrder 1024 #def

有了OpenMP,MPI,为什么还要MapReduce? (转载)

OpenMP和MPI是并行编程的两个手段,对比如下: OpenMP:线程级(并行粒度):共享存储:隐式(数据分配方式):可扩展性差: MPI:进程级:分布式存储:显式:可扩展性好. OpenMP采用共享存储,意味着它只适应于SMP,DSM机器,不适合于集群.MPI虽适合于各种机器,但它的编程模型复杂: 需要分析及划分应用程序问题,并将问题映射到分布式进程集合: 需要解决通信延迟大和负载不平衡两个主要问题: 调试MPI程序麻烦: MPI程序可靠性差,一个进程出问题,整个程序将错误: 其中第2个问题

windows下codeblocks配置openmp

使用vs直接到setting里面设置即可支持openmp了,然而我太懒了装了个codeblocks with mingw版本 本来gcc4.4后就完全支持openmp了,结果codeblocks怎么配置都提示-fopenmp这些找不到. 搞了一上午终于发现,虽然mingw支持openmp但是在codeblocks安装过程中并不让装这些组件,需要自己装个tdm-gcc with mingw,蛋疼╮(╯▽╰)╭ 配置流程: 1)下载tdm-gcc,安装的时候注意默认openmp支持是没有勾选的,记得

openMP的一点使用经验

最近在看多核编程.简单来说,由于现在电脑CPU一般都有两个核,4核与8核的CPU也逐渐走入了寻常百姓家,传统的单线程编程方式难以发挥多核CPU的强大功能,于是多核编程应运而生.按照我的理解,多核编程可以认为是对多线程编程做了一定程度的抽象,提供一些简单的API,使得用户不必花费太多精力来了解多线程的底层知识,从而提高编程效率.这两天关注的多核编程的工具包括openMP和TBB.按照目前网上的讨论,TBB风头要盖过openMP,比如openCV过去是使用openMP的,但从2.3版本开始抛弃ope

gdb 调试openmp多线程程序 示例介绍

 首先一个简单程序源代码: 1 #include <stdio.h> 2 #include <stdlib.h> 3 #include <omp.h> 4 int main(int argc, char * argv[]){ 5 int i, k,m,n; 6 printf("i=%d,threads_num=%d\n",i, omp_get_num_threads()); 7 printf("i=%d,thread_id=%d\n&quo

OpenMp实现并行化

前言 昨天,往arm上移植opencv程序,发现运行速度很慢.观察资源监视器发现只有一个核处于高负荷(总共4核),遂考虑到需要多核计算.OpenMp和MPI是常用并行计算库,OpenMP相对简单适合单机多核多线程,MPI适合集群,但复杂. OpenMp是由OpenMP Architecture Review Board牵头提出的,并已被广泛接受的,用于共享内存并行系统的多处理器程序设计的一套指导性的编译处理方案(Compiler Directive).OpenMP支持的编程语言包括C语言.C++

应用OpenMP的一个简单的设计模式

小喵的唠叨话:最近很久没写博客了,一是因为之前写的LSoftmax后馈一直没有成功,所以在等作者的源码.二是最近没什么想写的东西.前两天,在预处理图片的时候,发现处理200w张图片,跑了一晚上也才处理完一半.早上的时候,出于无奈,花半小时改写了一个简单调用OpenMP的处理程序,用了30个核心,然后一小时不到就处理完了.感慨在多核的时代,即使是简单的程序,如果能支持多核,应该都能节省不少时间. 本文系原创,转载请注明出处~ 小喵的博客:http://www.miaoerduo.com 博客原文:

连通域标记算法并行化(MPI+OpenMP)

1 背景 图像连通域标记算法是从一幅栅格图像(通常为二值图像)中,将互相邻接(4邻接或8邻接)的具有非背景值的像素集合提取出来,为不同的连通域填入数字标记,并且统计连通域的数目.通过对栅格图像中进行连通域标记,可用于静态地分析各连通域斑块的分布,或动态地分析这些斑块随时间的集聚或离散,是图像处理非常基础的算法.目前常用的连通域标记算法有1)扫描法(二次扫描法.单向反复扫描法等).2)线标记法.3)区域增长法.二次扫描法由于简单通用而被广泛使用! 图1 连通域标记示意图 随着所要处理的数据量越来越

OpenMp并行提升时间为什么不是线性的?

最近在研究OpenMp,写了一段代码,如下: #include<time.h> #include<stdio.h> #include<stdlib.h> #include<omp.h> #define THREAD_NUM 8 int main() { clock_t start,finish; int n=80000000; int sum; start=clock(); for(int i=0;i<n;i++) { sum+=2; sum-=1;