上午在论坛看到个热帖,里头的题目挺有意思的,简单的记录了一下。

0. 题目 

在FPGA上实现一个模块,求32个输入中的最大值和次大值,32个输入由一个时钟周期给出。(题目来自论坛,面试题,如果觉得不合适请留言删除)

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

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

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

1. 解法

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

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

这种解法有若干个缺点,包括:延迟求最大值和次大值分别需要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#(
parameter DW =
)
(
input clk,
input [*DW- :] din,
output [DW-:] max1,
output [DW-:] max2
); wire[DW-:] d[:];
generate
genvar i;
for(i=;i<;i=i+)
begin:loop_assign
assign d[i] = din[DW*i+DW-:DW*i];
end
endgenerate // stage 1,comp
reg[DW-:] s1_max[:];
reg[DW-:] s1_min[:];
generate
for(i=;i<;i=i+)
begin:loop_comp
always@(posedge clk)
if(d[*i]>d[*i+])begin
s1_max[i] <= d[*i];
s1_min[i] <= d[*i+];
end
else begin
s1_max[i] <= d[*i+];
s1_min[i] <= d[*i];
end
end
endgenerate // stage 2,
wire[DW-:] s2_max[:];
wire[DW-:] s2_min[:];
generate
for(i=;i<;i=i+)
begin:loop_megs2
meg u_s2meg(
.clk(clk),
.g1_max(s1_max[*i]),
.g1_min(s1_min[*i]),
.g2_max(s1_max[*i+]),
.g2_min(s1_min[*i+]),
.max1(s2_max[i]),
.max2(s2_min[i])
);
end
endgenerate
// stage 3,
wire[DW-:] s3_max[:];
wire[DW-:] s3_min[:];
generate
for(i=;i<;i=i+)
begin:loop_megs3
meg u_s3meg(
.clk(clk),
.g1_max(s2_max[*i]),
.g1_min(s2_min[*i]),
.g2_max(s2_max[*i+]),
.g2_min(s2_min[*i+]),
.max1(s3_max[i]),
.max2(s3_min[i])
);
end
endgenerate // stage 4,
wire[DW-:] s4_max[:];
wire[DW-:] s4_min[:];
generate
for(i=;i<;i=i+)
begin:loop_megs4
meg u_s4meg(
.clk(clk),
.g1_max(s3_max[*i]),
.g1_min(s3_min[*i]),
.g2_max(s3_max[*i+]),
.g2_min(s3_min[*i+]),
.max1(s4_max[i]),
.max2(s4_min[i])
);
end
endgenerate // stage 5,
meg u_s5meg(
.clk(clk),
.g1_max(s4_max[]),
.g1_min(s4_min[]),
.g2_max(s4_max[]),
.g2_min(s4_min[]),
.max1(max1),
.max2(max2)
);
endmodule module meg#(
parameter DW =
)
(
input clk,
input [DW- :] g1_max,
input [DW- :] g1_min,
input [DW- :] g2_max,
input [DW- :] g2_min,
output reg [DW-:] max1,
output reg [DW-:] max2
);
always@(posedge clk)
begin
if(g1_max>g2_max) begin
max1 <= g1_max;
if(g2_max>g1_min)
max2 <= g2_max;
else
max2 <= g1_min;
end
else begin
max1 <= g2_max;
if(g1_max>g2_min)
max2 <= g1_max;
else
max2 <= g2_min;
end
end
endmodule

3. 其他

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

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

