用FPGA处理矩阵加法,何时能比CPU快
设备:
alter cyclone EP1C3T144C8 ;
串口RS232 ;
PC机 ;
利用RS232 实现 PC 和 FPGA 通信
实验目标
对于5000x5000的矩阵A、B,进行相加。保证每位数据均为七位宽(即数据范围0-127)(即保证数据和低于八位宽(0-255))。
比较PC机和FPGA处理速度
实验过程
Step 1 利用PC进行处理(c++)
把矩阵定义为short类型(因为不知道更短的类型)
跑一个矩阵求和,大概25_000_000次short型计算
跑出来的时间51ms(计算一下,我的电脑大概一秒能做600_000_000次整型运算)
结论 PC能在50ms给出答案(不包括IO时间)
优点:足够快且简单
缺点:时延不固定
Step 2 利用RAM缓存处理数据
按照CPU的处理思路,第一想法是把数据加载进入RAM,然后读出,处理,输出;然后再加载进入RAM,再读出处理输出……
看一下我EP1C3T144C8的RAM,RAM只有59904个bit,也就是能存7488个字节,然而我有25_000_000个字节,这样得重复处理大概2500次。
但好在FPGA对于片上RAM的读写非常快(读写速度是由时钟频率决定的),再加上RAM可以实现边读边写,那我们何必去使用RAM,直接使用FIFO即时处理不就好了。(所以RAM和FIFO本质上没有什么不同吧)
Step 3 即时处理每帧数据
处理框图如下,利用同一个时钟sys_clk进行驱动,在uart_rx 模块收入矩阵A一帧数据(一个完整的数)之后,传入数据处理模块利用寄存器暂存,这时候等待uart_rx 模块传来矩阵B同一个坐标下的数据,传入数据处理模块后,相加结果传入uart_tx模块输出。
整个处理过程用一个例子阐述就是
eg:
A B
[1,2,3] [1,2,3]
[4,5,6] [4,5,6]
[7,8,9] [7,8,9]
矩阵A的数据1传入数据处理模块暂存,等待B传入数据1,传入之后相加再输出。
整个处理时间是在时钟频率内就可以完成的
但是串口的波特率只有9600,大量的时间花费在IO上
结论 处理时间能够在固定时延内完成(几个时钟周期),但是IO时间成本高
优点 时延固定,并且处理时间能够在几个时钟内解决
缺点 IO成本高
PS:我们依然用利用PC进行预处理,因为要AB两个矩阵轮流发送数据(这样就显得FPGA画蛇添足了,但这只是开始吧!
Step 4提高串口bps,换用高速接口
不过显然这个问题可以得到改善,我们只需要提高接口协议的速率即可。
两个矩阵2x5000x5000x8一共200_000_000bit的数据
USB3.0的bps在Gbps(1_000_000_000 bit/s)这个级别,所以理论上可以在200_000_000/1_000_000_000 == 0.2秒之内完成操作,但是这时候时钟频率也要达到Ghz,显然对于FPGA来说无法达到(目前旗舰FPGA主频在几百Mhz,即使倍频成Ghz,也是无法稳定工作,甚至利用PLL无法输出Ghz的时钟频率)
结论 FPGA的主频无法支持这个想法
Step 5多个IO口提高速率
优化到Step 4 的时候,我脑子里都是FPGA是一个并行化处理见长,那么我们怎么进行并行化处理呢?
一个最直观的想法就是提高IO口数目
这样的话,似乎并行口越多,处理速度越快,要是有一万个IO口我们就能提升一万倍了
显然,没有电脑有几万个IO口
Step 6 多时钟域处理问题
直到我在知乎上看到这样一句话(历史记录找不到了,大概是这个意思
FPGA从来不是靠极快的时钟频率解决问题,而是靠多个时钟域并行处理
这句话顿时让我醒悟,之前Step 4遗留下来的问题,我们并不需要提高时钟频率啊!而是采用多个时钟,时钟之间有相位差就可以了啊!
cyclone I 系列的PLL是1个,每个锁相环可以产生5路时钟信号
也就是说,我们可以将时间缩小5倍
当锁相环数量增多,两个PLL我们就能实现一个数量级的时间优化
对于1Gbps传入的数据,如果在10个异步时钟域处理问题,那么时钟需要的频率就是1_000_000_000/10 == 100MHZ的频率,这就是我们完全能够达到的。
如果我们再增加PLL数量呢?情况当然会更好了。
总结
一个简单的矩阵的加法的例子,就能充分体现(我认为的)FPGA的并行优势。
这是建立在我们的一次操作,仅仅是一次加法的基础上,CPU占尽了优势,因为CPU处理一次加法的时间远快于FPGA的一个时钟周期。
但是如果我们的一次操作不仅仅是一个加法呢?
如果我们一次操作CPU要O(N)的时间(例如对N个数据求和
但是FPGA能在一个时钟周期内完成
显然,不用任何优化,FPGA就占据了一个数量级的优势了
从C语言到硬件描述语言,我们又迈出了一步!
但是作者只是初学者,如果有错误,请不啬赐教!