1、什么是OpenMP呢?
OpenMP是一种API(应用程序接口/一个支持共享存储并行设计的库,适合于多核CPU上的并行程序开发设计)。作为单机多核心共享内存并行编程的开发工具,编码简洁,容易上手。
线程的查看方式:这个工具是visual studio自带的,请在调试状态下,通过菜单“调试”=》“窗口”=》“线程”。
2、如何进行并行处理?
首先,并行处理的基本操作方法:首先在For循环中加入打印语句判断是否多核执行,然后判断系统确实是多核执行后,在For循环中加入等待函数sleep,运行程序并计时,判断双核乃至四核机器的并行时间是否是串行的2倍,4倍。
总共分2步:
(1) 新建一个工程。这个不再多讲。
(2) 建立工程后,点击 菜单栏->Project->Properties,弹出菜单里,点击 Configuration Properties(配置属性)->C/C++->Language->OpenMP Support,在下拉菜单里选择Yes。
程序员在编程时,只需要在特定的源代码片段的前面加入OpenMP专用的#pargma omp预编译指令,就可以“通知”编译器将该段程序自动进行并行化处理,并且在必要的时候加入线程同步及通信机制。
标准并行模式执行代码的基本思想是,程序开始时只有一个主线程,程序中的串行部分都由主线程执行,并行的部分是通过派生其他线程来执行,但是如果并行部分没有结束时是不会执行串行部分的(即先由其它线程进行并行处理,然后由主线程进行串行操作)。这就是标准的并行模式fork/join式并行模式,共享存储式并行程序就是使用fork/join式并行的,OpenMP亦是如此。。
3、在进行相加(或其他简单运算)运算时需要注意什么?
OpenMP为我们提供了另一个工具,归约(reduction):在#pragma omp parallel for 后面加上了 reduction(+:sum),它的意思是告诉编译器:下面的for循环你要分成多个线程跑,但每个线程都要保存变量sum的拷贝,循环结束后,所有线程把自己的sum累加起来作为最后的输出。
#include
int main(){
int sum = 0;
int a[10] = {1,2,3,4,5,6,7,8,9,10};
#pragma omp parallel for reduction(+:sum)
for (int i=0;i<10;i++)
sum = sum + a[i];
std::cout<<"sum: "<
reduction虽然很方便,但它只支持一些基本操作,比如+,-,*,&,|,&&,||等。
4、处理for循环
在C/C++中,OpenMP指令使用的格式为:#pragma omp 指令 [子句[子句]…]
在这里,for必须与parallel结合成parallel才可以。
#pragma omp parallel for
for(i=0;i
{
//没有循环迭代相关的语句,如把图像数组中的RGB值转为灰度值。
}
如果一次性进入一个并行段,并直接对其进行工作拆分。并且,由于以下代码进入并行段的流程仅执行一次,这样比对两个for循环使用一次并行操作运行速度更快。
#pragma omp parallel{
#pragma omp for
for (i=0; i
理想情况下,应用的所有关键性能部分(也称为热点)都将在并行段中执行。
5、处理区段sections
section语句是用在sections语句里用来将sections语句里的代码划分成几个不同的段,每段都并行执行。用法如下:
#pragma omp [parallel] sections [子句]
{
#pragma omp section
{
代码块
}
#pragma omp section
{
代码块
}
}
#pragma omp parallel{ //创建一组线程
#pragma omp for //将循环迭代分配到其中
for (i=0; i
在这里,OpenMP 首先创建了一组线程,然后将循环迭代分配到其中。循环结束后,区段被分配到线程中,从而可使每条线程与其它线程精确地并行执行一次。如果程序包括的区段数量多于线程数,则剩余的区段将在线程处理完前面的区段之后再行调度。与循环迭代不同,OpenMP 将完全控制线程执行区段的方式、时间和顺序。但是,您仍然可以通过与循环结构相同的方式使用“私有”和“减少”子句,来控制变量的分享或私有属性。
举例:
void main(int argc, char *argv)
{
#pragma omp parallel sections {
#pragma omp section
printf(“section 1 ThreadId = %d/n”, omp_get_thread_num());
#pragma omp section
printf(“section 2 ThreadId = %d/n”, omp_get_thread_num());
#pragma omp section
printf(“section 3 ThreadId = %d/n”, omp_get_thread_num());
#pragma omp section
printf(“section 4 ThreadId = %d/n”, omp_get_thread_num());
}
section 1 ThreadId = 0
section 2 ThreadId = 2
section 4 ThreadId = 3
section 3 ThreadId = 1
使用section语句时,需要注意的是这种方式需要保证各个section里的代码执行时间相差不大,否则某个section执行时间比其他section过长就达不到并行执行的效果了。
上面的代码也可以改写成以下形式:
void main(int argc, char *argv)
{
#pragma omp parallel {
#pragma omp sections
{
#pragma omp section
printf(“section 1 ThreadId = %d/n”, omp_get_thread_num());
#pragma omp section
printf(“section 2 ThreadId = %d/n”, omp_get_thread_num());
}
#pragma omp sections
{
#pragma omp section
printf(“section 3 ThreadId = %d/n”, omp_get_thread_num());
#pragma omp section
printf(“section 4 ThreadId = %d/n”, omp_get_thread_num());
}
}
section 1 ThreadId = 0
section 2 ThreadId = 3
section 3 ThreadId = 3
section 4 ThreadId = 1
这种方式和前面那种方式的区别是,两个sections语句是串行执行的,即第二个sections语句里的代码要等第一个sections语句里的代码执行完后才能执行。
推荐几个网站:
OpenMP的数据处理子句:http://blog.csdn.net/drzhouweiming/article/details/2033276
资料集锦:http://blog.csdn.net/drzhouweiming/article/details/4093624
详解及实例:http://blog.sina.com.cn/s/blog_66474b160100z15b.html
实例解析:http://www.cnblogs.com/yangyangcv/archive/2012/03/23/2413335.html