EEJournal

专题文章
现在就订阅

多核自动化

找到中庸之道

我曾经是一个铁杆手动档司机。甚至在我开车之前,我就在我们的凯斯拖拉机上学会了如何用双离合器在行进中平稳地换挡(凯斯拖拉机没有同步档位,因为它不打算在行进中换挡)。我的祖母坚持使用手动变速器,直到她80多岁(或更晚?)不再开车:“我想用我的自我!(这是瑞士-德国口音…)

当我有了手机后,我终于不得不重新思考我的原则。关键时刻来了,我在红绿灯前一边打电话一边等着左转。绿灯亮了,我继续往前走,但意识到我的手不够用:我需要同时转弯、换挡、握着手机。

用非常古怪的话说,当多任务处理只涉及转向和换挡——两个独立的过程,每个过程只需要一只手(但其中一只手受益于两只手)时,我做得还不错。我能够与方向盘和换挡过程共享一个资源,我的右手。

再加上一部手机,我就遇到了资源共享的问题。电话(在使用时)靠的是我把它举到耳边。(如果联邦调查局(FBI)或其他执法机构在窃听我们的谈话,我想郑重声明,那是在免提法出台前几年的事了。)换档过程依赖于相同的资源,现在我有了对该资源的争夺。

所以……承认这可能是一个隐喻,它确实导致了一个问题:在一个不那么平凡的情况下,你如何知道如何在多核系统中执行任务,而不会导致手机掉在大腿上或汽车在换挡时转向迎面而来的左转弯汽车?(1 .完成整个转弯装备太丢人了,不是个真正的选择。)

随着多核在嵌入式世界中越来越普遍,这是一个越来越相关的问题。到目前为止,嵌入式多核首先被包处理所主导,它有自己的快和慢路径的小世界,由手工精心制作,现在是手机,有多个处理器做不同的事情。

在手机的情况下,它工作得非常好,特别是因为处理器做不同的事情——它们通常不相互作用,或者,如果相互作用,它足够简单,可以手动管理。但是现在ARM和MIPS系列的多核通用处理器正变得越来越普遍。因此,我们不再讨论将单独的进程放在单独的处理器上:我们讨论的是将一个大进程拆分为多个任务——它们可能是线程或进程——并让它们并行工作。

现在,让我们假设One Big Process已经为单个核心实现了。这意味着它是一个连续的(或串行的)程序,所有事情都以确定的、有序的方式发生。一只脚总是往前走。

就叫离婚吧

当您开始将其拆分并并行运行时,您可能会陷入大麻烦。首先,不再是单个进程请求资源,该进程的多个部分现在可能同时要求内存或外围设备的注意。内存只有这么多端口。

第二,这些任务都从头开始。如果其中一项任务反映了“一个大过程”接近尾声时发生的事情,那么,如果你不小心,它就会在其他所有任务开始时开始,并产生无意义的结果。不知何故,它必须被告知,在它所依赖的东西准备好之前,它不能启动。

简单的情况是,

A = x + y

C = a + z

当它们依次发生时,那么的值c最后是X + y + z.但如果它们被放到并行的过程中同时开始,那么c会是什么结果z加到…里面的东西里一个当时(可能是,但很可能不是)等于X + y).

不幸的是,大多数情况都没有这么明显。当在c语言中使用指针时,这就变得非常棘手了。刚才说明的简单情况可以通过对代码的静态分析来检测。但指针不是这样的——当系统崩溃时,您无法确定它们将指向什么(除了0),而且如果不使用全覆盖测试套件进行动态分析,指针算术和混叠会使问题变得棘手。

并行时如何划分程序对并行实现的运行方式有巨大的影响。有四种可能的结果:

  • 它工作得很完美;拍拍自己的背,好好休息一下。(或者醒来。)
  • 它可以工作,但是非常慢——可能比原来的顺序版本要慢。
  • 它根本不管用。好消息是,您可以立即了解并开始调试。
  • 它似乎工作得很完美。直到你发布了产品,然后客户开始到处发现奇怪的、难以捉摸的错误,这些错误很难复制,甚至更难调试。这是你的噩梦。(你希望你能醒来。)

