并行编程OpenMP在ARMv8架构上的应用

2,823 阅读3分钟

1.OpenMP简介

OpenMP是一种用于共享内存并行系统的多线程程序设计方案,支持的编程语言包括C、C++和Fortran。OpenMP提供了对并行算法的高层抽象描述,特别适合在多核CPU机器上的并行程序设计。编译器根据程序中添加的pragma指令,自动将程序并行处理,使用OpenMP降低了并行编程的难度和复杂度。当编译器不支持OpenMP时,程序会退化成普通(串行)程序。程序中已有的OpenMP指令不会影响程序的正常编译运行。

OpenMP采用fork-join的执行模式。开始的时候只存在一个主线程,当需要进行并行计算的时候,派生出若干个分支线程来执行并行任务。当并行代码执行完成之后,分支线程会合,并把控制流程交给单独的主线程。

一个典型的fork-join执行模型的示意图如下:

2.开发测试环境

出于对ARM多核处理器的研究,使用OpenMP模型对一款8核CPU进行简单的测试。由于现在没有开发板实物,所以我就用QEMU模拟了一个8核contex-a72、内存512M的CPU,怎么使用QEMU模拟我会在下一篇文章中讲诉。

准备:

  • Ubuntu18.04操作系统(不是虚拟机)
  • 搭建好的QEMU环境
  • 使用apt-get下载交叉编译器aarch64-linux-gnu-

3.编写OpenMP测试程序

OpenMP遍译制导指令以#pragma omp 开始,后边跟具体的功能指令,格式如:#pragma omp 指令[子句[,子句] …]。常用的功能指令如下:

  • parallel:用在一个结构块之前,表示这段代码将被多个线程并行执行;
  • for:用于for循环语句之前,表示将循环计算任务分配到多个线程中并行执行,以实现任务分担,必须由编程人员自己保证每次循环之间无数据相关性;
  • parallel for:parallel和for指令的结合,也是用在for循环语句之前,表示for循环体的代码将被多个线程并行执行,它同时具有并行域的产生和任务分担两个功能;
  • sections:用在可被并行执行的代码段之前,用于实现多个结构块语句的任务分担,可并行执行的代码段各自用section指令标出(注意区分sections和section);
  • parallel sections:parallel和sections两个语句的结合,类似于parallel for;
  • single:用在并行域内,表示一段只被单个线程执行的代码;
  • critical:用在一段代码临界区之前,保证每次只有一个OpenMP线程进入;
  • flush:保证各个OpenMP线程的数据影像的一致性;
  • barrier:用于并行域内代码的线程同步,线程执行到barrier时要停下等待,直到所有线程都执行到barrier时才继续往下执行;
  • atomic:用于指定一个数据操作需要原子性地完成;
  • master:用于指定一段代码由主线程执行;
  • threadprivate:用于指定一个或多个变量是线程专用,后面会解释线程专有和私有的区别。 还有一些经常用到的API函数

image.png

1.编写测试代码OpenMPTest.c

#include<stdio.h>  
#include"omp.h"  
void main()  
{  
#pragma omp parallel for num_threads(8)  
    for (int i = 0; i < 8; i++)  
    {  
        printf("OpenMP Test, 线程编号为: %d\n", omp_get_thread_num());  
    }  
    return 0;
}  

2.交叉编译OpenMPTest.c

aarch-linux-gnu-gcc OpenMPTest.c -o OpenMPTest

3.可执行文件OpenMPTest挂载到QEMU中Linux文件系统中

mount -o loop /home/xt/rootfs.ext3 /home/xt/tmpfs/
cp dhry.elf /home/xt/tmpfs/
umount /home/xt/tmpfs/

4.执行QEMU启动代码

qemu-system-aarch64 \
        -machine virt \
        -cpu cortex-a72 \
        -nographic \
        -m 512 \
        -smp 8 \
        -kernel /home/xt/linux-5.12.9/arch/arm64/boot/Image \
        -initrd /home/xt/rootfs.ext3 \
        -append "root=/dev/ram0 rdinit=/linuxrc console=ttyAMA0"

执行结果如下图所示: 屏幕截图 2019-11-15 105600.jpg 5.在模拟地ARM环境中执行已经挂载地可执行文件,./xxx image.png

执行完成!!!!!!!!!!!!!!!!!!

参考

blog.csdn.net/u011808673/… www.pianshen.com/article/346… blog.csdn.net/Tronlong/ar…