OpenMP在多核DSP上的应用

  TI的多核DSP支持OpenMP,可以方便地使用多核来加速一些计算过程。

编译器

  我使用的DSP是TI的6678,编译器可以是7.4或者8.x版本。7.4版本的编译器只支持OpenMP3.0版本,而8.x版本的编译器支持OpenMP3.0和部分的OpenMP4.0的功能。因为我使用的是7.4版本的编译器,所以后面只对OpenMP3.0相关的设置进行介绍。

参考资料

  Specification里面介绍了OpenMP实现的机制,重点理解第一章里的“Excution Model”和“Memory Model”。Summary Card是一个总结,相当于一个API手册,可以用它方便地查找命令的语法。
  实际OpenMP的使用除了查阅这两个文档意外还有一些需要注意的地方。

OpenMP模块

  TI对OpenMP的支持,我在官网上只找到了这个SDK里有一个omp的模块,这个2.01.02.06应该是在网上能找到的最新的也是唯一的版本了。
在这里插入图片描述
  下载并安装完成后,可以在安装路径下找到omp_1_01_03_02这个package。在它的doc目录下也有一个文档“User_Guide.pdf"介绍了这个package的使用方式。

RTSC设置

在这里插入图片描述
  一般是直接用SDK中的OpenMP就行,但我这边有一些问题,所以用的是重新编译的OpenMP,它依赖的Package的版本和XDCTools的版本也都很重要。从SDK的Release notes里可以找到需要的版本号。主要有下面这三个:

  • IPC 1.24.3.32
  • PDK 1.1.2.6
  • SYS/BIOS 6.33.6.50

  使用重新编译的Package需要去掉原来的Packge的勾选,然后添加新的Package的目录。

地址映射

  OpenMP模块中有两个属性条目,用于地址映射。这个映射关系是始终成立的。
在这里插入图片描述
  它会将noncachedMsmcAlias作为起始地址,长度为4MB的地址空间映射到mpaxRaddr作为起始地址的4MB物理空间中。这个两个属性是由默认值的,默认会将0xA0000000开始的4MB映射到0x0C000000开始的4MB空间中。也就是原先DDR中的一部分空间映射到了MSMC上。访问0xA0000000开始的4MB空间相当于在访问MSMC。

额外的存储开销

  为了支持OpenMP的功能,同步各个核,需要一些空间存放状态,从而对各个核进行调度。这部分共享的状态/代码,都存放在MSMCSRAM_NOCACHE这块地址空间中。所以带OpenMP功能的工程的platform里需要有一个定义“MSMCSRAM_NOCACHE”的存储区域。这部分存储空间的数据是随时都有可能被其它核改写的,所以不能被Cache。
在这里插入图片描述
  记得前面做的地址映射吗,MSMC的物理地址被映射到了另一块地址上。所以L1D如果作为Cache,直接通过物理地址访问MSMC中的数据是能够被Cache的;而通过另一块地址访问则不能。
  可以看到MSMCSRAM_NOCACHE中的一大半都已经被用了,而这部分是不包含任何用户自己的代码的。所以相当于是一个固有的额外存储开销。
  MSMCSRAM_NOCACHE中还剩下一些空间没有用。所以可以把它设成platform的默认datamemory,来充分利用这部分空间。但实际上这部分空间只剩1MB左右了,如果临时变量、全局变量比较多就不太方便了。
  OpenMP的程序都需要把代码和数据放在共享的存储空间中,而在MSMC空间有限的情况下,大部分数据都只能放在DDR里,代码可以放在MSMCSRAM里。

堆区管理

  不同于单核的heap,多核系统中的共享堆区可以通过IPC中的SharedRegion这个模块实现。它使得用户在堆区中的变量能够被不同的核共享访问。
  HeapOmp管理一个Local Heap和一个Shared Heap,在Shared Heap还没建立时,先使用Local Heap。用户在堆区分配和释放空间默认都会在Shared Heap上进行操作。

OpenMP的使用

工程设置

在这里插入图片描述
  在工程设置中添加omp的编译选项。

调试

  在调试界面通过Variables窗口看到的变量值和实际值不同,但是用printf打印输出变量值能看到实际值。我猜想这部分问题是由于MPAX的设置不当造成的,因为前面的地址映射是对于每个Core来说的,而对于调试器来说,它并不知道这样的地址映射。对于这个问题的解决方式并不清楚。

结构体/类成员

  结构体中的成员或者类成员(除静态成员以外)都不能作为共享变量。包括类的成员函数,也是不能在OpenMP的代码块中执行的。这应该是OpenMP 3.0中的限制,需要特别注意。
在这里插入图片描述

常用命令

parallel for

#pragma omp parallel for
    for(int i = 0; i<N; ++i){

    }

  parallel和for是两条独立的命令,他们可以分开使用。parallel命令产生多个线程,for命令以当前线程数执行for循环。两者结合起来就是用一定的线程数执行for循环。

firstprivate/private/shared

#pragma omp parallel for firstprivate(a), private(b), shared(c)
    for(int i = 0; i<N; ++i){

    }

  在OpenMP的代码块中声明的变量都是private,firstprivate,private和shared是parallel for的子命令,它们后面的括号中需要放前面声明过的变量。
  firstprivate后面跟的变量列表中的变量是在每个thread中用相同的初始值初始化;private则是每个thread的变量都是不一样的;shared就是共享的变量。
  如果某个变量是一个类的对象,firstprivate相当于调用拷贝构造函数;private相当于调用默认构造函数;shared则不会重新生成新的变量,每个thread都访问同一个变量。

collapse

#pragma omp parallel for collapse(2)
    for(int i = 0; i<2; ++i){
        for(int j = 0; j<4; ++j){

        }
    }

  如果是多重循环,可以把它“打平”,从而更好地平行化。比如我有8核,可以做到8个thread并行,而第一重循环只有2,如果不用collapse子命令,只有2个thread会被安排任务;collapse(2)会将两重循环一起考虑,从而将循环体中的代码更加均匀地分到各个thread。

reduction

#pragma omp parallel for reduction(+:sum)
    for(int i = 0; i<N; ++i){
        sum += i;
    }

  reduction子命令可以实现分散的运算最后汇总。比如在某些时候,我们需要对变量求和,可以用多个thread分别计算部分和,最后再对这些部分和求和。

单核与多核性能对比

  引入OpenMP后,可以使程序部分并行化。每个核拷贝一份共享的变量,到自己的存储空间(threadprivate memory)进行运算,最后再写回。我觉得比较好的做法是每个thread共享指向堆区的一个指针,这样可以减少数据的搬运,而让每个thread都能对数据进行独立的修改。
  原本的单核程序可能是在L2和MSMC上运行,而使用OpenMP的程序可能受到空间限制,把程序放在DDR上运行,这样就会慢很多,反而起不到加速的效果。而每个核之间的同步也有额外的开销,所以加速效果可能达不到预期。
  实际测试发现,如果在platform里直接设置L2 Cache,OpenMP可能都跑不通,会出现任务栈溢出的错误。后来我就没有在platform上直接设置L2 Cache,而是在运行的过程中设置L2 Cache,这样做的效果也不是很理想。在DDR上开辟堆区,如果没有L2 Cache实际计算的效率非常低。源操作数和目的操作数均位于DDR上,我用4核OpenMP+L2 Cache计算8000次浮点乘法,平均每次用时80ns;而用单核+L2 Cache仅需3点几个ns。所以如果是想加速算法,真的不建议用OpenMP。

  • 0
    点赞
  • 12
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

小裘HUST

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值