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

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

[复制链接]

该用户从未签到

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

EDA365欢迎您登录!

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

x
本帖最后由 twel2e 于 2021-6-16 13:42 编辑
0 {% ~8 b3 ~; _" L$ `% c. y8 v! P; J2 r

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

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

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

1. 解法

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

  • 通过比较,求最大值,通过流水线实现两两之间的比较,32-16-8-4-2-1通过5个clk的延迟可以求得最大值;
  • 由于需要求取次大值,因此需要确定最大值的位置,在求最大值的过程中需要维持最大值的坐标;
  • 最大值坐标处取值清零(置为最小)
  • 通过流水线实现两两之间的比较,32-16-8-4-2-1,再经过5个clk的延迟可以求得次大值;
    , w; A' {6 d* q0 Q# t% J* h( ?- ]8 G

    这种解法有若干个缺点,包括:延迟求最大值和次大值分别需要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#(
+ X1 ]" j0 `7 L( Z! sparameter DW = 8! h3 s3 g9 [  o* W$ E
)
7 R! b, Y2 y4 b. F(' o8 B; G% Z, H1 x7 h9 y6 r7 F# s
input clk,
) y% L3 w! v3 M8 \input [32*DW-1 :0] din,
0 f4 k4 j" r- ~" `, [8 \2 Noutput [DW-1:0] max1,
8 x4 ?4 h# s3 [! G3 F' ^; f* Routput [DW-1:0] max21 }5 \2 z, o# V: I
);' N6 n0 c' R7 O! ]- k" F; A2 u" e

# v# @, a2 u+ E( a; w2 Ewire[DW-1:0] d[31:0];
$ Z4 D% p7 t. Y1 Q/ z$ Q6 Q- vgenerate2 A7 W7 O2 e' L# ^* w6 Q' O
    genvar i;
: v) a9 P9 x; S  r* e    for(i=0;i<32;i=i+1)
) I% \$ A5 g# o( @! j/ P    begin:loop_assign
  w  Y0 I4 X+ }: n7 Z& l% T1 {        assign d = din[DW*i+DW-1W*i];/ l* c4 ^) b  L2 A
    end
- E) b" c* C* S" E( x/ T/ Cendgenerate
( ~6 [! F8 T7 D* s: J" \0 _2 \9 E1 k
// stage 1,comp( e  R7 C. s. r- a3 h8 G
reg[DW-1:0] s1_max[15:0];
; B' O" B- z# greg[DW-1:0] s1_min[15:0];" T& h2 x/ G- n4 c* h
generate
. s2 D( L+ S. c    for(i=0;i<16;i=i+1)
- V0 ]& _5 M# i! O  S: L    begin:loop_comp7 L% G1 h/ |* S- p8 k4 x7 r+ g
        always@(posedge clk)
& \  s4 F& ]& g0 W& w! Y            if(d[2*i]>d[2*i+1])begin
) U0 r2 {+ _2 W9 n% b0 |                s1_max <= d[2*i];) a. b$ |! K: V; @
                s1_min <= d[2*i+1];6 ], d0 @2 _- x; E% H6 s0 S! o
            end
* M1 h. s/ B" {, y% [. K            else begin! u' A- `4 |3 B( [- A" |) x; p
                s1_max <= d[2*i+1];. B& l% P  m" w  f( t" s
                s1_min <= d[2*i];+ o$ h- B0 y: {2 w, s. Z# n4 j
            end
- Z$ k2 m( j8 U% b" C/ W/ z    end
) {4 [, ]1 v, U4 ~endgenerate- }+ H7 m0 m+ J5 x" |$ x' m4 R
# a8 S4 c6 F$ Z
// stage 2,9 I: I0 b: ~2 @' N( ~$ ?
wire[DW-1:0] s2_max[7:0];" N2 D; V  U' x( }- B9 h* ~, f& H
wire[DW-1:0] s2_min[7:0];) t: N2 b% ]0 k+ \2 [; ]
generate- M) \; W: @* c1 k3 z  a/ j
    for(i=0;i<8;i=i+1)