在大多数情况下,这个问题都是由拥有非常专业的编程利基的专家手动处理的。但是没有足够的这些家伙来支持将需要的多核编程。因此,自动化正在拯救我们。但问题是,什么是自动化的?

让我们把这个问题分开,以便让我们的头脑(好吧,我的头脑)理解它,现在继续我们的假设,我们从一个已知良好的顺序程序开始。我将把创建并行版本的过程分为三个主要部分:

  1. 确定在哪里对程序进行分区
  2. 实现分区
  3. 验证和调试

第一步包括分析和决策——以及对原始程序的可能更改。第二种是修改代码,将原始程序转换为并行版本。第三个是……嗯,通常的顽强和64盎司的TweakStar能量饮料。我们将重点关注前两个。

如何分割资产

放大到第一步,它涉及到几个项目,它们的顺序可能不同:

  • 分析程序中的依赖关系
  • 对原始代码进行更改以提供更多的机会并发性
  • 评估代码划分的不同方法
  • 将分区映射到核心(在SMP环境中不需要,在SMP环境中所有的核心看起来都是一样的,操作系统处理实时的核心分配)。

关于如何分析依赖关系有一些哲学。两种不同的工具旨在帮助这个过程体现这两种理念。

其中之一是CriticalBlue的Prism。使用这个工具,您可以确定首先要评估哪些分区。对于每一种可能性,Prism可以分析依赖关系,并在时间轴上“舞台”不同的线程(我们将在这里使用术语“线程”),这样您就可以看到性能是什么样子的。可以为某些体系结构建模特定的核心行为,这样就可以包括任何特定处理器或缓存的特性。

从这个视图中,您可以看到某个特定任务可能在哪里被延迟,因为它正在等待其他任务来提供一些可用数据。因此,您可以运行“如果”分析,看看如果删除依赖项会发生什么。通过这样做,您可以评估提高程序性能的不同方法,并最终选择最佳分区方案。它不会告诉您如何更改程序,当然也不会为您进行更改(稍后将详细介绍),但它确实将您的注意力集中在需要修复的特定事项上,以便消除瓶颈。

在这种情况下,首先选择分区然后对该分区进行依赖分析。CriticalBlue的David Stewart说,你真的需要按照这个顺序来做,因为整个程序中依赖的数量是巨大的,而你真的不关心它们中的大多数。标识分区首先将您的注意力集中在重要的依赖项上。

Vector Fabrics有一种不同的方法。他们的vfEmbedded工具预先分析整个程序,开发一个依赖项数据库。它们通过程序的可视化避免了依赖关系混乱的问题:它们有一个图形显示,可以过滤掉与给定视图无关的依赖关系。

虽然这两个工具看起来非常不同,但到目前为止,它们的相似之处在于它们可以为您指出您可能希望在原始程序中消除的依赖项。但是vfEmbedded方法将依赖项分析置于分区之前。这样做的一个好处是,工具本身可以根据依赖关系推荐分区,并可能加快速度。

这里的技巧在于区分不同种类的依赖关系。在程序中找到没有依赖关系的超干净断点是不太可能的。无论您以何种方式进行拆分,您都可能不得不“交叉”或“中断”依赖项。

打破依赖关系的概念很像重新配置建筑物或修改服装时所发生的情况。你可能需要剪断一些木材或去掉一条缝,但随后你可以以一种有效的方式将它们重新组合在一起。

一些依赖关系——比如我们上面看到的简单依赖关系——很容易修复:您只需同步c计算,直到一个在继续之前已准备好。流数据可以在线程之间使用适当配置的fifo进行修复。有些依赖关系根本无法修复。

所以问题是,无论是手动还是通过工具,都要找到一种方法来削减程序

  • 没有依赖关系(不太可能),
  • 只有可以修复的依赖项(并且尽可能少),
  • 或者有不重要的不可挽回的依赖。

最后两个需要解释一下。当修复可修复的依赖关系时,必须添加实现同步的库调用。添加这些调用是一项工作,它们在运行时有一些开销。因此,在所有条件都相同的情况下,您希望修复的依赖项尽可能少。

