找回密码
 注册
关于网站域名变更的通知
查看: 591|回复: 3
打印 上一主题 下一主题

FPGA上如何求32个输入的最大值和次大值:分治

[复制链接]

该用户从未签到

跳转到指定楼层
1#
发表于 2021-6-16 13:41 | 只看该作者 |只看大图 回帖奖励 |倒序浏览 |阅读模式

EDA365欢迎您登录!

您需要 登录 才可以下载或查看,没有帐号?注册

x
本帖最后由 twel2e 于 2021-6-16 13:42 编辑
. z% T7 V& V8 U* X0 X9 a8 M; i+ k/ ^) A3 }7 [5 i

从我个人的观点来看,这是一道很好的面试题目:

  • 其一是这大概是某些机器学习算法实现过程中遇到的问题的简化,是很有意义的一道题目;
  • 其二是这道题目不仅要求FPGA代码能力,还有很多可以在算法上优化的可能;

    , S; b. k  {- ?' R" i

    当然,输入的位宽可能会影响最终的解题思路和最终的实现可能性。但位宽在一定范围内,譬如8或者32,解题的方案应该都是一致的,只是会影响最终的频率。后文针对这一题目做具体分析。(题目没有说明重复元素如何处理,这里认为最大值和次大值可以是一样的,即计算重复元素)

1. 解法

    从算法本身来看,找最大值和次大值的过程很简单;通过两次遍历:第一次求最大值,第二次求次大值; 算法复杂度是O(2n)。FPGA显然不可能在一个周期内完成如此复杂的操作,一般需要流水设计。这一方法下,整个结构是这样的

  • 通过比较,求最大值,通过流水线实现两两之间的比较,32-16-8-4-2-1通过5个clk的延迟可以求得最大值;
  • 由于需要求取次大值,因此需要确定最大值的位置,在求最大值的过程中需要维持最大值的坐标;
  • 最大值坐标处取值清零(置为最小)
  • 通过流水线实现两两之间的比较,32-16-8-4-2-1,再经过5个clk的延迟可以求得次大值;

    9 j. Y: [5 v% G3 ]1 m

    这种解法有若干个缺点,包括:延迟求最大值和次大值分别需要5clk延时,总延迟会超过10个cycles;资源占用较高,维持最大值坐标和清零操作耗费了较多资源,同时为了计算次大值,需要将输入寄存若干个周期,寄存器消耗较多。

    另一个种思路考虑同时求最大值和次大值,由于这一逻辑较为复杂,可以将其流水化,如下图。(以8输入为例,32输入需要增加两级)

    其中sort模块完成对4输入进行排序,得到最大值和次大值输出的功能。4个数的排序较为复杂,这一过程大概需要2-3个cycles完成。对于32输入而言,输入数据经过32-16-8-4-2输出得到结果,延迟大概也有10个周期。

2. 分治

    如果需要在FPGA上实现一个特定的算法,那么去找一个合适的方法去实现就好了;但如果是要实现一个特定的功能,那么需要找一个优秀的且适合FPGA实现的方法。

    求最大值和次大值是一个很不完全的排序,通过简单的查找复杂度为O(2n),且不利于硬件实现。对于排序而言,无论快速排序或者归并排序都用了分治的思想,如果我们试图用分治的思想来解决这一问题。考虑当只有2个输入时,通过一个比较就可以得到输出,此时得到的是一个长度为2的有序数组。如果两个有序数组,那么通过两次比较就可以得到最大值和次大值。采用归并排序的思想,查找最大值和次大值的复杂度为O(1.5n)(即为n/2+n/2+n/4… ,不知道有没有算错)。采用归并排序的思想,从算法时间复杂度上看更为高效了。

    那么这一方案是否适合FPGA实现呢,答案是肯定的。分治的局部性适合FPGA的流水实现,框图如下。(以8输入为例,32输入需要增加两级)

    其中meg模块内部有两级的比较器,一般而言1clk就可以完成,输入数据经过32-32-16-8-4-2得到结果,延迟为5个时钟周期。实现代码如下

module test#(
- `8 T2 P6 J/ Z6 K' v( \parameter DW = 8. b. \8 E2 l0 d( ~
)8 ?% k: j# A6 |4 d
(# ]2 v7 T" |6 O7 w3 s3 R3 q5 }6 P
input clk,
. _1 o9 i2 M, V. {: Yinput [32*DW-1 :0] din,
" m0 e$ O0 V7 F5 q9 s2 N1 Koutput [DW-1:0] max1,
( C1 m0 N# _2 k# l' x7 l# ioutput [DW-1:0] max29 x# M+ e7 W8 c
);1 p& D, f; X6 @& _# w! M. s
" [: u+ a3 i: D% F, v
wire[DW-1:0] d[31:0];
" C6 _8 }$ B0 r( ~8 U4 qgenerate
+ n7 A) d0 F$ `1 H8 g4 b1 L    genvar i;
, Z; I5 B! P, E: h6 {/ Q    for(i=0;i<32;i=i+1)
9 g' l5 k% g& i* c+ q$ T1 i    begin:loop_assign3 a/ Q' W0 x1 |
        assign d = din[DW*i+DW-1W*i];6 O$ ^/ p" V# O) N# E# ~. l
    end
( a% R% x' V8 f9 r. j0 D0 r! cendgenerate
2 e2 t! E$ n9 O  Y. U7 {2 ]0 U: ?$ J' H3 D0 |; F( f6 h' ~& e
// stage 1,comp4 D( O4 r$ V- ^" c: m. l
reg[DW-1:0] s1_max[15:0];
. k1 P7 j5 Y1 P6 _; D5 L& lreg[DW-1:0] s1_min[15:0];
% {  L: c9 R2 bgenerate
3 {: p8 ]7 R6 e1 d    for(i=0;i<16;i=i+1)$ ^1 ]# g, K9 r0 [4 Z2 H9 B; _+ W6 [
    begin:loop_comp
! G* f% m$ c# D/ x. i+ f        always@(posedge clk)8 V" X  H  T1 A( u  E0 r- Z( R
            if(d[2*i]>d[2*i+1])begin4 n: E- B$ A# w5 `7 H9 v4 H: x- l
                s1_max <= d[2*i];9 [/ x  w$ e$ I1 A! |( c
                s1_min <= d[2*i+1];
" |# P2 B) F) D+ y+ w/ z. B4 J            end+ T9 C! C  N( \. ^. o1 S; d
            else begin
! ^3 ], t+ t6 `' k0 s, f" ~; E+ T" a                s1_max <= d[2*i+1];
6 s( \4 i5 k4 W# m  i                s1_min <= d[2*i];6 S, l! k0 e, n% x9 |
            end
) H& z% l' |9 D    end
) Q  s( H! W( dendgenerate
, X- u, _" K0 ~; [) a; x- g
7 _" v( W$ @  v( P( d// stage 2,6 K" ~! q. \3 _2 d8 r' B# b& T2 H) S
wire[DW-1:0] s2_max[7:0];
# V. o( A3 A: u- T) ]3 z3 X" b' N* qwire[DW-1:0] s2_min[7:0];. Y% m2 r+ k+ K& q
generate6 Q' x, L4 `: k& C
    for(i=0;i<8;i=i+1)8 U) ~! s* X. v: x& p
    begin:loop_megs2" @1 ^+ H* o/ {, J0 J+ y- j& N3 A
        meg u_s2meg(
# D! O3 M9 p" S8 g" L            .clk(clk),5 [4 }' L4 T+ M8 K9 T5 D
            .g1_max(s1_max[2*i]),
- D& D& x. G# o/ E2 ?            .g1_min(s1_min[2*i]),6 F$ |" G- p% q1 b% d
            .g2_max(s1_max[2*i+1]),
1 I0 C* T  V9 f: \6 B            .g2_min(s1_min[2*i+1]),$ X6 O+ t+ O' ~; g- t
            .max1(s2_max),
; l4 n' ?$ ]! g0 z6 |( C: A" b            .max2(s2_min)' i2 o! g% [- o+ V, b6 f/ d" @
        );" Y! P6 G; @; N9 d
    end
% g* ?$ [: z/ \& F$ hendgenerate
+ H+ h' }9 r) O" {% F+ s6 e// stage 3,0 ]. M2 a7 I$ {) X/ Y
wire[DW-1:0] s3_max[3:0];! R: n+ J, e' |. Q; G8 T+ q; k
wire[DW-1:0] s3_min[3:0];
1 U7 `3 M& n1 F7 E7 J' Zgenerate$ j8 w: k8 c* I5 J- N) j
    for(i=0;i<4;i=i+1)1 k+ d0 q9 I  C4 y0 d
    begin:loop_megs3
! t: a3 I0 c+ X' F. i9 D        meg u_s3meg(
$ Q$ T5 m* A6 v  e- t            .clk(clk),& `9 A5 Q% e2 Z# c" q% E  W# Q: u
            .g1_max(s2_max[2*i]),. |; Y, v% j8 D
            .g1_min(s2_min[2*i]),5 l+ m) v9 }0 {$ j- e
            .g2_max(s2_max[2*i+1]),0 g# b- J6 S8 K; A. _
            .g2_min(s2_min[2*i+1]),5 r6 b8 h+ L& c' O/ j: ^
            .max1(s3_max),
( H2 g2 V* z+ ^+ E' z            .max2(s3_min)
+ L# u% t/ `. P8 n        );
: M& c- U) p& F) B4 U; o; [    end  @& i8 K7 T7 r& ?0 K
endgenerate
0 e1 r% O. i3 M& Y4 R) i8 y* J( w$ ]  Q
// stage 4,* M% h# a. N+ A2 t& t
wire[DW-1:0] s4_max[1:0];1 E! j' K' H) B, \
wire[DW-1:0] s4_min[1:0];2 M) U/ e" S. h+ ~2 V5 b( v
generate8 u$ d5 M  x1 @! _! q: Y
    for(i=0;i<2;i=i+1); U/ @3 I$ h0 q7 X
    begin:loop_megs4! }' k9 E2 Q: I6 O1 @+ T* d. k
        meg u_s4meg(
' u  J  G0 h; h# x, B$ ~$ M            .clk(clk),' y1 {: c6 r* r% u6 U( m
            .g1_max(s3_max[2*i]),
. [& R: V) A1 c2 C3 t8 z            .g1_min(s3_min[2*i]),- N2 v: h' K% W5 \
            .g2_max(s3_max[2*i+1]),5 I  K: O. r+ r
            .g2_min(s3_min[2*i+1]),
. G1 X9 b9 `6 R6 d' N            .max1(s4_max),
; \7 `1 \1 h5 K/ E1 Y( z) O' a6 b' n+ |            .max2(s4_min)  x# Q5 D/ C6 D8 T: n' P
        );
+ r% e2 N6 D1 A/ ~- u    end
4 K. x$ |2 g, _4 @. Mendgenerate7 i% e5 q. \) B5 m% R

1 L" i4 b2 G: S// stage 5,9 M+ O9 N* X' O5 `! \
meg u_s5meg(# x7 A% H1 @; l' T( B( b
    .clk(clk),
1 c- M6 [: X" @# a. R& j    .g1_max(s4_max[0]),7 w% i9 k* x/ F. y2 v, {
    .g1_min(s4_min[0]),
5 a% m! H1 [: D: e: t- Z8 f& X    .g2_max(s4_max[1]),- z" u) u7 i6 Y7 W
    .g2_min(s4_min[1]),& h' r+ w! n# [: ]: S
    .max1(max1),7 o1 @9 _1 Y8 X7 K. P  |
    .max2(max2)- d7 i! T! |# ?4 D+ v8 J$ U
);0 _) c3 O4 x7 U3 J
endmodule
4 {; I: d4 j" v& h- K- V
9 b% @/ F/ u) Vmodule meg#(: m* Y! b% G/ z
parameter DW = 8
' \$ {+ g4 z9 s, X)
! j+ h* |" E, S% |(
4 h) v( O; s. \* _/ j" V9 xinput clk,
$ H5 v1 n( y- }+ q3 P" I$ N8 L6 Minput [DW-1 :0] g1_max,: `! L" W; a! G  S+ T: {- k- u* }
input [DW-1 :0] g1_min,
, A/ E9 {/ X" t' p! L8 c8 x$ vinput [DW-1 :0] g2_max,/ u5 U& T/ u6 z3 U) K* T
input [DW-1 :0] g2_min,
& o1 [2 J5 A, A* M9 R5 |output reg [DW-1:0] max1,- o( l* P" H# ]. T9 X
output reg [DW-1:0] max2
$ p! D9 N: ^0 x4 w6 p% A);
+ _( @0 t2 x+ r+ J- Y  ~& l% |; ?always@(posedge clk)
+ \$ K+ S( s& I) A8 [5 F. W6 j$ ~$ Pbegin
6 E+ C( Z  C- V4 q8 O' ^: V    if(g1_max>g2_max) begin: o6 I" W1 Q( B% |
        max1 <= g1_max;3 i* e! B# W* D9 W9 |
        if(g2_max>g1_min)
3 \1 a- w/ S$ v" ]$ X            max2 <= g2_max;5 M; @& l5 G( M0 \( s, T
        else, T5 A' _3 p, K; I$ S
            max2 <= g1_min;+ _' W! H: C1 B5 J5 W
    end1 Y  @  D4 V5 g8 _
    else begin
& }; l$ w+ Z+ F( F% N4 z2 S        max1 <= g2_max;. C6 a; m/ u) Q# ?! n7 x
        if(g1_max>g2_min)  q- R: K/ m9 ~8 O
            max2 <= g1_max;
0 A# ~- v. x5 \5 W% ~, I. N1 H        else/ B, k) R& L! L9 u1 a& S  a8 d9 B
            max2 <= g2_min;1 {; D0 h8 D4 X. o& Y2 y; L
    end
5 D6 o2 ?5 o! g. w1 `0 c1 `& Rend8 A( y& ?4 N- G( K
endmodule
View Code
3. 其他

    简单测试了上面的代码,在上一代器件上(20nm FPGA),8bit数据输入模块能综合到很高的频率,逻辑级数大概是5级左右,对于整个工程而言瓶颈基本不会出现在这一部分。32bit数据输入由于数据位宽太大,频率不会太高,但是通过将meg模块做一级流水,也几乎不会成为整个系统的瓶颈。

    32bit32输入情况下,数据输入位宽为1024(不是IO输入,是内部信号)。之前在通信/数字信号处理方面可能不会用到这么大位宽的数据,但对于AI领域FPGA的应用,数千比特的输入应该是很平常的,这的确会影响最终FPGA上实现的效果。要想让机器学习算法在FPGA上跑得更好,还需要算法和FPGA共同努力才是。

, e7 W4 U4 L, n! M

该用户从未签到

2#
发表于 2021-6-16 15:02 | 只看该作者
FPGA显然不可能在一个周期内完成如此复杂的操作,一般需要流水设计
) {% a9 x9 V% s3 T/ ?% c

该用户从未签到

3#
发表于 2021-6-16 16:50 | 只看该作者
要想机器学习算法在FPGA上跑的更快,还需要算法和FPGA的共同努力
- c5 ?, U# j9 B- k! Z" f3 e( U" F2 r3 R8 ]9 H0 A! D; J; j

该用户从未签到

4#
发表于 2021-6-16 17:47 | 只看该作者
分而治之,是这个意思吗
; ]$ h7 v% K' }% z$ M2 A! S
您需要登录后才可以回帖 登录 | 注册

本版积分规则

关闭

推荐内容上一条 /1 下一条

EDA365公众号

关于我们|手机版|EDA365电子论坛网 ( 粤ICP备18020198号-1 )

GMT+8, 2025-8-16 06:40 , Processed in 0.156250 second(s), 26 queries , Gzip On.

深圳市墨知创新科技有限公司

地址:深圳市南山区科技生态园2栋A座805 电话:19926409050

快速回复 返回顶部 返回列表