zoukankan      html  css  js  c++  java
  • OpenMP并行编程

    OpenMP(Open Multi Processing)是由Open ARB发布的一种用于并行编程的规范,是建立在串行语言上的扩展,目前可以在C/C++/Fortran中使用。
    OpenMP的格式非常简单,原理也不难。它的基本原理就是创建多个线程,操作系统把这几个线程分到几个核上面同时执行,从而可以达到快速执行代码的目的。
    OpenMP由三部分组成:编译指导(compiler directive)、运行库(runtime library)和环境变量(environment variables)。其语言模型基于以下假设:执行单元是共享一个地址空间的线程,即OpenMP是基于派生/连接(fork/join)的编程模型。Fork/join的并行机制如下图所示:

    Fork/join并行机制:并行区前,串行命令派生出多条并行命令并行执行,执行到并行区末等待,等所有并行任务都结束,再转到串行执行。
    OpenMP有两种常用的并行开发形式:一是通过简单的fork/join对串行程序并行化;二是采用单程序多数据对串行程序并行化。

    优点:第一,共享存储模型,使得程序员不必进行数据划分和分布,使得开发并行程序比较容易;第二,更适合于SMP系统;第三,主要面向循环级的并行开发,可以容易地实现增量性的并行化。

    缺点:第一,OpenMP只适用于SMP结构;第二,OpenMP主要开发循环级的并行程序,受此限制,对某些应用并不适合;第三,OpenMP的编写、正确性调试和性能调度复杂。

    在编写OpenMP程序之前,应注意下面三点,

    • 使用vs2005或者以上的版本编写OpenMP程序
    • 编写程序的时候,选择Property Pages->Configuration Properties->c/c++->language->OpenMp Support,打开开关
    • 添加#include <omp.h> 声明。

    先看一个简单的使用了OpenMP程序

    int main(int argc, char* argv[])
    {
    #pragma omp parallel for
         for (int i = 0; i < 10; i++ )
         {
             printf("i = %d/n", i);
         }
         return 0;
    }
    

    这个程序执行后打印出以下结果:

    i = 0
    i = 5
    i = 1
    i = 6
    i = 2
    i = 7
    i = 3
    i = 8
    i = 4
    i = 9
    

    可见for 循环语句中的内容被并行执行了。(每次运行的打印结果可能会有区别)

    这里要说明一下,#pragma omp parallel for 这条语句是用来指定后面的for循环语句变成并行执行的,当然for循环里的内容必须满足可以并行执行,即每次循环互不相干,后一次循环不依赖于前面的循环。

    将for循环里的语句变成并行执行后效率会不会提高呢,我想这是我们最关心的内容了。下面就写一个简单的测试程序来测试一下:

    void test()
    {
         int a = 0;
         clock_t t1 = clock();
         for (int i = 0; i < 100000000; i++)
         {
             a = i+1;
         }
         clock_t t2 = clock();
         printf("Time = %d 
    ", t2-t1);
    }
     
    int main(int argc, char* argv[])
    {
         clock_t t1 = clock();
    #pragma omp parallel for
         for ( int j = 0; j < 2; j++ ){
             test();
         }
         clock_t t2 = clock();
         printf("Total time = %d 
    ", t2-t1);
     
         test();
         return 0;
    }
    

    test()函数中,执行了1亿次循环,主要是用来执行一个长时间的操作。
    main()函数里,先在一个循环里调用test()函数,只循环2次,我们还是看一下在四核CPU上的运行结果吧:

    Time = 190
    Time = 201
    Total time = 202
    Time = 194
    

    可以看到在for循环里的两次test() 函数调用都花费了200ms, 但是打印出的总时间却只花费了200ms,后面那个单独执行的test()函数花费的时间也是200ms,可见使用并行计算后效率提高了整整一倍。

    reference:

  • 相关阅读:
    Eclipse 远程调试
    大数据处理方法bloom filter
    sicily 1259 Sum of Consecutive Primes
    sicily 1240. Faulty Odometer
    sicily 1152 简单马周游 深度优先搜索及回溯算法
    sicily 1050 深度优先搜索解题
    sicily 1024 邻接矩阵与深度优先搜索解题
    sicily 1156 二叉树的遍历 前序遍历,递归,集合操作
    sicily 1443 队列基本操作
    sicily 1006 team rankings 枚举解题
  • 原文地址:https://www.cnblogs.com/P3nguin/p/7861957.html
Copyright © 2011-2022 走看看