最后一点比较微妙。关于“修复”的全部内容是确保您不会“破坏程序的语义”。换句话说,新的并行版本应该在各个方面都像原来的版本一样。如果你破坏了一个依赖而没有修复它,这通常是一件坏事(而且通常很难发现)。但有时这并不重要。

例如,如果您有一个将数据记录到文件的程序,那么它将按照特定的顺序执行。如果这个顺序很重要,那么如果一个坏的依赖项重新排列日志条目,那就不好了。但是如果顺序不重要——如果您只是想以任何顺序记录所有内容——那么更改语义(因为日志顺序已经更改)的事实也不重要。

vfEmbedded工具可以描述不同的依赖关系,以确定哪些可以修复,哪些不能修复。基于此,该工具将推荐分区。根据设计,推荐的分区将只破坏可修复的(或忽略不可修复的)依赖项。这些分区也不存在竞态条件(这里我们不会详述另一个多核噩梦)。

无论是手动完成还是借助工具完成,如果使用映射步骤,分区问题必须与映射步骤齐头并进,因为不同的内核可能具有不同的性能,或者一些内核可能会过度使用。因此,在划分程序之后,将并行块分配给不同的核心。根据结果,您可以决定尝试不同的分区。因此,如果您进行手动映射,那么您可能会交替迭代分配和映射,直到找到解决方案。

Prism和vfEmbedded都使用了选择核心的相对详细的模型——它们的性能建模是“硬件感知的”。CriticalBlue列出了各种ARM内核,包括Cavium、飞思卡尔、Intel x86、MIPS、Netlogic、Renesas和Toshiba,一些是Linux内核,一些是Android内核(外加一个裸机内核和一个V-Kernel内核)。Vector Fabrics列出x86和ARM(独立于OS)。他们都说还有更多。

所以,回顾第一步的第一部分,我们有:

  • 依赖分析:Prism和vfEmbedded使用静态和动态分析自动化此工作。另一家公司Target Compiler也这样做,但只使用静态分析,对依赖关系持悲观态度(换句话说,如果它可能是依赖关系,它会被标记为依赖关系——如果你愿意,可以忽略它)。稍后将详细介绍目标编译器。
  • 对原始代码进行更改:Prism和vfEmbedded在这里都不提供任何自动化。这就是用户喜欢的方式。“不要碰我的代码。”
  • 评估分区:这在某种程度上是Prism的手动操作,其优势在于“假设”分析能力。vfEmbedded自动识别合法(和首选)分区的过程(尽管没有什么会阻止您选择其他分区)。
  • 将分区映射到核心:这是通过Prism和vfEmbedded手动完成的,尽管有图形工具可以使这更容易。这两种工具都支持同构核组内的映射,但不支持异构多核。斯图尔特指出,单个问题不太可能被分散到不同的核心上。

写在纸上

完成这些步骤后,就有了需要实现的分区(和映射)方案。如果您正在映射代码,那么您将在系统级上将代码分配给核心,这是一项手动任务。如何做到这一点取决于系统的类型(例如SMP vs. AMP)。我只想说,没有自动化。

但是我们仍然需要在程序中实现分区。例如,这涉及到分解代码(字面上),添加线程调用(如果线程化)或创建单独的运行到完成程序。但同样重要的是添加同步数据和修复任何损坏的依赖关系的代码。

虽然这是一项乏味、费力、容易出错的工作,但它是确定的、有良好边界的。它容易出错的原因是有很多细节,错过其中任何一个都会导致问题。

目标编译器自动执行此过程。这是一种非常不同的思维方式,因为Target Compiler是一家专门创建他们所谓的特定于应用程序的处理器(asip)的公司。这些asip是为SoC创建的,以卸载通用处理器,它们本质上是专门用于特定功能的定制处理器。因为它们只实现程序的一部分,所以它们必须与主处理器通信,以便所有的依赖关系都被考虑在内。

在创建ASIP时,目标编译器还创建了用于通信的基础结构,以便自动地将所有内容放到合适的位置。

