垂直卷积给 FPGA 首选的串流数据模型带来了难题。数据必须按列访问,但存储整张图像并非上策。解决方案是使用行缓冲器,如下图所示。
图 1. 串流垂直卷积
此处样本同样按串流来读取,但这次从 hls::stream hconv
读取。算法要求读取至少 K-1 行数据,然后才能处理首个样本。在此之前执行的所有计算都将被放弃。
行缓冲器允许存储 K-1 行数据。每次读取新样本时,都会将另一个样本挤出行缓冲器。此处值得注意的是在计算中使用最新样本,然后将此样本存储到行缓冲器中,并将旧样本排出。这样即可确保只需将 K-1 行数据保存在高速缓存中,而不是 K 行数据。虽然行缓冲器确实要求将多行数据存储在本地,但卷积内核大小 K 始终小于完整的视频图像中的 1080 行。
读取第 K 行上的首个样本时即可执行首次计算。随后,该算法会继续输出值,直至读取最后一个像素为止。
// Vertical convolution
VConvH:for(int col = 0; col < height; col++) {
VConvW:for(int row = 0; row < vconv_xlim; row++) {
#pragma HLS DEPENDENCE variable=linebuf type=inter dependent=false
#pragma HLS PIPELINE
T in_val = hconv.read();
T out_val = 0;
VConv:for(int i = 0; i < K; i++) {
T vwin_val = i < K - 1 ? linebuf[i][row] : in_val;
out_val += vwin_val * vcoeff[i];
if (i > 0)
linebuf[i - 1][row] = vwin_val;
}
if (col >= K - 1)
vconv << out_val;
}
}
以上代码会以串流方式再次处理设计中的所有样本。此任务持续运行。使用 hls::stream
构造会强制将数据保存在本地高速缓存中。这是适合用于 FPGA 的理想策略。