虽然现在在项目上还是会用到一些OpenMP编程,但是还是想记录一下,以后看的时候也会更方便一些……
所有的在OpenMP基础中的博文主要参考的是《OpenMP编译原理及实现技术》一书,同时在实际用的时候也在网上查了很多大牛的问题解答……
1、OpenMP采用的是fork-join的形式,fork用于创建新的线程或唤醒应有的线程;join即多线程的回合。下面的图我感觉画的已经特别清楚了。
2、首先C/C++程序中,OMP的所有编译制导以#pragma omp开始,后面跟具体的功能指令。
例如:#pragma omp parallel num_threads(4) //这一句的含义是启动4个线程并行完成 {} 中的代码。
{
……
}
3、制导指令和子句的功能分类:
1)并行域控制类:指示编译器产生多个线程以并发执行任务。如上面的2
2)任务分担类:指示编译器如何给各个并发线程分发任务。如sections
3)同步控制类:指示编译器协调并发线程之间的时间约束关系。如barrier
4)数据环境类:指令处理并行域内外的变量共享或私有属性以及边界上的数据传送操作等。如private
4、我们继续拿2的代码:
#pragma omp parallel num_threads(4)
{ //并行域开始---对应1图中的fork
printf("Hello world!\n");
} //并行域结束---对应1图中的join
那么放在main函数中,然后执行以下代码……………………………………(结果会出现四行Hello world!)
在上面的代码中printf语句是在四个线程中并行执行的
5、设置线程数的方式
1)通过设置环境变量OMP_NUM_THREADS(这种方式只能在程序刚开始的时候起作用,我没这么设置过……感觉不是很方便)
2)调用omp_set_num_threads()函数,例如设置4个线程omp_set_num_threads(4);
3)通过num_thread()子句,例如面的2。
获取所在线程的线程号通过调用函数omp_get_thread_num()
获取启动线程的总数通过调用函数omp_get_num_threads()
例如在上例中的printf语句写成,printf(“Hello world! ThreadId = %d\n”,omp_get_thread_num());
还有一点要说明的是fork产生并行域之前,主线程的线程号为0。
6、for制导指令
omp_set_num_threads(4);
#pragma omp parallel for
for(int j = 0; j < 4; j++)
{
printf(“j = %d, ThreadId = %d\n”, j, omp_get_thread_num());
}
也可以写成:
#pragma omp parallel //在实际的项目中,我经常用到这种写法
{
#pragma omp for
for(int j = 0; j < 4; j++)
{
printf(“j = %d, ThreadId = %d\n”, j, omp_get_thread_num());
}
}
例如一个parallel并行域中有多个for制导指令
#pragma omp parallel
{
for(int j = 0; j < 4; j++)
{
……
}
for(int j = 0; j < 4; j++)
{
……
}
}
在并行域内多个线程并行执行第一个for,当执行完之后进行一次同步(for制导指令隐含在结束处同步),然后在进行第二个for
OK这一节就写到这里了……我在做项目的时候经常用到for制导指令,而且第二种for制导指令的写法较常用。留一下小问题就是用for制导指令可以实现累加求和吗?O(∩_∩)O