查看: 2073|回复: 0

当您的嵌入式处理器失去动力时,请尝试并行

[复制链接]

该用户从未签到

发表于 2019-8-8 10:00:39 | 显示全部楼层 |阅读模式
分享到:

下面的场景越来越常见了。您有一个正在工作的嵌入式设计,在客户那里已经部署了多年,成百上千行的调试代码为其提供支持。市场上随之而来的是一组性能新规范,采用需要大量计算的算法进行研发。您现有的CPU系列无法对此进行处理。

在这一点,您的选择不是那么乐观。您可能会选择性能更高一些的CPU系列,不会完全损失指令集兼容性。但是新操作系统(OS)版本和代码重新验证几乎一定会带来问题。新CPU会有新的硬件相关问题,从更大的功耗直至不同的DRAM接口。

当然,您也可以转到具有不同指令集的更快的CPU。但是新工具链,从编译器到调试,以及找到所有这些隐藏指令集的任务取决于您的已有代码,这种转换可能会非常困难。改变SoC供应商也会有系统级硬件相关问题。

或者您可以尝试不同的方法:找到代码中或者新算法中的性能热点,将其分成能够并行执行的多个线程。然后,您可以在多核CPU群中执行新代码。除非您目前使用非常独特的东西,那么总是有很好的机会使用有多个CPU内核例化的芯片。或者,您的数据本质上是并行的,您可以重新编写这些线程,在图形处理器(GPU)、多核数字信号处理(DSP)芯片,或者FPGA和ASIC中的专用硬件加速器上运行。所有这些选择都需要新代码——但是只针对您所加速的某些代码段。大部分已有代码可以保持不变。

实现并行

如果您决定采用并行路线,接下来最明显的问题就是怎样实现它。正如您所预计的,答案取决于您的代码以及所选硬件的并行特性。

总是有手动方法。如果您打算研究如何实现任务的并行。例如,带来麻烦的需求是最大延时规范,例程中最差情况通路上有太多的指令。如果在多核配置中您有N个CPU,您可以将关键例程分成N个独立线程,在每一个CPU内核上并行运行。您可能会思考执行一些线程,这样大部分线程不需要等待其他地方的计算结果。

采用多核感知操作系统,您可以将每一线程与不同的内核相关联,同时启动它们,减小最慢线程的任务延时,稍有一些开销。如果幸运的话,能够提高近1/N。当然,您负责找到线程避免共享存储器或者I/O带来的冲突问题。如果改变了算法或者硬件,您可能不得不重新开始。

另一手动机会来自硬件加速器。如果您使用GPU,可以通过它来探查数据的并行处理。您需要在供应商开发的GPU语言中对任务重新编码,例如Nvidia的CUDA。相似的,如果您采用FPGA来加速任务,会使用Verilog或者VHDL描述所需的状态机和数据通路来进行加速计算。在GPU和FPGA这两种情况下,有翻译至少能够帮助您将C/C++转换成所需的硬件专用语言,您利用这些语言开始工作。但是在这一过程的前端和后端仍然有手动步骤。

这里对自动处理的需求非常明显:能够处理您代码的工具,对比通路和时序约束,找到可以并行的热点,将其转换为目标硬件中的代码。还没有这类工具。但是有两种工具,都是在嵌入式计算环境之外开发的,能够完成大部分这类工作。

OpenXX

其他领域在进行嵌入式计算之前就遇到了并行处理难题。例如,在高性能计算中,从早期Cray机等大量的单线程处理器到小规模的多核处理器阵列等,都要求程序员重新编码。他们不得不从具有大量本地参考的巨大的线程转到能够在不同内核上运行的半独立线程。由于真正的大规模工作通常会转到最先面市的超级计算机上,程序员希望能够有一种与机器无关的方式来完成这类工作的工作台。对此最成功的答案之一是OpenMP。

由于其传承性,OpenMP被认为能够帮助编程人员在同构、共享存储器多处理环境中应用代码(图1)。最近扩展到采用加速器以及多核群来一起工作,但仍然是基于共享存储器。理想情况下,在OpenMP中应用代码后,会在有OpenMP平台的任何系统中正确的执行,而性能会有很大的不同。

图1.OpenMP建立在共享存储器多处理模型基础上。

OpenMP通过读取注释——您在C或者FORTRAN中的注释,在代码中建立并行区,在这些区域中分开多个线程,将线程分配给单独的处理器。您通过注释标记并行区的开始(在FORTRAN中)和结束。然后——接下来是对很多的功能进行极大的简化,您可以从两个不同的模型中进行选择。您可以告诉OpenMP,闭环代码是for循环(或者DO循环,如果您是FORTRAN程序员),OpenMP应解开循环,提取出能够并行执行的线程。这是您进行数据并行处理常用的方法。或者,您可以告诉OpenMP,代码含有一些独立部分——每一部分以更多的注释进行标记,可以在单独的处理器中执行。这是任务并行的方法。

OpenMP平台根据您在注释中放置的指令、可用硬件以及运行时变量,将您找到的线程分配给处理器。这样,您可以实现从纯粹的任务静态映射到处理器直至全动态系统的所有工作。如果您告诉OpenMP恢复正常工作,您最初的程序会以最初的形式运行,一个CPU上的一个线程。如果您让OpenMP使用更多的CPU,它会尝试按照您要求的方式来进行。其他的指令控制线程的同步,变量的控制和使用,以及并行编程所必须的其他工作。