FPGA上如何求32个输入的最大值和次大值:分治的更多相关文章

  1. leetcode-747-Largest Number At Least Twice of Others(求vector的最大值和次大值)

    题目描述: In a given integer array nums, there is always exactly one largest element. Find whether the l ...

  2. 云中的机器学习:FPGA 上的深度神经网络

    人工智能正在经历一场变革,这要得益于机器学习的快速进步.在机器学习领域,人们正对一类名为“深度学习”算法产生浓厚的兴趣,因为这类算法具有出色的大数据集性能.在深度学习中,机器可以在监督或不受监督的方式 ...

  3. 【小梅哥FPGA进阶教程】MC8051软核在FPGA上的使用

    十.MC8051软核在FPGA上的使用 本教程内容力求以详细的步骤和讲解让读者以最快的方式学会 MC8051 IP core 的应用以及相关设计软件的使用,并激起读者对 SOPC 技术的兴趣.本实验重 ...

  4. PCIE_DMA实例四:xapp1052在Xilinx 7系列(KC705/VC709)FPGA上的移植

    PCIE_DMA实例四:xapp1052在Xilinx 7系列(KC705/VC709)FPGA上的移植 一:前言 这段时间有个朋友加微信请求帮忙调试一块PCIe采集卡.该采集卡使用xilinx xc ...

  5. Win7 64位系统上配置使用32位的Eclipse(转)

    Win7 64位系统上配置使用32位的Eclipse 博客分类: Eclipse eclipse  最近工作电脑换成了64位的win7系统,之前个人电脑上安装的jdk和Eclipse都是32位的.而新 ...

  6. 基于dsp_builder的算法在FPGA上的实现

    基于dsp_builder的算法在FPGA上的实现   一.摘要 结合dsp_builder.matlab.modelsim和quartus ii等软件完成算法的FPGA实现. 二.实验平台 硬件平台 ...

  7. Java实现 蓝桥杯VIP 算法提高 3-2字符串输入输出函数

    算法提高 3-2字符串输入输出函数 时间限制:1.0s 内存限制:512.0MB 描述 编写函数GetReal和GetString,在main函数中分别调用这两个函数.在读入一个实数和一个字符串后,将 ...

  8. 求S=a+aa+aaa+aaaa+aa...a的值

    问题描述:求S=a+aa+aaa+aaaa+aa...a的值,其中a是一个数字,由输入a(1 <= a <= 9)表示,相加的元素个数由输入b(b<= 1000)表示. 这个算法的优 ...

  9. 题目:求s=a+aa+aaa+aaaa+aa...a的值,其中a是一个数字。

    一.第一种写法 package com.pb.demo1; import java.util.Scanner; /** * 题目:求s=a+aa+aaa+aaaa+aa...a的值,其中a是一个数字. ...

随机推荐

  1. Python 开发个人微信号在运维开发中的使用

    一.主题:Python 开发个人微信号在运维开发中的使用 二.内容: 企业公众号 介绍开发微信公众号的后台逻辑,包括服务器验证逻辑.用户认证逻辑 个人微信号 面对企业微信的种种限制,可以使用 Itch ...

  2. angular4.0项目main.ts详解

    main.ts负责引导整个angular应用的起点 // 导入enableProdMode用来关闭angular开发者模式 import { enableProdMode } from '@angul ...

  3. 企业级memcached缓存数据库结合php使用与web管理memcached

    环境 [root@cache01 ~]# cat /etc/redhat-release CentOS Linux release (Core) [root@cache01 ~]# uname -a ...

  4. (译)ABP之Abp Session

    原文地址:https://aspnetboilerplate.com/Pages/Documents/Abp-Session 介绍 ABP提供IAbpSession接口获取当前用户和租户信息,而不是使 ...

  5. 更新Appium中的WebDriverAgent

    到WebDriverAgent下载最新版本的WebDriverAgent 进入下载后的WebDriverAgent文件 执行 ./Scripts/bootstrap.sh 直接用Xcode打开WebD ...

  6. easy ui Tree请求跨域数据

    扯淡篇: jQuery EasyUI为提供了大多数UI控件的使用,如:accordion,combobox,menu,dialog,tabs,validatebox,datagrid,window,t ...

  7. 【LCT】BZOJ2049 [SDOI2008]Cave 洞穴勘测

    2049: [Sdoi2008]Cave 洞穴勘测 Time Limit: 10 Sec  Memory Limit: 259 MBSubmit: 10059  Solved: 4863[Submit ...

  8. django 项目中遇到的问题(持续更新中)

    问题1:in include 'provide the namespace argument to include() instead 描述:在最外层的urls.py 添加项目的urls后报错,错误显 ...

  9. Spring+SpringMVC+MyBatis+easyUI整合优化篇

    优化篇 Spring+SpringMVC+MyBatis+easyUI整合优化篇(一)System.out.print与Log Spring+SpringMVC+MyBatis+easyUI整合优化篇 ...

  10. windbg关于.NET分析的扩展命令

    收到一个dump文件,运行环境的.net framework的详细版本是多少呢? dump信息与性能计数器结合分析时,想知道该dump运行的进程号是多少? dump定位到有效的堆栈信息,而对应的源码是 ...