openmp并行化编程

本文介绍了OpenMP的基本语句,如并行、for、sections和critical,以及如何通过示例展示如何在C++程序中利用OpenMP实现线程共享和同步。重点讲解了Demon、section和atomic等关键特性,适合理解并行编程的初学者和进阶者。
摘要由CSDN通过智能技术生成

1. 简介

openmp是一个编译器指令和库的几何,主要是为了共享式存储计算机上的并行程序而使用的。程序的运行包括串行和并行,主程序完成串行同时子进程可以来完成并行。若并行程序没有完成不会进行程序的串行
#pragma omp指令[子句[子句]…]

2. 基本语句

  • parallel,用在一个代码段之前,表示这段代码将被多个线程并行执行
    for,用于for循环之前,将循环分配到多个线程中并行执行,必须保证每次循环之间无相关性。
  • parallel for, parallel 和 for语句的结合,也是用在一个for循环之前,表示for循环的代码将被多个线程并行执行。
  • sections,用在可能会被并行执行的代码段之前
  • parallel sections,parallel和sections两个语句的结合
  • critical,用在一段代码临界区之前
  • single,用在一段只被单个线程执行的代码段之前,表示后面的代码段将被单线程执行。
  • flush,
  • barrier,用于并行区内代码的线程同步,所有线程执行到barrier时要停止,直到所有线程都执行到barrier时才继续往下执行。
  • atomic,用于指定一块内存区域被制动更新
  • master,用于指定一段代码块由主线程执行
  • ordered, 用于指定并行区域的循环按顺序执行
  • threadprivate, 用于指定一个变量是线程私有的。

3. Demon

例子1:

#include <iostream>
#include "omp.h"
using namespace std;
int main(int argc, char **argv) {
	//设置线程数,一般设置的线程数不超过CPU核心数,这里开4个线程执行并行代码段
	omp_set_num_threads(4);
#pragma omp parallel
	{
		cout << "Hello" << ", I am Thread " << omp_get_thread_num() << endl;
	}
}

例子2:

#include <iostream>
#include "omp.h"

using namespace std;

int main() {
	omp_set_num_threads(4);
#pragma omp parallel
        for (int i = 0; i < 3; i++)
		printf("i = %d, I am Thread %d\n", i, omp_get_thread_num());
	getchar();
}

For 循环使用

#pragma omp for 
	for(i=0;i<max;i++){
	}

Sections语句的用法
section语句是用在sections语句里用来将sections语句里的代码划分成几个不同的段,每段都并行执行。用法如下:
#pragma omp [parallel] sections [ 子句 ]
{
#pragma omp section
{
代码块
}
}

先看一下以下的例子代码:
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

从结果中可以发现第4段代码执行比第3段代码早,说明各个section里的代码都是并行执行的,并且各个section被分配到不同的线程执行。

使用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语句里的代码执行完后才能执行。

用for语句来分摊是由系统自动进行,只要每次循环间没有时间上的差距,那么分摊是很均匀的,使用section来划分线程是一种手工划分线程的方式,最终并行性的好坏得依赖于程序员。

2. 参考文献

link. https://zhuanlan.zhihu.com/p/51173703
link. https://blog.csdn.net/drzhouweiming/article/details/1175848

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值