方案一
- 方案一 源码
1 |
|
- 方案一 kernel 设置
- 方案一 综合结果
- 方案一 HLS log 文件
- 方案一 Performance图
方案二(修改gmem位宽为64bit)
- 方案二 kernel 设置
- 为何为64bit?
首先,源码中对外层loop_1
进行pipeline,因此对于内层的loop_2
自动进行uroll展开。内层for循环的边界为J_CNT = 2
因此将loop_2
代码
展开为如下代码形式。因此需要对a
和b
进行两次读取,对a
请求一次读入,对b
请求一次读入。一拍只能对gmem请求一次,因为是并行执行因此a
有两个数据a[i * J_CNT + 0]
和a[i * J_CNT + 1]
需要读入所以接口位宽为sizeof(int) * 2
。
对于代码来说gmem
位宽应该等于sizeof(int) * J_CNT
1 | // loop_2 uroll 展开过程 |
- 方案二 综合结果
- 方案二 HLS log文件
- 方案二 Performance图
方案二 II = 2 原因分析
- 修改源码,解决gmem ii = 2 问题(屏蔽掉b向arrayB赋值)
1 |
|
- 综合结果分析
- HLS log文件
- Performence图
- 为何源程序 II = 2?
该问题还要从loop_2
unroll说起
1 | // loop_2 uroll 展开过程 |
关键原因是一拍只能对gmem
请求一次 因为是并行执行因此第一拍对gmem
进行a
的读请求,a
有两个数据a[i * J_CNT + 0]
和a[i * J_CNT + 1]
需要读入,同理下一拍对gmem
进行b
的请求,b
有两个数据b[i * J_CNT + 0]
和b[i * J_CNT + 1]
需要读入。
因此解决办法也不言而喻:一个gmem
只能一次读请求,但是综合多个gmem
便可以在一拍内分别进行请求!
方案三(解决 II = 2问题)
- 方案三 源码
1 |
|
- 方案三 设置
- 方案三 综合结果
- 方案三 HLS log文件
- 方案三 Performence图
总结
- 产生gmem carry dependency的两种解决办法:
- 进行 gmem位宽大小的调整 32bit – 512bit
- 多个 __global 参数采用多个gmem进行数据传输(max memory ports)
TODO 采用pipe传输(做一个memRead)
- 问题(当数据为非32bit的倍数-512bit)