openmp

openmp
多执行绪的概念
  OpenMP是作为共享存储标准而问世的。它是为在多处理机上编写并行程序而设计的一个应用编程接口。它包括一套编译指导语句和一个用来支持它的函数库。
  目前双核心的 CPU 当道,AMD 的 Athlon64x2、Intel 的 Pentium-D、Core Duo,以及即将上市的 Core 2 Duo,俨然将成为下一代电脑的主流(尤其是超低价的 Pentium D,绝对是现阶段 C/P 值极高的双核心 CPU)。但是双核心有什麼用呢?
  对於一般单一执行绪(single thread)的程式,多核心的处理器并没有办法提升它的处理效能;不过对於多执行绪(multi thread)的程式,就可以透过不同的核心同时计算,来达到加速的目的了!简单的例子,以单执行绪的程式来说,一件事做一次要十秒的话,要做十次,都丢给同一颗核心做的话,自然就是 10 秒 * 10 次,也就是 100 秒了;但是以多执行绪的程式来说,它可以把这一件事,分给两颗核心各自做,每颗核心各做 5 次,所以所需要的时间就只需要 50 秒!
  当然,多执行绪的程式实际上没这麼简单。在工作的切割、结合上,也是要多花时间的,所以在现实中,即使最佳状况,双核心的效能也不会是 1 + 1 = 2 这样的理想化。除此之外,也不是所有工作都是可以切割的!很多工作是有关联性的,这样如果直接切割给不同的处理核心各自去平行运算,出来的结果是肯定有问题的。而且,多执行绪的程式在编写、维护上,也都比单一执行绪的程式复杂上不少。
  不过,如果电脑本身是多处理器、多核心处理器,或是处理器拥有像 Intel Hyper-Threading Technology 这类的能在同一个时间处理多个执行绪的功能的话,那把各自独立的工作由单一执行绪改成多执行绪,在执行的效率上,大多还是会有增进的!
  --------------------------------------------------------------------------------
多执行绪的程式
  写程式的时候该怎麼去写多执行绪的程式呢?一般的方法,就是真的利用 thread 的控制,去实际在程式中去产生其他的 thread 来处理。像 POSIX Threads 这套 library,就是用来产生、控制执行绪的函式库。而像 Microsoft VisualStudio 2005 中,也有提供控制 thread 的功能。这种方法,大多就是产生多个 thread,而再由主要的 thread 把工作拆开,分给各 thread 去运算,最後再由主要的 thread 回收结果、整合。
  但是,实际上要去控制 thread 是满麻烦的~在程式的编写上,也会复杂不少;而如果我们只是想要把一些简单的回圈平行化处理,用 thread library 来控制,实在有点杀鸡用牛刀的感觉。这时候,用 Open MP 就简单多了!OpenMP 是一种能透过高阶指令,很简单地将程式平行化、多执行绪化的 API;在最简单的情形,甚至可以只加一行指令,就可以将回圈内的程式平行化处理了!
  --------------------------------------------------------------------------------
OpenMP 的基本使用
  要在 Visual C++ 2005 中使用 openMP 其实不难,只要将 Project 的 Properties 中 C/C++ 里 Language 的 OpenMP Support 开启(参数为 /openmp),就可以让 VC++2005 在编译时支援 OpenMP 的语法了;而在使用到 OpenMP 的档案,则需要先 include OpenMP 的 header file : 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 把 mian() 里面的回圈平行化处理呢?只需要修改成下面的样子:
  #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%。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值