Fy J
CS专业扫雷学深造学者互联网冲浪一级选手
FRIENDS
jhn

Clang+OpenMP:初步

11-25-2020 10:45:29 云计算与分布式系统 OpenMP
Word count: 1.2k | Reading time: 4min

原创文章,转载、引用请注明出处!


目标

完成一个简单的OpenMP并行程序设计,体会多核并行程序的思想。

介绍

OpenMP

OpenMP是由OpenMP Architecture Review Board牵头提出的,并已被广泛接受,用于共享内存并行系统的多处理器程序设计的一套指导性编译处理方案(Compiler Directive)。

OpenMP支持的编程语言包括C、C++和Fortran;而支持OpenMp的编译器包括Sun Compiler,GNU Compiler和Intel Compiler等。

OpenMp提供了对并行算法的高层的抽象描述,程序员通过在源代码中加入专用的pragma来指明自己的意图,由此编译器可以自动将程序进行并行化,并在必要之处加入同步互斥以及通信。当选择忽略这些pragma,或者编译器不支持OpenMp时,程序又可退化为通常的程序(一般为串行),代码仍然可以正常运作,只是不能利用多线程来加速程序执行。

Gcc

GCC是以GPL许可证所发行的自由软件,也是GNU计划的关键部分。GCC的初衷是为GNU操作系统专门编写一款编译器,现已被大多数类Unix操作系统(如Linux、BSD、MacOS X等)采纳为标准的编译器,甚至在微软的Windows上也可以使用GCC。GCC支持多种计算机体系结构芯片,如x86、ARM、MIPS等,并已被移植到其他多种硬件平台。

Clang

Clang是一个C++编写、基于LLVM、发布于LLVM BSD许可证下的C/C++/Objective-C/Objective-C++编译器。它与GNU C语言规范几乎完全兼容(当然,也有部分不兼容的内容,包括编译命令选项也会有点差异),并在此基础上增加了额外的语法特性,比如C函数重载(通过attribute((overloadable))来修饰函数),其目标(之一)就是超越GCC。

Mac OS下的Gcc/Clang

有了GCC在前为何还有Clang的出现?

这是因为Apple使用LLVM在不支持全部OpenGL特性的GPU(Intel低端显卡)上生成代码JIT,令程序仍然能正常运行。之后LLVM与GCC的集成过程发生了一些不快,GCC系统庞大儿笨重,而Apple大量使用的Object-C在GCC中优先级很低。此外GCC作为一个纯粹的编译系统,与IDE配合很差。加上许可证方面的要求,Apple无法使用修改版GCC而闭源。于是Apple决定从0开始写C family的前端,也就是基于LLVM的Clang了。

实际上,在Mac OS下,对于OpenMP,早期的Gcc并不支持(大概在4.2版本之前)。后期的Gcc也能做到支持,具体做法是直接下载<omp.h>

过程

准备工作

Clang环境

选择使用Clang来完成OpenMP的简单程序。

clang -v:检查本机的Clang环境。

Mac OS通常来说会自带这一框架。

代码

代码如下:

1
2
3
4
5
6
7
8
9
10
#include <stdio.h>
#include <omp.h>

int main(int argc, char* argv[]) {
#pragma omp parallel for
for (int i = 0; i < 10; i++ ) {
printf("i = %d\n", i);
}
return 0;
}

显然,当上述代码正常运行时,会按序输出0到9,共10个数字。文件命名为omp.c

这里需要注意的是:#pragma omp parallel for。这是因为,OpenMP编程需要通过编译制导指令制导并行化。编译制导指令以#pragma omp 开始,后边跟具体的功能指令,格式为:**#pragma omp 指令[子句[,子句] …]**。在上述指令中:

  • parallel:用在一个结构块之前,表示这段代码将被多个线程并行执行

  • for:用于for循环语句之前,表示将循环计算任务分配到多个线程中并行执行,以实现任务分担,必须由编程人员自己保证每次循环之间无数据相关性。

  • parallel for:parallel和for指令的结合,也是用在for循环语句之前,表示for循环体的代码将被多个线程并行执行,它同时具有并行域的产生和任务分担两个功能。

如果没有编译制导指令,在下面的步骤中使用同样的

代码编译与运行

去掉编译制导指令,作为对比,文件名为no_omp.c。会正常输出0到9。

clang -o omp.out omp.c -Xpreprocessor -fopenmp -lomp:用来编译代码。其中,-fopenmp默认使用计算机最大核数进行运行,这个参数是可调的。

可以看到,在使用了OpenMP之后,变成了乱序输出。

再次运行代码,发现乱序输出也是随机的,表明是多线程并行处理。


参考资料

百度百科:openmp: https://baike.baidu.com/item/openmp/3735430?fr=aladdin

百度百科:gcc: https://baike.baidu.com/item/gcc/17570?fr=aladdin

百度百科:clang: https://baike.baidu.com/item/clang/3698345?fr=aladdin

Mac下使用OpenMP编写第一个多线程程序: https://blog.csdn.net/suki570/article/details/104272040

https://clang-omp.github.io

< PreviousPost
论文研读:SISR数据增广的一种新思路
NextPost >
Ubuntu16.04虚拟机+Apache:配置与初步使用
CATALOG
  1. 1. 目标
  2. 2. 介绍
    1. 2.1. OpenMP
    2. 2.2. Gcc
    3. 2.3. Clang
    4. 2.4. Mac OS下的Gcc/Clang
  3. 3. 过程
    1. 3.1. 准备工作
      1. 3.1.1. Clang环境
      2. 3.1.2. 代码
    2. 3.2. 代码编译与运行
  4. 4. 参考资料