YunSDR小课堂-AIE编程指南(第55讲)

8. AI Engine Kernel and Graph Programming

使用输入输出缓冲器作为中间存储器

在获取输入或输出缓冲区之后但在释放它之前,缓冲区归内核所有。内核可以负责通过指针或迭代器读取或写入缓冲区,而不会发生数据冲突。下面的代码显示了用于在迭代之间临时存储的异步输出缓冲区的示例:

1.png

缓冲区端口的线性和循环寻址

缓冲器端口可以以线性或循环方式寻址。在线性寻址模式下,数据是线性寻址的,没有回绕。在循环寻址模式下,数据被循环寻址并具有环绕。在同一个瓦片中有余量的内核建议使用循环缓冲区端口。具有非零余量的端口连接需要在消费者内核返回之后在消费者端口处复制余量数据。但是,如果生产者和消费者在同一个核心上,并且您使用循环缓冲区端口,则可以避免边缘复制,从而提高性能。可以使用从data()API获得的指针或使用线性或循环迭代器访问常规缓冲区端口中的数据。线性迭代器的开销比循环迭代器低。

     注:

    ·循环寻址模式仅在一维缓冲区端口中支持。

    ·访问循环缓冲区端口中数据的迭代器必须是循环迭代器。

    ·循环缓冲区端口只能在函数原型中声明。

循环输入缓冲器

下面的示例声明了内核函数k2,输入循环缓冲区in0操作int32数据类型,输出流操作名为out0的int32数据类型。

2.png

循环输出缓冲器

decompression内核函数k1的输入流操作于名为in0的数据类型int32,循环1d输出缓冲区操作于名为out0的数据类型int32。

3.png

重要提示!当内核位于AI引擎中的同一瓦片上时,内存寻址优化成为可能。然而,重要的是要注意,由于这种优化,可能会出现一些限制。例如,如果K1和K2位于相同的瓦片中并且通过输出到输入缓冲器连接,则它们必须使用相同类型的寻址。这意味着它们可以选择线性或循环寻址,但不能两者兼而有之。但是,值得注意的是,在X86模拟期间不会识别此限制,因为它仅模拟AI引擎瓦片和内存的功能方面。有关X86仿真模型的更多详细信息,请参阅AI Engine Tools and Flows User Guide(UG 1076)中的限制。

异步循环缓冲区

decompression内核函数k3,具有异步循环输入一维缓冲区,其对具有在图中指定的缓冲区大小和命名为in0的边距大小MARGIN_SIZE的数据类型int32进行操作,以及对命名为out0的数据类型int32进行操作的输出流。

4.png

内核的缓冲区端口操作


向前移动当前读/写位置

  在下面的描述中,input_buffer<TYPE>代表任何允许的输入缓冲器端口数据类型。同样,output_buffer<TYPE>代表任何允许的输出缓冲区端口数据类型。

5.png


向后移动当前读/写位置

  在下面的描述中,input_buffer<TYPE>和input_circular_buffer<TYPE>代表任何允许的输入缓冲区端口数据类型。同样,output_buffer<TYPE>和output_circular_buffer<TYPE>代表任何允许的输出缓冲区端口数据类型。

6.png


 Buffer Ports与Windows的比较

    在AMD vitis™工具版本2022.1和以前的版本中,内核之间的内存接口被称为窗口。缓冲区端口类似于窗口端口,但不同之处如下所述。缓冲区端口为内核提供了一种对核心内存块进行操作的方法。

7.png


注意事项:对缓冲器端口大小、窗口大小和余量大小的限制取决于硬件约束,因此,缓冲器端口和窗口之间在最小大小方面没有区别。


    图形转换


    带有缓冲区端口到缓冲区端口的连接语句不需要指定大小的模板参数。使用图形中的dimensions()API指定所有输入/输出缓冲区端口的样本数(而不是字节数)。当不使用图中的dimensions()API时,也可以使用内核函数原型指定缓冲区端口大小(样本数,而不是字节数)。

基于窗口的连接示例

8.png

基于缓冲区端口的连接和维示例

9.png


 注意:只能在内核函数原型中指定边距大小。内核转换部分包含内核函数原型和边距示例。上面的示例仅说明了图形代码更新。


     内核转换

    当从基于窗口的内核迁移到基于缓冲区端口的内核时,用户需要确定每个内核的缓冲区端口寻址类型。窗口数据类型实现为循环缓冲区;但是,缓冲区端口类型实现为线性缓冲区,除非声明为循环缓冲区端口类型。下面列出了选择寻址模式的标准。选择循环地址模式的标准如下:

    ·两个内核必须位于相同的瓦片中,并且它们必须彼此直接通信。

    ·使用大于0的边距大小。

    ·内核需要周期性地对数据进行遍历。

    选择线性地址模式的标准如下:

    ·内核位置不保证在同一区块内。

    ·内核不需要任何余量。

    ·额外的边距副本确实会影响设计性能。

    内核转换函数原型的示例

    内核转换的示例如下:

    example1:

    基于窗口的函数原型:


10.png

一维环形缓冲端口函数原型:

11.png


example2:

    基于窗口的函数原型:

12.png

 一维缓冲端口函数原型:

13.png


 注意事项:当继承的大小在函数原型中被指定为缓冲区端口大小时,实际的缓冲区端口大小使用图中的dimensions()API指定。

     内核代码转换

    缓冲区端口不支持读、读推进、读递减、写和写推进API。

    从缓冲区端口访问数据说明了使用指针、迭代器和向量引用访问数据的多种方法。如果内核算法使用向量,建议使用向量迭代器进行向量引用,以使用向量处理器获得最佳和优化的性能。如果内核算法使用标量数据类型,则建议使用迭代器来简化代码,使其可移植,并且与指针引用相比更安全。

    从输入阅读的示例

    窗口读取操作需要转换为输入缓冲区端口迭代器读取。基于向量的操作需要使用向量迭代器。迭代器递增/递减对应于window_readincr()和window_writeincr()操作。

    基于窗口的输入示例:

14.png

  基于缓冲器端口的输入:

15.png

基于窗口的输出示例:

16.png

基于缓冲器端口的输出:

17.png