存储器停滞分析 - 2023.2 简体中文

AI 引擎工具和流程用户指南 (UG1076)

Document ID
UG1076
Release Date
2023-12-04
Version
2023.2 简体中文
AI 引擎可在每个周期内执行多次矢量加载或存储操作。但这些操作必须以不同存储体为目标才能并行执行加载或存储操作。如果在同一周期内多次访问同一存储体,就会发生存储器停滞。

存储器种类包括内核、RTP 缓冲器与系统存储器之间的窗口缓冲器和 DMA FIFO。系统存储器包括前 32 字节、栈和堆之间的内核同步信息。静态变量位于堆内,而函数控制逻辑则位于栈内。系统存储器占据连续存储体。工具可以在特定存储体上自动或手动完成窗口缓冲器、RTP 缓冲器、DMA FIFO 和系统存储器的布局。为缓解这些存储器之间的存储器停滞,请尝试尽可能将其布局到独立存储体内。但如果无法为所有存储器都找到独立的存储体,或者在同一个存储器上发生多次访问,那么仍可能发生存储器停滞。

总之,编译器会尝试尽可能在同一个周期内调度多次存储器访问,但也存在例外情况。源自同一指针的多次存储器访问调度为在不同周期内执行。如果编译器在同一个周期内对多个变量或指针调度执行多项操作,则可能发生存储体冲突。每个存储体都有其自己的仲裁器用于在所有请求之间执行仲裁,且仲裁采用循环方式执行。解决所有请求后,就会释放存储器停滞。

您可通过“Performance Metrics”(性能指标)分析来识别是否需要对存储器停滞执行分析。

  1. 选择Trace(追踪)视图。
  2. 选择Memory Stalls(存储器停滞)表。
    图 1. Trace视图中的“Memory Stall”

    此处停滞名为 MS_<NUM>。编号随时间增加。每次停滞都包含下列关联信息。

    NAME(名称)
    存储器停滞 ID。停滞发生时间越早,编号越小。此编号在所有类型的停滞中都是唯一的。
    Stalled Tile(停滞的拼块)
    已停滞的内核所在的 AI 引擎 tile。
    Stalled Kernel(停滞的内核)
    已停滞的内核。此内核名为 <Kernel_function_name>.<Schedule_ID>.<Graph_instance_name>。有时,它显示为 _main,随后,需通过交叉探测来查找实际的内核函数。
    Start (ps)(开始 (ps))
    发生停滞的开始时间
    Duration (ps)(持续时间 (ps))
    停滞的持续时间。
    PC
    发生停滞时的程序计数器。
    Bank Conflict(存储体冲突)
    发生停滞的存储器。
    Buffer 1Buffer 2Buffer 3
    导致存储器停滞的缓冲器。可能仅有一个缓冲器,也可能有多个缓冲器导致停滞。
  3. 单击Stalls(停滞)视图中的每一行停滞时,它会转至Trace(追踪)视图中存储器停滞的起始位置。通过缩放Trace(追踪)视图即可观察存储器停滞的发生频率,以及运行中的内核中发生停滞的位置。
    注释: 如果在运行中的内核中重复发生大量存储器停滞,这表明停滞可能循环发生。最好对此问题进行调查并解决。如果仅在内核开始运行时发生一次存储器停滞,或者在内核运行期间仅发生少量停滞,通常可将其忽略。根据导致停滞的缓冲器名称可以识别出导致停滞的是窗口缓冲器、系统缓冲器或其他缓冲器。如果是可在计算图中加以控制的窗口缓冲器或 RTP 缓冲器,那么可以使用约束对其进行手动布局,前提是能够找到更好的布局方法。如果是系统存储器(名为 system<NUM>+<NUM>),则需识别停滞中所涉及的变量。
  4. 单击特定停滞对应的行,然后切换至Events(事件)视图。
    图 2. “Memory Stall”的Events视图
  5. Events视图可显示器件中发生的事件。发生存储器停滞的周期会高亮显示。您可看到发生 DM_BANK_CONFLICT 事件的 tile(拼块),以及正在读取或写入的数据。
  6. 请尝试浏览停滞周期之前或之后的其他周期以寻找线索。

    在某些情况下,该工具会调度为在某一周期内同一个 bank 上读取或写入变量。在 AI 引擎内核与计算图编程指南 (UG1079) 的“含虚拟资源注解的加载和存储”中记录了一种解决方案。例如,重定义指向这些变量,并为其添加注解 __aie_dm_resource_a。代码示例如下所示:

    const v8cint16 __aie_dm_resource_a* __restrict coeff = (v8cint16 __aie_dm_resource_a*) eq_coef0; const v8cint16 coe = *coeff;
    v16cint16 __aie_dm_resource_a* __restrict p_buff = (v16cint16 __aie_dm_resource_a*) &delay_line; v16cint16 buff=*p_buff;

下表列出了导致存储器停滞的部分可能场景以及可能的解决方案。

表 1. 存储器停滞场景和解决方案
来源 目标 停滞类型 可能的解决方案 注释
单个内核 单个存储体上的缓冲器 存储器停滞
  • 将存储器分派至不同存储体(存储器包括系统存储器、RTP、窗口缓冲器、DMA 和 FIFO)。请参阅 存储器停滞
  • 利用虚拟存储器注解来为编译器调度提供指引。请参阅 AI 引擎内核与计算图编程指南 (UG1079) 中的“含虚拟资源注解的加载和存储”部分

单个内核访问同一存储体上的多个存储器。

或者,单个内核对同一存储体上的单个存储器进行多次访问。

(每个周期均可包含两次加载和一次存储)

相邻 AI 引擎 tile 上的多个内核 单个存储体上的多个缓冲器 存储器停滞
  • 将存储器分派至不同存储体(存储器包括系统存储器、RTP、窗口缓冲器、DMA 和 FIFO)。
  • BufferOptLevel。请参阅 映射器和布线器选项
  • 如果存储体耗尽,请执行剖析和 AI 引擎停滞分析,寻找内核执行时间更短或者停滞比例更低的更优解决方案。
多个内核访问同一存储体上的多个存储器。