, P9 }' c! }; H: ~$ b* H    begin:loop_megs29 {$ \5 \5 m* v/ Z# P  b6 F/ |* X
        meg u_s2meg(
0 g$ Q" z, [2 G) c            .clk(clk),  A5 m7 G% C2 D6 \
            .g1_max(s1_max[2*i]),
6 o# T7 e; K; N" |8 n+ q  t            .g1_min(s1_min[2*i]),' H& O# X$ i* k  z3 G( c+ ?8 b  x
            .g2_max(s1_max[2*i+1]),) {2 ^9 u$ F# _1 c; {
            .g2_min(s1_min[2*i+1]),
& w% o5 ]# C, x. L7 t            .max1(s2_max),( g+ j  }, c: P9 t. u* o  D4 @
            .max2(s2_min)) b3 p9 _& s: R& Q5 H0 d2 x
        );5 T4 l9 x9 s% w
    end' i( V3 O" Y9 s2 [2 r! w% c: m6 v
endgenerate
1 j# j3 ]. R9 B3 M7 F6 L- k" L// stage 3,
# \& P5 c% p1 y7 I2 r! dwire[DW-1:0] s3_max[3:0];
* d- l. s9 l! D% [5 swire[DW-1:0] s3_min[3:0];
' B8 m7 f8 Z9 J( w5 M/ Lgenerate! i- S8 P' v( ^% F0 y# i
    for(i=0;i<4;i=i+1)' l0 `0 p/ @" t4 Q" K3 Y
    begin:loop_megs3; ~' I! M8 d5 Z3 o' c* }, Q
        meg u_s3meg(0 \8 m  z4 y  P4 P
            .clk(clk),
( C) n3 F3 ^2 V, x' Z            .g1_max(s2_max[2*i]),
8 d' {# M4 Z" Y: h            .g1_min(s2_min[2*i]),) J8 h( u" @- O; \5 H+ D1 H
            .g2_max(s2_max[2*i+1]),
4 x# Y' |: n  f# Z3 K9 a' ^            .g2_min(s2_min[2*i+1]),+ u3 p5 n- A8 U% L
            .max1(s3_max),2 ^, T! Y( a( ?1 J$ K* {+ G
            .max2(s3_min)5 @% x% G5 A+ h( D1 c
        );: z- w9 e  U0 A5 u+ K- N
    end
- h, R2 g3 ?- ~# |6 f: Qendgenerate
6 n) F8 I" A2 x; L- a8 p
) ^; s( _% M6 G; D  k( j: X# L. t// stage 4,3 H6 L! N8 H6 I& X; \  Y- {
wire[DW-1:0] s4_max[1:0];( O* N) Y; B- t# n- Q7 I
wire[DW-1:0] s4_min[1:0];
" k! R; F5 L! P, ]+ u: R% y( Xgenerate
- W. ]6 M1 k- d' D1 ]    for(i=0;i<2;i=i+1)6 S7 ]3 B2 l8 M+ F7 a7 D# X
    begin:loop_megs43 ?( \: }0 K6 X1 a3 B
        meg u_s4meg(
' g" @+ \$ H. T: n% z            .clk(clk),8 Y$ B! c0 D, Y5 `  Y: S
            .g1_max(s3_max[2*i]),( Z4 w5 D( Z8 r1 ?7 {0 V& S
            .g1_min(s3_min[2*i]),
1 @1 {0 n; u- u( |3 M; K+ c            .g2_max(s3_max[2*i+1]),
" s) L" z" V( e& a            .g2_min(s3_min[2*i+1]),
' q7 X6 L; i6 U            .max1(s4_max),( b( ?4 P+ J3 Z% c
            .max2(s4_min)6 T/ t* R# a& [9 S% ^# q
        );/ \. |# d4 J1 h8 e2 U
    end; K; F' W8 c& F* J4 q% E( r9 `
endgenerate
( [5 u+ O3 R# o2 `: i9 g9 S( a9 o# \, J5 H, ?
// stage 5,
* j: x* ]+ F- ]) [- jmeg u_s5meg(
, u: C+ ^) A+ A3 T& G9 y    .clk(clk),$ Y4 C0 Z7 h6 w: r  `
    .g1_max(s4_max[0]),
3 u. Y% a  x8 E1 p+ ^    .g1_min(s4_min[0]),8 x1 `: p5 V3 b2 q, t3 w. E
    .g2_max(s4_max[1]),3 m, ~9 {$ I* Y! W  G" [7 e. {
    .g2_min(s4_min[1]),
/ x7 b) c, |# M# @8 |1 i; x    .max1(max1),& W; R) p" _5 j# r+ }$ W9 X
    .max2(max2)0 F9 S% S9 i! ]( a' p" P9 s
);; N( X5 N* ], E8 G
endmodule
# ~7 |  X$ k! _& H! ?. F- Y- e& G5 o; c9 X  |" m6 A
module meg#(- a% G- w2 o+ I' }
parameter DW = 8# A; a9 s2 c, A# y: C  e
)1 U  q; U  Q! k
(* d% F& A8 ~7 d7 H
input clk," c/ ?# T; @; _& ^' f5 ^
input [DW-1 :0] g1_max,
3 ~) J9 i5 S5 R& m- H" l1 @input [DW-1 :0] g1_min,
# V" m* {, n: A5 n) {: Vinput [DW-1 :0] g2_max,
* N% B+ {2 l% \5 binput [DW-1 :0] g2_min,3 E) `1 j5 q6 J' k
output reg [DW-1:0] max1,6 F, H7 e8 Z( L1 }7 s
output reg [DW-1:0] max2# I8 v7 x4 Y" H  M) @
);
0 E# h* W, r0 x" g1 yalways@(posedge clk)/ l4 K; B. i' P6 G  F
begin0 m1 K' w7 I. W" e1 {6 H, G, h
    if(g1_max>g2_max) begin
7 x: ?: \) X" C5 C* N& P        max1 <= g1_max;
. Q9 c( g; J$ ~* ?4 ~5 d5 L5 T' o/ C9 y        if(g2_max>g1_min)# F9 U! l, ]7 i1 f6 U% W4 R
            max2 <= g2_max;
! ?" n" }8 b+ L& M; l4 }        else2 ]8 F, d0 {6 C% |0 D6 S
            max2 <= g1_min;6 @- n% {7 N$ |9 ]! K$ j+ y; _
    end
. o5 i8 @+ d6 ?, _5 D: p    else begin
  i  S% J$ h# ~        max1 <= g2_max;
2 _' c3 F; q8 w( b8 j0 ~        if(g1_max>g2_min)- z( ?. z) C) V
            max2 <= g1_max;
" @6 Y  e( l: R! L        else
& p. U9 O4 X% ?            max2 <= g2_min;
0 D2 D- s% h7 R5 T9 I  s    end6 ]- c* }6 C; F  O4 `: v- G( s: K
end+ P( P3 W7 t- F: @
endmodule
View Code
3. 其他

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

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


. j$ G: P- E' o; Y7 @* _' ~

该用户从未签到

2#
发表于 2021-6-16 15:02 | 只看该作者
FPGA显然不可能在一个周期内完成如此复杂的操作,一般需要流水设计2 v2 B- n+ p* m  d

该用户从未签到

3#
发表于 2021-6-16 16:50 | 只看该作者
要想机器学习算法在FPGA上跑的更快,还需要算法和FPGA的共同努力
, r. E  [/ ~, L* W" k9 i& h) U9 q/ L+ S1 p3 X

该用户从未签到

4#
发表于 2021-6-16 17:47 | 只看该作者
分而治之,是这个意思吗
$ p$ q4 I- E$ ?3 Z. p
您需要登录后才可以回帖 登录 | 注册

本版积分规则

关闭

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

EDA365公众号

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

GMT+8, 2025-10-9 22:29 , Processed in 0.156250 second(s), 26 queries , Gzip On.

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

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

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