0
  • 聊天消息
  • 系统消息
  • 评论与回复
登录后你可以
  • 下载海量资料
  • 学习在线课程
  • 观看技术视频
  • 写文章/发帖/加入社区
会员中心
创作中心

完善资料让更多小伙伴认识你,还能领取20积分哦,立即完善>

3天内不再提示

FPGA如何能让程序员们更好友好的开发

h1654155971.7688 来源:未知 作者:李倩 2018-06-01 08:56 次阅读

简介

对于一个软件开发人员,可能听说过 FPGA,甚至在大学课程设计中,可能拿FPGA做过计算机体系架构相关的验证,但是对于它的第一印象可能觉得这是硬件工程师干的事儿。

目前,随着人工智能的兴起,GPU 借助深度学习,走上了历史的舞台,并且正如火如荼的跑者各种各样的业务,从 training 到 inference 都有它的身影。FPGA 也借着这股浪潮,慢慢地走向数据中心,发挥着它的优势。所以接下来就讲讲 FPGA 如何能让程序员们更好友好的开发,而不需要写那些烦人的 RTL 代码,不需要使用 VCS,Modelsim 这样的仿真软件,就能轻轻松松实现 unit test。

实现这一编程思想的转变,是因为 FPGA 借助 OpenCL 实现了编程,程序员只需要通过 C/C++ 添加适当的pragma就能实现 FPGA 编程。为了让您用 OpenCL 实现的 FPGA 应用能够有更高的性能,您需要熟悉如下介绍的硬件。另外,将会介绍编译优化选项,有助于将您的 OpenCL 应用更好的实现 RTL 的转换和映射,并部署到 FPGA 上执行。

FPGA 概览

FPGA 是高规格集成电路,可以实现通过不断的配置和拼接,达到无限精度的函数功能,因为它不像 CPU 或者 GPU 那样,基本数据类型的位宽都是固定的,相反 FPGA 能够做的非常灵活。在使用 FPGA 的过程中,特别适合一些 low-level 的操作,比如像 bit masking、shifting、addition 这样的操作都可以非常容易的实现。

为了达到并行化计算,FPGA 内部包含了查找表(LUTs),寄存器(register),片上存储(on-chip memory)以及算术运算硬核(比如数字信号处理器 (DSP) 块)。这些 FPGA 内部的模块通过网络连接在一起,通过编程的手段,可以对连接进行配置,从而实现特定的逻辑功能。这种网络连接可重配的特性为 FPGA 提供了高层次可编程的能力。(FPGA的可编程性就体现在改变各个模块和逻辑资源之间的连接方式)

举个例子,查找表(LUTs)体现的 FPGA 可编程能力,对于程序猿来说,可以等价理解为一个存储器(RAM)。对于 3-bits 输入的 LUT 可以等价理解为一个拥有 3位地址线并且 8 个 1-bit 存储单元的存储器(一个8长度的数组,数组内每个元素是 1bit)。那么当需要实现 3-bits 数字按位与操作的时候,8长度数组存的是 3-bits 输入数字的按位与结果,一共是 8 种可能性。当需要实现 3-bits 按位异或的时候,8长度数组存的是 3-bits 输入数字的按位异或结果,一共也是 8 种可能性。这样,在一个时钟周期内,3-bits 的按位运算就能够获取到,并且实现不同功能的按位运算,完全是可编程的(等价于修改 RAM 内的数值)。

3-bits 输入 LUT 实现按位与(bit-wise AND)示例:

注: 3-bits 输入 LUT 查找表

我们看到的三输入的按位与操作,如下所示,在 FPGA 内部,可通过 LUT 实现。

如上展示了 3输入,1输出的 LUT 实现。当将 LUT 并联,串联等方式结合起来后就可以实现更加复杂的逻辑运算了。

传统 FPGA 开发

传统 FPGA 与软件开发对比

对于传统的 FPGA 开发与软件开发,工具链可以通过下表简单对比:

注:传统 FPGA 与软件开发对比表

重点介绍一下,编译阶段的 Synthesis (综合),这部分与软件开发的编译有较大的不同。一般的处理器 CPU、GPU等,都是已经生产出来的 ASIC,有各自的指令集可以使用。但是对于 FPGA,一切都是空白,有的只是零部件,什么都没有,但是可以自己创造任何结构形式的电路,自由度非常的高。这种自由度是 FPGA 的优势,也是开发过程中的劣势。

