HERA异构系统设计:让FPGA像CPU/GPU一样易用的系统级方案
1. 项目概述为什么我们需要HERA这样的异构系统设计方法在过去的几十年里我们见证了计算性能的指数级增长这主要归功于摩尔定律和登纳德缩放定律的持续生效。然而随着晶体管尺寸逼近物理极限这两大定律的效应正在显著放缓。单纯依靠提升CPU主频或增加核心数量已经难以满足现代应用对计算性能和能效日益增长的需求。这就好比在城市交通中仅仅增加更多的同类型小汽车CPU核心并不能解决拥堵问题反而可能因为道路内存带宽、功耗墙的限制而加剧矛盾。于是异构计算架构应运而生成为破局的关键。其核心思想是“让专业的硬件做专业的事”。CPU擅长处理复杂的、分支众多的通用任务好比城市里的出租车灵活但载客量有限GPU则专精于大规模数据并行计算好比公交车一次能运送大量乘客但路线固定而像FPGA这样的可重构逻辑则扮演着“定制化特种车辆”的角色。它既不像ASIC那样“焊死”了功能灵活性差也不像GPU那样架构固定在某些特定任务上能效比不高。FPGA可以通过编程在硬件层面为特定算法“量身定制”一条最优的数据通路从而实现极高的能效和性能。听起来很美好对吧但现实是FPGA在通用计算领域的普及远不如GPU。根本原因在于其极高的使用门槛。传统的FPGA开发流程是怎样的你需要精通硬件描述语言如Verilog/VHDL理解时钟、时序、资源布局等底层硬件概念然后经历漫长的综合、布局布线过程生成一个比特流文件最后再通过特定的驱动和API将其加载到硬件上执行。这个过程与主流的软件开发范式写C、Python然后编译运行格格不入。一个软件开发者想要利用FPGA加速其应用几乎需要从头学习一套全新的技能树这严重阻碍了其广泛应用。因此当前异构计算领域面临的核心矛盾是我们拥有FPGA这样强大的、灵活的硬件加速器却缺乏一种能让广大软件开发者像使用CPU和GPU一样轻松、安全、高效地使用它的系统级方法。现有的解决方案要么只关注某个子问题比如如何用高级语言描述硬件要么只适用于特定的、封闭的环境如云端独占实例无法满足通用计算场景下多用户、多应用、动态负载的需求。HERA方法论正是为了系统性地解决这一矛盾而提出的。它不是一个具体的工具或库而是一套完整的设计哲学和系统架构蓝图。其核心目标是在通用计算系统中为可重构逻辑如FPGA构建一个与CPU、GPU平起平坐的、易于访问且安全的“一等公民”地位。它借鉴并扩展了已在GPU领域取得成功的ROCm生态系统及其背后的HSA异构系统架构标准旨在打造一个从应用程序到硬件执行的“端到端”统一平台。2. HERA方法论的核心设计思路拆解HERA的愿景是让FPGA的使用体验无限接近CPU和GPU。为了实现这一点它必须解决几个根本性的系统级挑战。我们可以将其拆解为三个层次的需求对开发者友好、对系统运行时友好、对系统管理员安全友好。2.1 开发者视角如何让编程像写CPU代码一样简单对于开发者而言理想的情况是我写一段标准的、描述并行计算的代码比如一个for循环编译器或运行时环境能自动判断并选择最合适的硬件CPU、GPU或FPGA来执行它而我无需关心底层是哪种硬件。2.1.1 统一的编程模型与单源编程HERA方法论坚定地拥抱了“单源编程”范式。这意味着加速代码内核和主机代码写在同一个源文件中使用熟悉的语言和并行框架。论文中重点提到了三种方式OpenMP指令通过在循环前添加#pragma omp target这样的编译制导语句告诉编译器这部分代码可以卸载到加速器执行。C Parallel STL直接使用C17标准中的并行算法如std::for_each(std::execution::par, ...)由运行时库决定在何处执行。OpenCL虽然它需要明确区分主机和设备代码但其作为开放的异构计算标准拥有广泛的生态HERA也提供支持。关键在于无论采用哪种方式源代码本身不包含任何特定于FPGA的优化指令如HLS编译指示。这保证了代码的可移植性。同一份代码可以在只有GPU的系统、只有FPGA的系统或两者都有的系统上编译运行由运行时根据硬件可用性和性能预测自动选择最佳执行目标。2.1.2 系统共享虚拟内存这是降低编程复杂度的另一个关键。在传统的GPU或FPGA加速模型中开发者必须手动管理主机内存和设备内存之间的数据拷贝。你需要显式地分配设备缓冲区将数据从主机内存复制过去计算完成后再复制回来。对于复杂的数据结构如指针丰富的链表、树这简直是噩梦。HERA通过实现系统共享虚拟内存来解决这个问题。其原理是CPU和加速器包括FPGA共享同一套虚拟地址空间。当FPGA上的加速器内核需要访问某个内存地址时它发出的请求会经过一个IOMMU输入输出内存管理单元。IOMMU将这个虚拟地址翻译成物理地址并检查访问权限。这意味着开发者可以直接将主机程序中的指针传递给FPGA内核内核可以直接通过这个指针读写数据就像CPU线程一样。这彻底消除了显式数据拷贝的需要极大地简化了编程模型并使得加速复杂数据结构成为可能。2.1.3 设备无关的二进制中间表示为了保护知识产权和实现真正的“一次编译到处运行”HERA要求编译器将设备代码内核编译成一种设备无关的中间表示例如HSAIL或SPIR-V。这个中间表示会被嵌入到最终的可执行文件中。当应用程序在目标机器上运行时运行时系统会检测可用的硬件加速器。如果发现有FPGA它会调用一个“最终化器”将这个中间表示即时编译成针对当前系统上具体FPGA型号和配置的比特流。这个过程对开发者完全透明。他们分发的是一个通用的二进制程序而不是一堆针对不同FPGA的预编译比特流后者会极大地增加软件包体积。2.2 系统运行时视角如何高效、公平地管理稀缺的FPGA资源在个人工作站或部门服务器上FPGA通常只有一块甚至只有一部分逻辑资源可用。如何让多个用户、多个应用共享这一块FPGA就像共享CPU和GPU一样2.2.1 硬件虚拟化与动态部分重配置这是HERA运行时系统的核心。它将FPGA的物理资源划分为两部分静态Shell这是一个固定不变的硬件逻辑区域包含了系统管理、任务调度、内存管理、安全监控等基础功能。可以把它想象成FPGA上的“操作系统内核”。动态可重构分区这是留给用户加速器内核在HSA术语中称为“角色”使用的区域。系统可以动态地将不同的比特流加载到这些分区中。HERA的硬件调度器称为“包处理器”负责管理来自多个进程的加速请求。当一个进程请求执行某个内核时调度器会检查对应的“角色”是否已经加载到某个可重构分区中。如果没有且所有分区都已占用它会根据LRU最近最少使用等策略选择一个分区进行动态部分重配置将旧的角色换出加载新的角色。2.2.2 透明的比特流缓存与合成管理FPGA的“编译”即综合、布局布线过程非常耗时可能长达数分钟甚至数小时。HERA引入了一个系统级的守护进程——合成管理服务。它的工作流程如下当某个应用程序第一次请求某个内核时SSM会接管这个请求。SSM使用集成的HLS工具将设备无关的中间表示转换为针对当前FPGA Shell配置的硬件描述语言如VHDL/Verilog。然后它调用后端工具链如Xilinx Vivado进行逻辑综合和布局布线生成最终的比特流。生成的比特流会被计算一个哈希值并存储在一个系统级的缓存中。后续任何用户、任何应用请求同一个内核时SSM会直接返回缓存中的比特流完全跳过耗时的合成过程。这个机制极大地提升了用户体验。对于像BLAS、TensorFlow这样的常用库其内核只需在系统生命周期内合成一次之后所有用户都能受益。2.2.3 基于队列的直接任务分发为了追求极低的任务分发延迟HERA采用了HSA标准定义的机制应用程序通过驱动在用户空间内存中创建异步队列。任务以特定格式的包AQL包形式写入队列。然后应用程序通过“门铃”机制通知硬件调度器。关键点在于硬件调度器可以直接从用户空间内存中读取任务包无需经过操作系统内核的上下文切换。这大大减少了任务启动的开销。调度器解析包内容将任务分发给对应的已加载的加速器核心执行并在完成后更新完成信号。这种机制使得FPGA任务分发的延迟可以降低到微秒级与GPU处于同一水平。2.3 安全与管理员视角如何防止“捣蛋”的硬件逻辑给予用户直接配置硬件电路的能力是一把双刃剑。一个恶意的或存在缺陷的比特流可能会通过DMA操作破坏系统内存发起总线攻击导致系统死锁甚至通过侧信道攻击窃取其他进程的数据。HERA必须构建严密的安全防线。2.3.1 信任边界与硬件隔离HERA将整个系统划分为不同的信任域不可信域用户提供的加速器“角色”逻辑。这些逻辑可以做任何事因此必须被严格隔离。可信域静态Shell中的所有组件包括包处理器、系统管理器、总线架构等。这些由系统管理员验证和部署是安全的基础。2.3.2 系统守卫与地址空间管理每个可重构分区与Shell之间的数据通路AXI总线上都放置了一个系统守卫。它的职责是实时监控所有进出分区的总线事务检查协议合规性。如果发现异常事务例如试图访问未授权的内存地址、违反总线握手协议系统守卫会立即终止该分区的所有活动并向系统报告错误。地址空间管理器则负责为每个总线主设备即每个加速器核心分配一个进程地址空间ID。所有从加速器发出的内存访问请求都会带上这个PASID。IOMMU会根据这个ID使用对应进程的页表进行地址翻译和权限检查。这样一个进程的加速器内核无法访问另一个进程的内存空间实现了进程间隔离。2.3.3 比特流认证与防篡改为了防止用户上传恶意构造的、试图绕过区域边界或破坏Shell逻辑的比特流HERA引入了比特流认证机制。SSM在合成比特流后会使用一个只有管理员知道的密钥为比特流生成一个基于哈希的消息认证码。驱动在加载任何比特流之前都会验证这个HMAC。只有通过验证的、由受信任的SSM生成的比特流才能被加载到FPGA上。这从根本上防止了用户直接注入任意硬件逻辑。2.3.4 对抗拒绝服务与资源滥用即使有了上述保护用户仍然可能通过编写无限循环的内核或者发起海量内存请求来耗尽FPGA或内存资源。HERA的应对策略包括任务抢占与终止系统管理员或具有特权的监控进程有权强制终止运行在FPGA上的特定任务而不影响其他任务。资源配额可以对用户或进程设置资源使用上限。访问控制通过Linux用户组权限限制只有受信任的用户才能使用FPGA加速和SSM合成服务。3. HERA系统实现的关键技术与实操要点理解了设计思路我们来看看HERA是如何具体实现的。论文基于Xilinx Zynq UltraScale MPSoC和Virtex UltraScale平台构建了原型系统其软件栈和硬件架构紧密耦合共同支撑起上述所有特性。3.1 硬件架构设计从Shell到角色HERA的FPGA硬件设计遵循一个清晰的层次结构如下图所示概念图----------------------------------------------------------------------- | 应用软件 (Application) | ----------------------------------------------------------------------- | OpenMP | C PSTL | OpenCL | ... (语言运行时与用户绑定) | ----------------------------------------------------------------------- | HSA运行时库 (ROCR) 设备抽象层 (ROCT) | ----------------------------------------------------------------------- | 合成管理服务 (SSM) | 内核驱动 (HPPD) | ----------------------------------------------------------------------- | Linux 内核 | ----------------------------------------------------------------------- | 硬件FPGA (Shell 可重构分区) | -----------------------------------------------------------------------3.1.1 静态Shell的构成Shell是FPGA上永不改变的部分是系统的基石包含以下关键组件包处理器通常由一个嵌入式软核如MIPS实现。它是硬件调度器负责解析AQL任务包、管理任务队列、触发角色重配置、与驱动通信。它运行在可信域是连接软件和硬件角色的桥梁。系统管理器一个简单的状态机负责管理芯片状态、处理来自驱动的特权命令如初始化、重配置请求、更新ASM中的PASID映射。它通过一条独立的、与数据总线隔离的命令总线与驱动通信防止被用户逻辑篡改。系统守卫每个可重构分区入口处都有一个。它持续监控AXI总线检查事务地址范围、协议信号如VALID/READY是否合规超时处理等。一旦检测到攻击或错误立即隔离该分区。地址空间管理器位于Shell内部总线交叉开关之前。它维护着一个从“总线主设备ID”到“PASID”的查找表。当包处理器调度一个新任务到某个加速器核心时会通过系统管理器更新ASM中的映射确保该核心发出的所有内存访问都带有正确的进程标识。3.1.2 可重构分区与角色这是留给用户加速器逻辑的区域。HERA的SSM会根据管理员的配置例如“创建2个可重构分区”在综合Shell时预留出相应数量和尺寸的“空位”。当应用程序请求执行某个内核时SSM合成的就是这个内核的硬件电路角色其比特流正好能严丝合缝地加载到这些预留分区中。3.1.3 内存子系统集成对于像Zynq MPSoC这样的片上系统CPU和FPGA通过一致性互连如ARM的CCI连接。HERA Shell通过AXI ACE或AXI HP端口连接到这个互连上从而天然支持缓存一致性和系统共享虚拟内存。CPU和FPGA可以共享同一份数据无需软件维护一致性极大简化了编程。 对于PCIe加速卡实现SSVM和缓存一致性更为复杂需要硬件支持PCIe ATS、PASID等特性。HERA的设计也考虑了这种场景在Shell中集成了必要的MMU和DMA引擎。3.2 软件栈实现从应用到驱动3.2.1 内核驱动HERA的FPGA驱动与AMD的GPU驱动共享相同的HSA Linux内核用户空间API。这使得上层运行时无需修改就能同时管理GPU和FPGA。驱动的主要职责包括设备发现与初始化通过sysfs暴露设备信息。进程地址空间管理与IOMMU/SMMU驱动协作为每个使用FPGA的进程绑定唯一的PASID并共享其页表。比特流生命周期管理接收来自SSM的、经过认证的比特流在FPGA管理器的帮助下执行动态部分重配置。异常处理接收来自硬件如系统守卫的中断处理内存访问违规、总线错误等并向违规进程发送信号如SIGSEGV。3.2.2 用户空间运行时与SSMROCm运行时库为应用程序提供了统一的HSA API。当应用程序调用hsa_finalize_agent来为FPGA准备内核时会发生以下事情运行时库将设备无关的中间代码发送给SSM守护进程通过Unix域套接字。SSM检查缓存。若未命中则启动HLS和综合流程生成比特流计算HMAC存入缓存。SSM将比特流文件路径返回给运行时库。运行时库通过驱动注册该比特流并获得一个唯一的内核句柄。此后应用程序使用该句柄提交任务时驱动和硬件就知道该加载哪个比特流了。3.2.3 语言前端集成这是让开发者无感知的关键。以GCC的OpenMP为例其工作流程是开发者编写带有#pragma omp target的C/C代码。GCC编译器在编译时识别这些编译制导语句将标记的代码区域提取出来。主机端的循环被替换为一系列HSA运行时API调用如创建队列、设置参数、分发任务。设备端代码被编译成HSAIL中间表示并嵌入到最终的可执行文件中。应用程序运行时HSA运行时库根据硬件情况调用相应的最终化器对GPU是编译成GCN ISA对FPGA是调用SSM合成比特流。3.3 性能与开销分析论文中的原型测试揭示了HERA系统各个环节的开销这对于评估其实用性至关重要。3.3.1 任务分发延迟在Zynq MPSoC平台上从CPU提交一个空任务包到收到完成信号端到端延迟仅为11微秒。这比之前一些研究中的方案185微秒快了一个数量级。这主要归功于HSA的内存映射队列和门铃机制使得任务提交完全绕过了操作系统内核调用实现了用户空间到硬件的直接通信。3.3.2 角色注册与重配置开销这是FPGA特有的开销。将一个新的比特流注册到驱动从磁盘加载到内核内存大约需要25-35毫秒取决于存储速度。动态部分重配置一个分区大约需要6-7毫秒。这些是“一次性”或“低频次”开销。一旦角色被注册并加载到FPGA上后续成千上万次的任务分发都只有微秒级的延迟。SSM的缓存机制确保了同一个内核在系统范围内只需合成和注册一次。3.3.3 内存访问开销启用系统共享虚拟内存和缓存一致性会引入一定的延迟。在Zynq MPSoC上由于Xilinx的缓存一致性互连实现效率问题实测内存带宽会受到一定影响读带宽约为理论值的74%写带宽为84%。不过对于大多数计算密集型内核计算本身是瓶颈这个开销在可接受范围内。更重要的是它换来了编程模型的极大简化和对复杂数据结构的支持这个权衡通常是值得的。3.3.4 加速效果尽管原型系统的HLS工具链还不成熟且未使用任何手工优化指令测试的几种基础算法向量加、矩阵乘、Stencil计算、二叉树遍历等在FPGA上仍然取得了显著的加速比。例如某些内核的每周期工作项吞吐量相比纯CPU执行提升了数倍。这证明了即使使用完全自动化的高级综合FPGA也能为合适的负载带来性能收益。随着HLS工具的进步和更优化内核的加入潜力会更大。4. 实战启示与未来展望通过深入剖析HERA方法论我们可以得到许多对异构计算系统设计特别是FPGA集成具有普遍指导意义的启示。4.1 核心理念以软件生态为中心HERA的成功不在于发明了某种新的硬件而在于它以现有的、成功的软件生态ROCm/HSA为中心逆向设计硬件和底层系统软件来满足生态的需求。它没有要求开发者学习新语言或新API而是让FPGA去适应开发者已有的习惯OpenMP、C PSTL。这是技术能否被广泛采纳的关键。4.2 安全必须作为首要设计原则而非事后补丁HERA从硬件架构的顶层就开始规划安全。系统守卫、地址空间管理器、比特流认证这三道防线构成了纵深防御体系。它清晰地认识到在通用计算环境中用户提供的硬件逻辑与恶意软件在本质上没有区别必须被同等对待和严格隔离。任何试图将FPGA“暴露”给多用户环境的系统都必须认真考虑这套安全模型。4.3 虚拟化与资源共享是通用化的必由之路FPGA资源是昂贵且稀缺的。HERA通过动态部分重配置和基于需求的资源分配实现了FPGA逻辑资源的细粒度时分复用。一个进程不能独占FPGA而不使用它这提高了资源利用率。透明的比特流缓存和集中式合成管理则将耗时的综合过程从用户路径中移除转化为系统级的后台服务极大地改善了用户体验。4.4 挑战与未来方向HERA原型也揭示了一些挑战HLS工具链的成熟度自动生成的硬件电路质量目前仍与手工优化的设计有差距。未来需要更智能的、能自动进行设计空间探索的HLS工具。重配置时间尽管毫秒级在多数场景可接受但对于超低延迟应用仍是瓶颈。下一代FPGA器件需要更快的配置接口和部分重配置速度。硬件成本静态Shell消耗了一定的FPGA资源在原型中约占15%。随着FPGA容量增长这部分开销占比会减小但对于小容量器件仍需精打细算。4.5 个人体会与建议在我多年的高性能计算和异构加速开发生涯中深感易用性与强大能力之间的鸿沟是阻碍技术普及的最大障碍。HERA方法论为我们指明了一条切实可行的道路通过严格的系统级抽象、统一的标准接口和周密的安全设计将硬件的复杂性封装起来把简单留给开发者。对于想要构建类似系统的团队我的建议是拥抱标准不要自己发明一套新的编程模型或API。尽可能基于像HSA、SYCL、OpenCL这样的开放标准这样可以最大限度地利用现有生态和开发者知识。分层解耦清晰划分硬件Shell、驱动、运行时、语言前端的职责。确保各层之间接口稳定便于独立演进和替换例如换用更好的HLS工具或新的FPGA型号。安全左移在架构设计的第一天就把威胁建模和缓解措施纳入考虑。硬件隔离、权限最小化、输入验证这些原则在可重构计算领域同样至关重要。性能分析驱动优化像HERA论文中那样细致地测量和分析每一个环节的开销任务分发、重配置、内存访问。优化往往来自于对关键路径的深刻理解而不是盲目猜测。HERA不仅仅是一个学术原型其理念与AMD/Xilinx联合推出的技术预览方向一致预示着工业界正在朝着这个方向迈进。随着芯片制程演进放缓异构计算已成为必然趋势。而让可重构逻辑真正融入通用计算的主流需要的就是像HERA这样兼具远见卓识和工程务实精神的系统级解决方案。它拆除了横亘在软件开发者与强大硬件加速能力之间的高墙让“定制计算”的民主化成为可能。