存储器模型 - 2023.2 简体中文

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

Document ID
UG1076
Release Date
2023-12-04
Version
2023.2 简体中文

如果内核需将状态从一次调用(迭代)保留至下一次调用,则可使用全局变量或静态变量来存储此状态。含静态存储类的变量(例如,全局变量和静态变量)可能导致 x86 仿真与 AI 引擎仿真之间出现不一致。根本原因在于,对于 x86 仿真,所有内核的源文件都编译到单个可执行文件内,而对于 AI 引擎仿真,以 AI 引擎为目标的每个内核都独立编译。因此,如果含静态存储类的变量被两个内核引用,并且这些内核映射到同一个 AI 引擎,那么 x86 仿真与 AI 引擎仿真共享此变量。但如果这些内核映射到不同 AI 引擎,那么对于 x86 仿真,仍共享该变量,但对于 AI 引擎仿真,每个 AI 引擎都有其自己的副本,无共享。如果该变量供内核读取和写入,那么这就会导致 x86 仿真与 AI 引擎仿真之间出现不匹配。

要跨内核迭代延续建模状态,首选方法是使用 C++ 内核类(请参阅 AI 引擎内核与计算图编程指南 (UG1079) 中的 C++ 内核类支持)。这样可以避免含静态存储类的变量的缺陷。或者,可将全局变量或静态变量的存储类更改为 thread_local,但这仅适用于 x86 仿真。在此情况下,x86 仿真中的内核的每个实例都有其自己的变量副本。这样如果使用的变量映射到不同的 AI 引擎,即可与 AI 引擎仿真的行为相匹配。在以下示例中,内核通过全局变量 delayLine 和静态变量 pos 跨内核迭代延续状态。这导致如有多个内核实例使用此源文件,x86 仿真与 AI 引擎仿真之间就会出现不匹配。通过将这些变量的存储类更改为 thread_local 即可避免此问题。

原始内核源代码:

// fir.cpp
#include <adf.h>
using namespace adf;
cint16 delayLine[16] = {};
void fir(input_buffer<cint16> *in1,
         output_buffer<cint16> *out1)
{
  static int pos = 0;
..
}

重做的内核源代码:

// fir.cpp
#include <adf.h>

#ifndef __X86SIM__
cint16 delayLine[16] = {};
#else
thread_local cint16 delayLine[16] = {};
#endif
void fir(input_buffer<cint16> *in1,
         output_buffer<cint16> *out1)
{
using namespace adf;
#ifndef __X86SIM__
  static int pos = 0;
#else
  static thread_local int pos = 0;
#endif
..
}
另一种可能是使用 X86SIM_THREAD_LOCAL 宏,使全局读/写线程安全。该宏在 adf.h 中定义,如下所示:
#ifdef _X86SIM_
#define X86SIM_THREAD_LOCAL thread_local
#else
#define X86SIM_THREAD_LOCAL
#endif
这使其定义为仅适用于 X86 仿真。
前述代码简化如下:
// fir.cpp
#include <adf.h>

X86SIM_THREAD_LOCAL cint16 delayLine[16] = {};

void fir(input_buffer<cint16> *in1,
         output_buffer<cint16> *out1)
{
using namespace adf;
static X86SIM_THREAD_LOCAL int pos = 0;
..
}