虽然在SoC中设计加速器的特定环境中,这可能是可以接受的,但程序员不太喜欢在更普遍的情况下,简单地并行顺序程序,自动进行这种更改。同样,“不要碰我的代码”倾向于占上风。这部分是因为人们不信任新工具,但也因为程序员想要拥有他们的代码,他们必须能够维护它。在这方面,机器生成的代码往往不能很好地工作。

vfEmbedded确实朝着代码更改的自动化迈出了一步:它生成了所谓的“菜谱”:这是一组关于所需更改的循序渐进的指令,以确保并行程序在语义上与连续的原始程序相同。

我们能重新开始吗?

您可能还记得,我暂时限定了这个过程,假设您从一个已知的好程序开始。这些工具可能很适合并行旧的、发霉的遗留程序,但如果要从头开始呢?从一开始就有编写并行程序的方法。但是CriticalBlue和Vector Fabrics都认为最好先写一个新的顺序程序,然后再并行化。

这有两个原因。首先,人们按顺序思考,所以更简单。但是,更实际的是,许多程序是针对许多不同的平台的。这就意味着要有一个连续的黄金原作,可以根据需要改编。因此,我们所研究的流程既可以应用于新程序,也可以应用于遗留代码。

所以……往回追溯,生成并行程序的过程已经被选择性地自动化了。分析步骤已经自动化,以帮助进行分区和映射决策。实际的实现,无论是改进旧代码还是生成新程序,都是手动的(可能由食谱指导)。这里的例外是Target Compiler,但这是一个系统设计过程,包括创建自定义处理器,因此上下文是不同的。

所以……再往前追溯,如果我在决定一辆车和我的手机一起使用时,有这样的工具,他们就会清楚地告诉我,我需要一辆自动变速器,这样我就不会发现自己在人行道上被改变了语意。但这些工具不会帮我开车。

是的,我想我可以接受有限的自动化。

注:还有一家名为Compaan的公司也在这个领域做类似的工作,但在本文付印之前,他们无法向我提供任何信息。

坦白地说,我以前是Vector Fabrics的执行团队成员,很久以前,我需要一个关于产品现状的简报。

更多信息:

棱镜

目标编译器

vfEmbedded

留下回复

有特色的博客
2023年1月6日
在Cadence的AWR微波办公软件中,数据集是一个强大且易于使用的功能。数据集,顾名思义,存储以前模拟的数据。模拟范围可以从电磁(EM)运行的s参数结果,到谐波平衡ci…
2023年1月5日
了解软件验证和强大的基础设施如何保护汽车OTA更新,以改善联网车辆的ADAS和汽车网络安全。文章如何大规模保护汽车OTA更新首先出现在从硅到软件....
2022年12月28日
我不得不说,其中许多机械运动对我来说都是全新的,从第一个开始,我现在知道它是施密特耦合....
2022年12月20日
作者:James Paris和Armen Asatryan在实现过程中自动进行简短检查,让设计团队快速找到并修复这些错误... ...

有特色的视频

演示:PCIe Gen5 x16运行在VectorPath加速卡上

Achronix

Achronix工程师展示了如何使用Speedster7t FPGA将VectorPath加速卡连接到PCIe Gen5 x16主机,并通过全芯片二维片上网络(NoC)读取/写入GDDR6内存。NoC将数据从任何高速接口以2GHz的速度路由到FPGA内部的核心结构,而不消耗任何FPGA逻辑资源。

点击这里观看更多来自Achronix的视频

特色粉笔谈话亚博里的电子竞技

蓝牙LE音频

逮老鼠的电子产品而且北欧半导体

蓝牙LE音频是当今音频创新的一个突出组成部分。在这一期的Chalk Talk中,来自亚博里的电子竞技北欧半导体公司的Finn Boetius和Amelia Dalton讨论了蓝牙LE音频的内容、位置和方式。他们仔细研究了蓝牙LE音频配置文件,蓝牙LE音频的架构,以及如何开始在您的下一个设计中使用蓝牙LE音频。

点击这里了解更多关于北欧半导体nRF5340多核片上系统(SoC)的信息

Baidu