程序运行速度慢应该是所有程序员都特别头疼的一个问题,当前对于程序运行加速有两种方式:一种是通过硬件的方式加速,比如我们常听说的硬解码,软解码,这里的硬解码就是通过硬件对程序进行加速;一种是通过软件的方式进行加速,而这种方式使用比较多的是使用共享存储编程。当前对于共享存储编程有三种标准:Pthreads,X3H5,OpenMP(最流行)。
OpenMP是一个支持共享存储并行设计的库,特别适宜多核CPU上的并行程序设计,由一系列编译指导语句和库函数组成,说白了就是一个开源库,和OpenCV差不多,只不过一个做并行处理库,一个是计算机视觉库。
一、fork/join并行执行模式
OpenMP使用的fork/join并行执行模式。
OpenMP并行执行的程序要执行完并行执行区域后才能执行主线程。这就是标准的并行模式fork/join式并行模式。因此,标准并行模式执行代码的基本思想是,程序开始时只有一个主线程,程序中的串行部分都由主线程执行,并行的部分是通过派生其他线程来执行,关闭并行区域前,主线程等待其他线程到达,也就是说,如果并行部分没有结束时是不会执行串行部分的。(实际上,这个“等待”就是一次“隐式同步”)。
二、如何应用OpenMP?
1. OpenMP常用于循环并行化; 找出最耗时的循环,在串行程序上加上编译指导语句实现并行处理,当然咯,只要每次循环互不相干,互不影响才能做成并行。
2. OpenMP常用于互不相关的两端或多端代码块的并行执行;比如在疲劳检测中要视线眨眼检测和哈欠检测,那么这个眨眼检测和哈欠检测就可以做成并行处理。
三、OpenMP程序结构
据我所知,当前OpenMP支持C、C++和fortran语言,下面就简单的写一个基于C/C++语言的OpenMP程序的结构。
#include<omp.h>
int main(int argc, char *argv)
{
#pragma omp parallel
{
printf("i like c++ programming!\n");
}
system("pause");
return 0;
}
程序运行结果如下:
可以看得出parallel语句中的代码被执行了八次,说明总共创建了8个线程去执行parallel语句中的代码,这个创建多少个线程与CPU的核数有关,我的电脑是八核的,所以创建了8个线程,代码被执行了八次。
四、并行执行特点
在了解OpenMP并行执行的特点前先看个OpenMP小程序。
#include <iostream>
#include<omp.h>
int main(int argc, char *argv)
{
printf("串行打印:\n");
for (int i = 0; i < 10; i++)
printf("%d, ", i);
printf("\n");
printf("并行打印:\n");
#pragma omp parallel for
for (int i = 0; i < 10; i++)
printf("%d, ", i);
printf("\n");
system("pause");
return 0;
}
程序运行结果可见for 循环语句中的内容被并行执行了。(每次运行的打印结果可能会有区别)。这里要说明一下,#pragma omp parallel for 这条语句是用来指定后面的for循环语句变成并行执行的,这算是是OpenMP语句入门级的使用,也是使用最频繁的一条语句。当然咯,for循环里的内容必须满足可以并行执行,即每次循环互不相干,后一次循环不依赖于前面的循环。
五、并行执行效率
将for循环里的语句变成并行执行后效率会不会提高呢,我想这是我们最关心的内容了。下面就写一个简单的测试程序来测试一下:
#include<time.h>
#include<iostream>
#include<omp.h>
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\n", 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\n", t2 - t1);
test();
return 0;
}
在test()函数中,执行了1亿次循环,主要是用来执行一个长时间的操作。在main()函数里,先在一个循环里调用test()函数,只循环2次,我们还是看一下在双核CPU上的运行结果吧:
Time = 297
Time = 297
Total time = 297
Time = 297
可以看到在for循环里的两次test()函数调用都花费了297ms, 但是打印出的总时间却只花费了297ms,后面那个单独执行的test()函数花费的时间也是297ms,可见使用并行计算后效率提高了整整一倍。上面有讲了使用最频繁的编译指导语句#pragma omp parallelfor,下面的博客会接着讲一些最常用的一些编译指导语句。
最后说一下,如何在Visual Studio这个IDE中开启OpenMP并行,打开过程如下:
项目属性->配置属性->C\C++ ->语言->OpenMP支持->是 (/openmp)
参考文献:
http://wenku.baidu.com/link?url=A-NdON4QI-9iKsRNrlw2mrqGoH2hynDhnZRXPpAWFJRnaNpoAx48tnVj3VYqieGzwJAWRlvR6cupiwCQ6rm0NlICCaPBT7cVVIkmHeHl8wa