xilinx 暑期学校学习笔记(三)HLS优化语法与资源

优化语法


硬件资源指定语法

指定向FPGA硬件资源映射时的资源类型#

#pragma HLS RESOURCE variable =<temp>core =<Xilinxcore>
Examples :
a = b + c;
# pragma HLS RESOURCE variable =a core =AddSub_DSP
intA[1024];
# pragma HLS RESOURCE variable =A core =RAM_T2P_BRAM

数组划分语法

#pragma HLS array _partition variable =<name><type>factor =<int>dim =<int>
Type :complete ,cyclic ,block 
dim=1,23(dim=0)

在这里插入图片描述
不同TYPE:
complete: 完全打散为N个数
Block: 打散为几个块
cycle: factor 取模的方式进行划分,如奇偶性


流水化

任务级流水化

#pragma HLS dataflow

管线优化

#pragma HLS PIPELINE

任务级流水化粒度更大,作用于不同的子函数,后面的代码只能包含函数调用和中间变量声明。

pipeline作用于循环的不同iteration


STREAM

数据类型: hls::stream<stream_type>
以高性能FIFO替代高资源占用的double-buffered RAM
指令:#pragma HLS stream variable =<variable>depth =<int>dim=<int>

  • 数据类型为Istream ,使用流操作符操作
  • 在函数参数配置时传引用“&”
  • 必须有一个producer 和一个consumer

函数内联

#pragma HLS INLINE(off)

循环

循环边界

一般循环次数为定值,否则综合后无法获得性能估计(Latency=?)

#pragma HLS loop_tripcount min = <int> max = <int> avg =<int>

循环展开

手动展开或使用指令

#pragma HLS UNROLL(factor = <int>)
E.g., #pragma HLS UNROLL factor=2

过分了可能综合时间过长和失败


资源内容

硬件资源

可以存储于为片上的存储单元/Buffer/Scratchpad Memory
设计利用数据局部性提高重复访问数据的访问效率

  • flip-flop(FF)
    • 单个时钟周期内可并行访问多个地址
    • 单个时钟周期内可完成读、写操作
    • 容量有限:典型值大约100Kbytes
  • Block RAM ( BRAM)
    • 高容量:典型值在Mbytes 级别
    • 访问性能受限:端口有限
  • 权衡:带宽vs.容量

数值精度

头文件: ap_int.h,ap_fixed.h
支持任意精度、任意位宽的有/无符号数据类型:

  • Unsigned int :ap_uint
  • Signed int :ap_int
  • Unsigned fixed : ap_ufixed<width,width_int>
  • Signed fixed :ap _fixed<width,width_int>

精度处理

  • 加法: ap_uint A = ap_uint B + ap_uint C ,where x = max (y,z) + 1
  • 乘法: ap_uint A = ap_uint B * ap_uint C ,where x = y+z

其实说人话就是加法的精度取决于原来误差较大的,乘法则是原来的相乘


模块接口

在综合过程中定义生成的硬件接口

  • 函数级(函数调用传参)的接口实现方式、控制协议
  • ip级(顶层函数参数)的接口实现方式、控制协议

常用有

  • ap_fifo:生成标准FIFO接口,常做模块间数据通路
  • m_axi:生成AXI4总线的Master接口,常做IP外部数据访问接口
  • s_axilite:生成AXI4-lite的Slave接口,常做控制IP调用的控制接口

优化案例

源码如下

void test()
{
	float In[CHin][Rin][Cin];
	float Out[CHout][R][C];
	float W[CHout][CHin][K][K];

	Output_Channel:
	for(int cho=0; cho<CHout; cho++)
	{
		Input_Channel:
		for(int chi=0; chi<CHin; chi++)
		{
			Row:
			for(int r=0; r<R; r++)
			{
				Column:
				for(int c=0; c<C; c++)
				{
					Kernel_Row:
					for(int kr=0; kr<K; kr++)
					{
						Kernel_Column:
						for(int kc=0; kc<K; kc++)
						{
							Out[cho][r][c] += In[chi][r+kr][c+kc] * W[cho][chi][kr][kc];
						}
					}
				}
			}
		}
	}

	return;
}

未优化

在这里插入图片描述

数组展开及循环展开

void test()
{
	float In[CHin][Rin][Cin];
#pragma HLS array_partition variable=In complete dim=1
	float Out[CHout][R][C];
#pragma HLS array_partition variable=Out complete dim=1
	float W[CHout][CHin][K][K];
#pragma HLS array_partition variable=W complete dim=1
#pragma HLS array_partition variable=W complete dim=2
	
	Row:
	for(int r=0; r<R; r++)				
	{
		Column:
		for(int c=0; c<C; c++)	
		{
			Kernel_Row:
			for(int kr=0; kr<K; kr++)					
			{
				Kernel_Column:
				for(int kc=0; kc<K; kc++)				
				{
					Output_Channel:
					for(int cho=0; cho<CHout; cho++)
					{
#pragma HLS UNROLL
						Input_Channel:
						for(int chi=0; chi<CHin; chi++)						
						{
#pragma HLS UNROLL
							Out[cho][r][c] += In[chi][r+kr][c+kc] * W[cho][chi][kr][kc];
						}
					}
				}
			}
		}
	}

	return;
}

在这里插入图片描述

数组展开及PIPELINE优化

void test()
{
	float In[CHin][Rin][Cin];
#pragma HLS array_partition variable=In complete dim=1
	float Out[CHout][R][C];
#pragma HLS array_partition variable=Out complete dim=1
	float W[CHout][CHin][K][K];
#pragma HLS array_partition variable=W complete dim=1
#pragma HLS array_partition variable=W complete dim=2
	
	Row:
	for(int r=0; r<R; r++)				
	{
		Column:
		for(int c=0; c<C; c++)	
		{
			Kernel_Row:
			for(int kr=0; kr<K; kr++)					
			{
				Kernel_Column:
				for(int kc=0; kc<K; kc++)				
				{
#pragma HLS PIPELINE
					Output_Channel:
					for(int cho=0; cho<CHout; cho++)
					{
						Input_Channel:
						for(int chi=0; chi<CHin; chi++)						
						{
							Out[cho][r][c] += In[chi][r+kr][c+kc] * W[cho][chi][kr][kc];
						}
					}
				}
			}
		}
	}

	return;
}

在这里插入图片描述

不同循环顺序的PIPELINE优化

void test()
{
	float In[CHin][Rin][Cin];
#pragma HLS array_partition variable=In complete dim=1
	float Out[CHout][R][C];
#pragma HLS array_partition variable=Out complete dim=1
	float W[CHout][CHin][K][K];
#pragma HLS array_partition variable=W complete dim=1
#pragma HLS array_partition variable=W complete dim=2

	Kernel_Row:
	for(int kr=0; kr<K; kr++)					
	{
		Kernel_Column:
		for(int kc=0; kc<K; kc++)				
		{
			Row:
			for(int r=0; r<R; r++)				
			{
				Column:
				for(int c=0; c<C; c++)	
				{		
#pragma HLS PIPELINE
					Output_Channel:
					for(int cho=0; cho<CHout; cho++)
					{
						Input_Channel:
						for(int chi=0; chi<CHin; chi++)						
						{
							Out[cho][r][c] += In[chi][r+kr][c+kc] * W[cho][chi][kr][kc];
						}
					}
				}
			}
		}
	}

	return;
}

在这里插入图片描述

效果对比

在这里插入图片描述

  • 6
    点赞
  • 22
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 3
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

豆沙粽子好吃嘛!

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值