【C++】OpenMP简介

一、背景知识

1、program作用

#pragma 是 C 和 C++ 语言中的一个预处理指令。它主要用于向编译器发送特定的信息或者指示,以便控制编译过程。#pragma 通常与编译器特定的选项或功能一起使用,因此它的具体行为和实现可能因不同的编译器而有所不同。

#pragma 的语法如下:

#pragma directive_name optional_arguments

其中,directive_name 是一个编译器识别的指示名称,optional_arguments 是可选的参数。

#pragma 的一些常见用途包括:

  • 优化:可以通过向编译器提供优化建议来改善生成的代码性能。例如,#pragma omp parallel for 用于 OpenMP 并行编程,以在循环中实现线程级并行。
  • 诊断:可以启用或禁用特定的编译器警告。例如,#pragma warning(disable: 4996) 可以在 Visual Studio 中禁用特定警告。
  • 代码段:可以将代码段驻留在特定的内存区域。例如,#pragma code_seg(“MY_SECTION”) 可以将代码段放置在名为 “MY_SECTION” 的内存区域中。
  • 初始化和终止函数:可以指定在程序启动和退出时自动执行的函数。例如,#pragma startup func1 和 #pragma exit func2 分别指定 func1 和 func2 在程序启动和退出时执行。
  • 数据对齐:可以控制数据结构成员的对齐方式。例如,#pragma pack(push, 1) 和 #pragma pack(pop) 分别设置和恢复数据对齐方式。

由于 #pragma 可能因编译器而异,建议查阅编译器的文档以了解支持的 #pragma 指令和相关功能。对于可移植性考虑,通常应尽量避免使用编译器特定的 #pragma。

2、C++不同版本区别

C++ 有多个版本,其中比较常见的包括:

  • C++98/03:这是最初的 C++ 标准,也称为 ISO/IEC 14882:1998(C++98),后来进行了一些小修订,称为 ISO/IEC 14882:2003(C++03)。该标准引入了类、继承、多态、模板等面向对象编程特性。它还支持异常处理、RTTI(运行时类型识别)和 STL(标准模板库)等功能。
  • C++11:也称为 ISO/IEC 14882:2011。该标准在 C++98 的基础上增加了大量新功能,如 lambda 表达式、右值引用、智能指针、constexpr 函数、nullptr 关键字、委托构造函数、变长模板等等。同时,它还对语言规范进行了一些修改和增强,以提高效率、可读性和可维护性。
  • C++14:也称为 ISO/IEC 14882:2014。该标准在 C++11 的基础上进行了一些小修订和改进。它主要增加了一些新特性,如二进制字面量、泛型 lambda 表达式、返回类型推导等。
  • C++17:也称为 ISO/IEC 14882:2017。该标准在 C++14 的基础上增加了许多新功能,如结构化绑定、内联变量、if constexpr、折叠表达式等。它还对语言规范进行了大量修改和增强,以便提高效率、可读性和可维护性。
  • C++20:也称为 ISO/IEC 14882:2020。该标准在 C++17 的基础上增加了许多新特性,如 concepts(概念)机制、三路比较运算符、协程、格式化 I/O 库等等。同时,它还增强了现有的功能,并修复了一些缺陷和错误。

查看g++默认使用的C++版本

g++ -dM -E -x c++  /dev/null | grep -F __cplusplus

版本对照表

C++标准__cplusplus值
C++ 11201103L
C++ 14201402L
C++ 17201703L

指定不同版本编译器

vim ~/.bashrc
echo alias g17=\'g++ -std=c++17\' >> ~/.bashrc
source ~/.bashrc

二、什么是OpenMP

OpenMP 是一套 C++ 并行编程框架, 也支持 Forthan .
它是一个跨平台的多线程实现, 能够使串行代码经过最小的改动自动转化成并行的。具有广泛的适应性。这个最小的改动,有时候只是一行编译原语!(在高阶示例中,我们将演示并评估加速性能)
具体实现是通过分析编译原语#pragma,将用原语定义的代码块,自动转化成并行的线程去执行。每个线程都将分配一个独立的id. 最后再合并线程结果。

OpenMP 入门与实例分析

三、关键字

1、reduction 作用

在 OpenMP 中,reduction 用于将一个变量的值从多个线程中合并为单个结果。该指令提供了一个简单的方法来实现并行计算中的归约操作。
下面是 reduction 的语法示例:

#pragma omp parallel for reduction(+:sum)
for (i = 0; i < n; i++) {
    sum += a[i];
}

在这个例子中,我们使用了 + 运算符作为 reduction 操作符,并且要对变量 sum 进行归约。在执行并行循环时,每个线程都会计算一部分的 sum 值,最终将这些值相加得到最终的结果。
其他的 reduction 操作符包括 -、*、&、|、^ 和 &&、||。可以根据具体应用场景选择适当的操作符。
需要注意的是,被归约的变量必须满足以下条件之一:

  • 全局变量(全局作用域)
  • 静态变量(静态存储期)
  • 分配在堆上的变量
  • 在 parallel 或 task region 中定义的私有变量

另外,OpenMP 还支持自定义数据类型的归约操作,需要通过 omp declare reduction 指令来声明自定义操作符和数据类型的归约方式。

2、default(shared)作用

default(shared)是OpenMP的一个指令,用于指定在并行计算中所有变量都是共享的。这意味着变量的存储将在所有线程之间共享,并且任何对变量的更改都将影响所有线程。使用此指令可以确保所有线程都使用相同的数据,因为它们都可以读取和修改共享变量。

请注意,使用default(shared)可能会导致数据竞争和不一致的结果。因此,在使用并行计算时,必须小心谨慎地选择变量的共享方式,并采取适当的同步措施来避免数据冲突。

  • 1
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
在C语言中,OpenMP是一种并行编程模型,它可以在多个线程之间共享任务,从而提高程序的性能。为了在程序中使用OpenMP函数,需要包含omp.h头文件。 在OpenMP中,可以使用临界区(critical)来保护多个线程之间共享的资源,例如公共链表。临界区内的代码在任意时刻只能由一个线程执行,以保证数据的一致性。临界区的名字是可选的,所有的临界区都是外部链接的,也就是说它们是公共变量,对所有线程可见。对于没有指定名字的临界区,OpenMP编译器会认为它们对应一个外部的临界区。临界区的代码应该是一个块结构,不允许有返回、退出或跳出语句。 下面是一个使用OpenMP并行编程的示例程序: ```c #include <stdio.h> #include <omp.h> int main() { int max = 0; int a = {11, 2, 33, 49, 113, 20, 321, 250, 689, 16}; #pragma omp parallel for for (int j = 0; j < 10; j++) { int temp = a[j]; printf("temp = a[%d = %d, id = %d\n", j, a[j], omp_get_thread_num()); #pragma omp critical { if (temp > max) max = temp; printf("temp = %d, max = %d, id = %d\n", temp, max, omp_get_thread_num()); } } printf("max = %d\n", max); return 0; } ``` 在Visual Studio中开发OpenMP程序,需要进行以下配置:首先选择属性页,然后在左侧选择“配置属性” -> “C/C++” -> “语言”,在右侧的“OpenMP支持”后选择“是(/openmp)”。这样就可以在Visual Studio中进行OpenMP的程序开发了。<span class="em">1</span><span class="em">2</span><span class="em">3</span>
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值