水平卷积 - 2021.2 Chinese

Vitis 高层次综合用户指南 (UG1399)

Document ID
UG1399
Release Date
2021-12-15
Version
2021.2 Chinese

为了提升 FPGA 实现的计算执行效率,采用下图所示方式来计算水平卷积。

图 1. 水平卷积串流

使用 hls::stream 可强制采用高效的算法实践,迫使您首先读取第一个样本,而不是对数据执行随机访问。该算法必须使用前 K 个样本来计算卷积结果,因此它将该样本复制到临时高速缓存 hwin 中。对于第一次计算,hwin 中没有足够的值用于计算结果,因此不写入任何输出值。

该算法会持续读取输入样本,并将其缓存到 hwin 中。读取每个新样本时,都会从 hwin 移除不需要的样本。读取第 K 个输入后,才能首次写入输出值。现在即可写入输出值。

该算法会沿各行按此方式继续操作,直至读取最后一个样本为止。届时,在 hwin 中仅存储最后 K 个样本:即计算卷积所需的全部样本。

执行这些操作的代码如下所示:

// Horizontal convolution 
 HConvW:for(int row = 0; row < width; row++) {
 HconvW:for(int row = border_width; row < width - border_width; row++){
 T in_val = src.read();
 T out_val = 0;
 HConv:for(int i = 0; i < K; i++) {
    hwin[i] = i < K - 1 ? hwin[i + 1] : in_val;
    out_val += hwin[i] * hcoeff[i];
 }
 if (row >= K - 1)
    hconv << out_val;
 }
}

以上代码中值得注意的是,它使用临时变量 out_val 来执行卷积计算。执行计算前,此变量设置为 0,无需耗费 2 百万个时钟周期来复位这些值,如前例中所示。

在整个流程中,src 输入中的样本以光栅串流方式来处理。逐一读取每个样本。任务输出将被放弃或使用,但任务将持续运行计算。这表示此代码与专为在 CPU 上执行而编写的代码不同。

在 CPU 架构中,通常会避免条件操作或分支操作。当程序需要分支时,会丢失 CPU 提取流水线中存储的所有指令。在 FPGA 架构中,硬件中针对每个条件分支已存在一条独立路径,并且在流水打拍任务内不存在与分支相关联的性能惩罚。只需选择要使用哪个分支即可。

输出存储在 hls::stream hconv 中以供垂直卷积循环使用。