目录
1. 简介
2. 基础 kernel
2.1 pass kernel
2.2 double_pass kernel
2.3 add_kernel
2.4 split kernel
3. 三种bypass
3.1 input_bypass
3.2 middle_bypass
3.3 output_bypass
4. 总结
1. 简介
本文展示三个在数据流水线中常见的问题:
- 输入参数绕过了第一个函数,导致数据流水线性能下降。
- 数据流内部的通道不是前馈的,绕过了任务,导致性能下降。
- 数据流通道输出没有正确处理,导致性能下降。
2. 基础 kernel
首先引入四个通用 HLS kernel 函数作为后续演示的基础:
2.1 pass kernel
void pass(int a[128], int tmp1[128]) {
for (int i = 0; i < 128; i++) {
tmp1[i] = a[i];
}
}
参数1 -> 参数2
2.2 double_pass kernel
void double_pass(int b[128], int tmp2[128], int tmp1[128], int tmp4[128]) {
for (int i = 0; i < 128; i++) {
tmp2[i] = b[i];
tmp4[i] = tmp1[i];
}
}
参数1 -> 参数2
参数3 -> 参数4
2.3 add_kernel
void add_kernel(int tmp1[128], int tmp2[128], int tmp3[128]) {
for (int i = 0; i < 128; i++) {
tmp3[i] = tmp1[i] + tmp2[i];
}
}
参数1 + 参数2 -> 参数3
2.4 split kernel
void split(int a[128], int tmp1[128], int tmp2[128]) {
for (int i = 0; i < 128; i++) {
tmp1[i] = a[i];
tmp2[i] = a[i];
}
}
参数1 -> 参数2
参数1 -> 参数3
3. 三种bypass
3.1 input_bypass
void dut(int a[128], int b[128], int tmp3[128]) {
#pragma HLS DATAFLOW
int tmp1[128], tmp2[128], tmp4[128];
pass(a, tmp1);
double_pass(b, tmp2, tmp1, tmp4);
add_kernel(tmp4, tmp2, tmp3);
}
优化后:
void dut(int a[128], int b[128], int tmp3[128]) {
#pragma HLS DATAFLOW
int tmp1[128], tmp2[128], tmp4[128];
int tmp5[128];
pass(a, b, tmp1, tmp2);
Double_pass(tmp2, tmp1, tmp4, tmp5);
add_kernel(tmp4, tmp5, tmp3);
}
对比:
a -> tmp1 -> tmp4
+ --> tmp3
b -> tmp2
a -> tmp1 -> tmp4
+ --> tmp3
b -> tmp2 -> tmp5
3.2 middle_bypass
void dut(int a[128], int b[128], int tmp3[128]) {
#pragma HLS DATAFLOW
int tmp1[128], tmp2[128], tmp4[128];
double_pass(a, b, tmp1, tmp2);
pass(tmp2, tmp4);
bypass(tmp1, tmp4, tmp3);
}
优化后:
void dut(int a[128], int b[128], int tmp3[128]) {
#pragma HLS DATAFLOW
int tmp1[128], tmp2[128], tmp4[128], tmp5[128];
double_pass(a, b, tmp1, tmp2);
pass(tmp2, tmp4, tmp1, tmp5);
bypass(tmp5, tmp4, tmp3);
}
对比:
a -> tmp1 ------>
+ --> tmp3
b -> tmp2 -> tmp4
a -> tmp1 -> tmp5
+ --> tmp3
b -> tmp2 -> tmp4
3.3 output_bypass
void dut(int a[128], int b[128], int tmp2[128]) {
#pragma HLS DATAFLOW
int tmp1[128], tmp3[128];
split(a, tmp1, tmp2);
pass(tmp1, b);
}
优化后:
void dut(int a[128], int b[128], int tmp2[128]) {
#pragma HLS DATAFLOW
int tmp1[128], tmp3[128];
split(a, tmp1, tmp3);
pass(tmp3, tmp2, tmp1, b);
}
对比:
a -> tmp1 -> b
a -> tmp2
a -> tmp1 -> b
a -> tmp3 -> tmp2
4. 总结
本文展示了在数据流水线中常见的三个输入参数绕过问题及其解决方案。通过引入四个基础的HLS kernel函数:pass、double_pass、add_kernel和split,演示了input_bypass、middle_bypass和output_bypass三种问题的具体情形及优化后的解决方案。优化后的代码通过重新排列数据流通道,使得数据流遵循前馈路径,提高了性能。