注意,OpenMP处理结构,而不是方法。完全由您来决定哪些任务应并行处理,怎样防止出现冲突问题,怎样避免死锁,等等。OpenMP不设定任务间通信模型,也不提供调试环境——您可以自由的选择自己的。OpenMP基本上位于您现有工具链和OS的顶层——尽管有一些工作是建立裸金属OpenMP平台。

OpenCL简介

在超级计算环境下从OpenMP工作中分离出来,苹果计算机的一个团队多年前以完全不同的方式开始研究同样的难题——并行代码。不是采用共享公共虚拟存储器的多个同样内核的系统来工作,苹果团队关注的是较小的不对称体系结构中的数据并行问题,一个CPU连接了多个硬件加速器。即,他们关注个人计算机。Intel、Nvidia和AMD——都采用了CPU+GPU SoC,很快在这方面进行了投入。他们的结果是开放计算语言(OpenCL)。

与OpenMP相似,OpenCL为并行提供了平台。与最初的OpenMP不同,OpenCL看到了异构环境,每一个处理器使用本地存储器中定义清楚的底层存储器(图2)。与OpenMP不同,OpenCL要求将您的部分C代码转换为扩展子集。(对不起,FORTRAN程序员。)为避免重新编写更严格的语言,OpenCL™平台将您代码的并行部分转译成能够在所支持的加速器硬件中执行的代码。目前,这包括某些GPU、多核DSP SoC、FPGA、固定功能加速器,例如,视频处理器,或者同时使用这些器件。

图2.OpenCL模型假设具有本地存储器的异构系统。

OpenCL开发流程与OpenMP的开发流程完全不同。并不是通过注释对程序标注,而是开发一组程序。主程序——相当于OpenMP中的主线程,您采用C/C++、Python、Java,或者大家不太知道的语言进行编写。在很多情况下,通过应用程序接口(API)调用替代某些程序段能够简化您已有的程序。您正常编译主程序,以及OpenCL API库,在您的主CPU上执行。(注意,OpenCL是面向主CPU和协处理器,即使是能够用在同构多核硬件中。)

您希望加速的代码部分——在OpenMP中通过注释标记的部分,采用OpenCL的C语言,作为单独的小程序而重新编写。这些小程序被称为核。您的主程序会通过您在前面段落中插入的OpenCL API调用来激活它们。

在运行时,OpenCL平台寻找哪些硬件实际上适用于它。如果没有可用的加速器,核会使用主CPU (如果是Intel或者AMD体系结构),就像有加速器,因此,您实际上得到了最初的单线程程序。如果有其他的硬件,OpenCL会编译核,对其进行探查。这可能会包括解开循环,或者分解矢量操作,将结果线程分到多个CPU内核上,或者GPU中的很多小处理器上。或者会将核的输入数据与SoC或者FPGA中的固定功能加速器相绑定。当您运行主程序时,会激活核,从而在加速器上执行。

FPGA呈现了一个有趣的特殊案例,面向FPGA的OpenCL工具能够将核编译到Verilog中,在运行之前,为FPGA离线综合硬件加速器。然后,OpenCL驱动会在运行时把加速器装载到FPGA中。通过建立定制硬件,您通常可以避免指令获取和解码工作,不需要内部数据移动,找到传统CPU无法完成的精细粒度并行操作。

最初发布的OpenCL附加了很多规范,包括更多的数据类型,更灵活的存储器组织,能够将较大的GPU或者FPGA等器件分成几个不同的加速器,增加管道,程序可以不使用缓冲,将数据从输入直接送入加速器。

做出决定

那么如何选择呢:手动并行,OpenMP,还是OpenCL?(是的,有其他的,有不太公开的选择。)当然,第一个问题,哪一种平台适用于您所考虑的硬件。有为大部分多核SoC提供的多核OS——尽管并不是所有的都支持非对称多处理。手动操作通常是可行的,不需要建立自己的裸机RTOS。

OpenMP如果能够提供一个简单的编程模型,可以说是任务并行或者同构多核SoC的最佳解决方案。但它只是从超级计算移植到嵌入式环境中。看起来德州仪器的Keystone ARM®加多核DSP SoC有供应商支持。这令人联想到,2月份ARM加入了OpenMP体系结构检查委员会,使得嵌入式巨头在平台方面有发言权。这些事实更清楚的展示了这些公司在服务器和嵌入式计算发展方面的策略。

OpenCL的数据并行加速与异构系统非常贴近,很快便融入到嵌入式环境中。某些SoC结合CPU和GPU,某些DSP SoC,以及某些FPGA提供OpenCL平台。越来越多的公司为这些芯片提供封装,提供全包OpenCL环境支持。

这些解决方案都没有为已有代码提供自动并行处理支持。整个行业仍然采用多处理系统的高效调试方法。没有人说平台使得设计容易了。但一种出路是——需求超出了您目前体系结构的发展,转到并行要比把大量的已有代码改成新指令集体系结构容易得多,而且风险也小得多。最终性能会非常好,能耗也低很多。值得了解一下。



回复

使用道具 举报

您需要登录后才可以回帖 注册/登录

本版积分规则

关闭

站长推荐上一条 /1 下一条

手机版|小黑屋|与非网

GMT+8, 2024-4-24 12:30 , Processed in 0.112841 second(s), 18 queries , MemCache On.

ICP经营许可证 苏B2-20140176  苏ICP备14012660号-2   苏州灵动帧格网络科技有限公司 版权所有.

苏公网安备 32059002001037号

Powered by Discuz! X3.4

Copyright © 2001-2024, Tencent Cloud.