写到这里,让我想起了最近 《神秘的程序员们》中的一个梗:

注:漫画来源《神秘的程序员们56》by 西乔

传统的FPGA开发就像10岁时候的 Linux,想吃一个蛋糕,需要自己从原材料开始加工。FPGA 正是这种状态,想要实现一个算法,需要写 RTL,需要设计状态机,需要仿真正确性。

传统 FPGA 开发方式

复杂系统,需要使用有限状态机(FSM),一般就需要设计下图包含的三部分逻辑:组合电路,时序电路,输出逻辑。通过组合逻辑获取下一个状态是什么,时序逻辑用于存储当前状态,输出逻辑混合组合、时序电路,得到最终输出结果。

然后,针对具体算法,设计逻辑在状态机中的流转过程:

实现的 RTL 是这样的:

module fsm_using_single_always (clock

, // clockreset

, // Active high, syn resetreq_0

, // Request 0req_1

, // Request 1gnt_0

, // Grant 0gnt_1 );//=============Input Ports=============================input

clock,reset,req_0,req_1; //=============Output Ports===========================output gnt_0,gnt_1;//=============Input ports Data Type===================wire

clock,reset,req_0,req_1;//=============Output Ports Data Type==================reg gnt_0,gnt_1;//=============Internal Constants======================parameter SIZE = 3

;parameter IDLE = 3'b001,GNT0 = 3'b010,GNT1 = 3'b100 ;//=============Internal Variables======================reg [SIZE-1:0]

state

;// Seq part of the FSMreg [SIZE-1:0]

next_state ;// combo part of FSM//==========Code startes Here==========================always @ (posedge clock)begin : FSMif (reset == 1'b1) begin

state <= #1 IDLE;  gnt_0 <= 0;  gnt_1 <= 0;end else case(state)   IDLE : if (req_0 == 1'b1) begin      

state <= #1 GNT0;        

gnt_0 <= 1;            

end else if (req_1 == 1'b1) begin

gnt_1 <= 1;    

state <= #1 GNT1;          

end else begin

state <= #1 IDLE;      

end GNT0 : if (req_0 == 1'b1) begin

state <= #1 GNT0;          

end else begin

gnt_0 <= 0;          

state <= #1 IDLE;      

end GNT1 : if (req_1 == 1'b1) begin

state <= #1 GNT1;        

end else begin

gnt_1 <= 0;            

state <= #1 IDLE;      

end default : state <= #1 IDLE;endcaseendendmodule // End of Module arbiter

传统的 RTL 设计,对于程序员简直就是噩梦啊,梦啊,啊~~~工具链完全不同,开发思路完全不同,还要分析时序,一个 Clock 节拍不对,就要推翻重来,重新验证,一切都显得太底层,不是很方便。那么,这些就交给专业的 FPGAer 吧,下面介绍的 OpenCL 开发 FPGA,有点像 25 岁的 Linux 了。有了高层次的抽象。用起来自然也会更加方便。

基于 OpenCL 的 FPGA 开发

OpenCL 对于 FPGA 开发,注入了新鲜的血液,一种面向异构系统的编程语言,将 FPGA 最为异构实现的一种可选设备。由 CPU Host 端控制整个程序的执行流程,FPGA Device 端则作为异构加速的一种方式。异构架构,有助于解放 CPU,将 CPU 不擅长的处理方式,下发到 Device 端处理。目前典型的异构 Device 有:GPU、Intel Phi、FPGA。

OpenCL 是个 what?

注:引用自 wiki

Open Computing Language(OpenCL) is a framework for writing programs that execute acrossheterogeneousplatforms consisting ofcentral processing units(CPUs),graphics processing units(GPUs),digital signal processors(DSPs),field-programmable gate arrays(FPGAs) and other processors orhardware accelerators. OpenCL specifies aprogramming language(based onC99) for programming these devices and application programming interfaces (APIs) to control the platform and execute programs on the compute devices. OpenCL provides a standard interface for parallel computing usingtask-basedanddata-based parallelism.

大意是说:OpenCL 是一个用于异构平台编程的框架,主要的异构设备有 CPU、GPU、DSP、FPGA以及一些其它的硬件加速器。OpenCL 基于 C99 来开发设备端代码,并且提供了相应的 API 可以调用。OpenCL 提供了标准的并行计算的接口,以支持任务并行和数据并行的计算方式。

OpenCL 案例分析

这里采用 Altera 官网的矩阵乘法案例进行分析。可以通过如下链接下载案例:Altera OpenCL Matrix Multiplication

代码结构如下:

.|-- common| |-- inc| | `-- AOCLUtils| | |-- aocl_utils.h| | |-- opencl.h| | |-- options.h| | `-- scoped_ptrs.h| |-- readme.css| `-- src| `-- AOCLUtils| |-- opencl.cpp| `-- options.cpp`-- matrix_mult |-- Makefile |-- README.html |-- device | `-- matrix_mult.cl `-- host |-- inc | `-- matrixMult.h `-- src `-- main.cpp

其中,和 FPGA 相关的代码是matrix_mult.cl,该部分代码描述了 kernel 函数,这部分函数会通过编译器生成 RTL 代码,然后 map 到 FPGA 电路中。

kernel 函数的定义如下:

__kernel__attribute((reqd_work_group_size(BLOCK_SIZE,BLOCK_SIZE,1)))__attribute((num_simd_work_items(SIMD_WORK_ITEMS)))void matrixMult( __global float *restrict C, __global float *A, __global float *B, int A_width, int B_width)

模式比较固定,需要注意的是__global指明从 CPU 传过来的数据,存放到全局内存中,可以是 FPGA 片上存储资源,DDR,QDR 等,这个视 FPGA 的 OpenCL BSP 驱动,会有所区别。num_simd_work_items用于指明 SIMD 的宽度。reqd_work_group_size指明了工作组的大小。这些概念,可以参考 OpenCL 的使用手册。

函数实现如下:

// 声明本地存储,暂存数组的某一个 BLOCK__local float A_local[BLOCK_SIZE][BLOCK_SIZE];__local float B_local[BLOCK_SIZE][BLOCK_SIZE];// Block indexint block_x = get_group_id(0);int block_y = get_group_id(1);// Local ID index (offset within a block)int local_x = get_local_id(0);int local_y = get_local_id(1);// Compute loop boundsint a_start = A_width * BLOCK_SIZE * block_y;int a_end = a_start + A_width - 1;int b_start = BLOCK_SIZE * block_x;float running_sum = 0.0f;for (int a = a_start, b = b_start; a <= a_end; a += BLOCK_SIZE, b += (BLOCK_SIZE * B_width)){  // 从 global memory 读取相应 BLOCK 数据到 local memory  A_local[local_y][local_x] = A[a + A_width * local_y + local_x];  B_local[local_x][local_y] = B[b + B_width * local_y + local_x];  // Wait for the entire block to be loaded.  barrier(CLK_LOCAL_MEM_FENCE);  // 计算部分,将计算单元并行展开,形成乘法加法树  #pragma unroll  for (int k = 0; k < BLOCK_SIZE; ++k)  {    running_sum += A_local[local_y][k] * B_local[local_x][k];  }  // Wait for the block to be fully consumed before loading the next block.  barrier(CLK_LOCAL_MEM_FENCE);}// Store result in matrix CC[get_global_id(1) * get_global_size(0) + get_global_id(0)] = running_sum;

采用 CPU 模拟仿真 FPGA

对其进行仿真,不需要 programer 关心具体的时序是怎么走的,只需要验证逻辑功能就可以,Altera OpenCL SDK 提供了 CPU 仿真 Device 设备的功能,采用如下方式进行:

# To generate a .aocx file for debugging that targets a specific accelerator board$ aoc -march=emulator device/matrix_mult.cl -o bin/matrix_mult.aocx --fp-relaxed --fpc --no-interleaving default --board # Generate Host exe.$ make# To run the application$ env CL_CONTEXT_EMULATOR_DEVICE_ALTERA=8 ./bin/host -ah=512 -aw=512 -bw=512

上述脚本中,通过-march=emulator设置创建一个可用于 CPU debug 的设备可执行文件。-g 添加调试 flag。—board用于创建适配该设备的 debugging 文件。CL_CONTEXT_EMULATOR_DEVICE_ALTERA为用于 CPU 仿真的设备数量。

当执行上述脚本后,输出如下:

$ env CL_CONTEXT_EMULATOR_DEVICE_ALTERA=8 ./bin/host -ah=512 -aw=512 -bw=512Matrix sizes: A: 512 x 512 B: 512 x 512 C: 512 x 512Initializing OpenCLPlatform: Altera SDK for OpenCLUsing 8 device(s) EmulatorDevice : Emulated Device ... EmulatorDevice : Emulated DeviceUsing AOCX: matrix_mult.aocxGenerating input matricesLaunching for device 0 (global size: 512, 64)...Launching for device 7 (global size: 512, 64)Time: 5596.620 msKernel time (device 0): 5500.896 ms...Kernel time (device 7): 5137.931 msThroughput: 0.05 GFLOPSComputing reference outputVerifyingVerification: PASS

通过仿真时候设置 Device = 8,模拟 8 个设备运行 (512, 512) * (512, 512) 规模的矩阵,最终验证正确。接下来就可以将其真正编译到 FPGA 设备上后运行。

FPGA 设备上运行矩阵乘

这个时候,真正要将代码下载到 FPGA 上执行了,这时候,只需要做一件事,那就是用 OpenCL SDK 提供的编译器,将*.cl代码适配到 FPGA 上,执行编译命令如下:

$ aoc device/matrix_mult.cl -o bin/matrix_mult.aocx --fp-relaxed --fpc --no-interleaving default --board

这个过程比较慢,一般需要几个小时到10几个小时,视 FPGA 上资源大小而定。(目前这部分时间太长暂时无法解决,因为这里的编译,其实是在行程一个能够正常工作的电路,软件会进行布局布线等工作)

等待编译完成后,将生成的matrix_mult.aocx文件烧写到 FPGA 上就 ok 啦。

烧写的命令如下:

$ aocl program matrix_mult.aocx

这时候,大功告成,可以运行 host 端程序了:

$ ./host -ah=512 -aw=512 -bw=512Matrix sizes: A: 512 x 512 B: 512 x 512 C: 512 x 512Initializing OpenCLPlatform: Altera SDK for OpenCLUsing 1 device(s) : Altera OpenCL QPI FPGAUsing AOCX: matrix_mult.aocxGenerating input matricesLaunching for device 0 (global size: 512, 512)Time: 2.253 msKernel time (device 0): 2.191 msThroughput: 119.13 GFLOPSComputing reference outputVerifyingVerification: PASS

可以看到,矩阵乘法能够在 FPGA 上正常运行,吞吐大概在 119GFlops 左右。

小结

从上述的开发流程,OpenCL 大大的解放了 FPGAer 的开发周期,并且对于软件开发者,也比较容易上手。这是他的优势,但是目前开发过程中,还是存在一些问题,如:编译器优化不足,相比 RTL 写的性能存在差距;编译到 Device 端时间太长。不过这些随着行业的发展,一定会慢慢的进步。

另外,对 FPGA 感兴趣,或者有用 FPGA 做方案的同学,欢迎一起探讨。

声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。 举报投诉
  • FPGA
    +关注

    关注

    1629

    文章

    21736

    浏览量

    603245
  • cpu
    cpu
    +关注

    关注

    68

    文章

    10860

    浏览量

    211723
  • 异构计算
    +关注

    关注

    2

    文章

    101

    浏览量

    16296

原文标题:FPGA 那些事儿之异构计算

文章出处:【微信号:weixin21ic,微信公众号:21ic电子网】欢迎添加关注!文章转载请注明出处。

收藏 人收藏

    评论

    相关推荐

    程序员中有没有高富帅?程序猿如何能够升级为糕富帅?

    前几天在论坛里看到一个冷笑话,一位妈妈说自己儿子:“你什么都好,就不该是个程序员。” 可是,有些开发者朋友说,程序员中有相当一部分是生活得还不错的,甚至是高富帅。 所以想问问大家,程序员
    发表于 11-24 17:00

    程序员中有没有高富帅?程序猿如何能够升级为糕富帅?

    前几天在论坛里看到一个冷笑话,一位妈妈说自己儿子:“你什么都好,就不该是个程序员。” 可是,有些开发者朋友说,程序员中有相当一部分是生活得还不错的,甚至是高富帅。 所以想问问大家,程序员
    发表于 11-24 17:00

    ADO程序员指南

    ADO 程序员指南要了解对《Microsoft ActiveX Data Objects (ADO) 程序员指南》的简介,请参阅以下主题: ADO 程序员指南已经编制完成,其目的是要帮助作为 ADO 新手的
    发表于 05-10 11:20 3次下载

    程序员如何定义

    当了几年的程序员了,一直都在想一个问题,什么是程序员程序员应该做好那些事情,什么样的程序员是有素质的程序员?什么样的
    的头像 发表于 12-18 14:15 2629次阅读

    程序员如何规划自己的成长之路

    程序员的成长经历往往很相似,大部分的人走过了最前面相同的一段路,而有的人则走得更远。总结自己这些年来的历程,这也许能让年轻的程序员少走一些弯路,成长得更快;或许更好一些,
    发表于 04-24 18:30 0次下载
    <b class='flag-5'>程序员</b>如何规划自己的成长之路

    菜鸟程序员和大神程序员的差距

    刚刚走出就业的程序员,技术是刚刚起步的基点。那下面我们就聊一聊有关技术的东西。首先请您先想想这几个问题。现在社会上有很多程序员,CSDN就是我们程序员的家,那您是否可想过程序员为什么会
    的头像 发表于 06-03 15:56 2533次阅读

    什么是程序员

    当了几年的程序员了,一直都在想一个问题,什么是程序员程序员应该做好那些事情,什么样的程序员是有素质的程序员?什么样的
    的头像 发表于 06-04 16:21 9003次阅读

    程序员的未来

    程序员出路在何方程序员 创业如果你是程序员,也想创业,看看我说的。
    的头像 发表于 06-12 17:29 2956次阅读

    普通程序员和高级程序员有哪些区别

    从工作的方面来说,普通程序员和高级程序员一般有下面几个区别:
    的头像 发表于 09-08 10:47 3780次阅读

    优秀程序员与糟糕程序员的变现差异

    软件蚕食一切,未来属于程序员。所以人人都想当程序员。但是并不是每个人都能当好程序员。在你做出决定前还是先看看自己能不能当好程序员吧。
    的头像 发表于 11-07 16:14 3070次阅读

    程序员的类型

    今天来聊个有趣的话题,你是什么类型的程序员? 在学校里或在公司里,你是不是接触过不少其他的程序员,有没有发现,虽然同属程序员科, 但也有众多的不同。 今天我就来给程序员分个类,看看你是
    的头像 发表于 11-28 16:39 4703次阅读

    FPGA之异构计算

    深度学习,走上了历史的舞台,并且正如火如荼的跑者各种各样的业务,从 training 到 inference 都有它的身影。FPGA 也借着这股浪潮,慢慢地走向数据中心,发挥着它的优势。所以接下来就讲讲 FPGA何能让
    的头像 发表于 02-03 20:40 800次阅读

    FPGA何能让程序员友好开发编程呢?

    对于一个软件开发人员,可能听说过 FPGA,甚至在大学课程设计中,可能拿FPGA做过计算机体系架构相关的验证,但是对于它的第一印象可能觉得这是硬件工程师干的事儿。
    发表于 08-25 10:23 667次阅读
    <b class='flag-5'>FPGA</b>如<b class='flag-5'>何能让</b><b class='flag-5'>程序员</b><b class='flag-5'>们</b>更<b class='flag-5'>友好</b>的<b class='flag-5'>开发</b>编程呢?

    程序员节 | 今年程序员都想要的礼物竟然是……

    原文标题:程序员节 | 今年程序员都想要的礼物竟然是…… 文章出处:【微信公众号:微软科技】欢迎添加关注!文章转载请注明出处。
    的头像 发表于 10-24 10:35 515次阅读
    <b class='flag-5'>程序员</b>节 | 今年<b class='flag-5'>程序员</b><b class='flag-5'>们</b>都想要的礼物竟然是……

    喜迎1024程序员节!祝各位开发“码”到“程”功!

    祝各位开发,节日快乐! 程序员(Programmer)是从事程序开发、维护的专业人员。 对于奋斗在一线的
    的头像 发表于 10-24 20:00 798次阅读
    喜迎1024<b class='flag-5'>程序员</b>节!祝各位<b class='flag-5'>开发</b>者<b class='flag-5'>们</b>“码”到“程”功!