lcytms
发表于 2018-4-19 09:16:27
14
接下来的话,我们聊一个话题,就是关于FPGA从软件编程人员,从软件开发者的角度,怎么来看FPGA?
我们从一个非常典型的软件例子入手,比如说我们做一个非常典型的软件操作。
把mem的一个数据取出来,和一个立即数相乘,乘完的数据和另外一个mem的数据相加。
结果成为mem。
做这么一件事情。
如果用指令集的方式来表达这个事情的话,实际上使用不同的指令来组成的。
这些指令里面,它有三条的load数据的指令。
有两条计算的指令,有一条乘,有一条加。
lcytms
发表于 2018-4-19 09:19:05
15
最后一个是store指令,把数据存回去。
这样的指令,它肯定是在某种硬件上面去执行,才能得到相应的结果。
这是一种通用硬件结构,来实现功能的一种方式。
这里有一个相对复杂的电路。
这个电路里面,包含了指令预取、指令译码、ALU、load、store单元。
但是这些指令在这上面去执行的话,它很显然是一个串行的执行方式,每条指令会用到电路的一部分功能。
但是由于这个电路它不能同时执行多条指令,这些指令都是顺序执行。
每一次使用到电路的一部分。
从这个角度来说,它用时间轴的方式来做这个事情。
那么这样一个事情,是不是一定要这样做呢?
有没有更好的方法来做这件事情呢?
lcytms
发表于 2018-4-19 09:20:34
16
实际上是有的。更好的方法,就是所谓的专用的电路来做这个事情。
专用的电路,大家看到的第一眼,第一个反应是什么呢?
电路很简单,相对于前面CPU,它表现出很简单。这个简单是怎么得到的?
简单是用专用得到的好处。
我不需要支持额外更多的东西,我用两个load单元,两个计算单元,有存储就足够了。
我不需要非常复杂的控制流。
这样的一个简化电路的话,就是用FPGA来实现的功能,与传统的通用硬件的方法的根本差别。
这个根本差别直接带来的好处是什么呀?
就是有可能有更高的流通量,有更低的Latency,和更低的功耗。
lcytms
发表于 2018-4-19 09:22:31
17
这也是为什么说FPGA我来实现同样一个算法,与CPU这个算法,或者GPU这个算法,我的能效比更高的一个根本原因。
因为什么呀?我没有多余的硬件电路,我所有的硬件都是为你的算法而定制的。
我们进入到第三个话题。
我们来介绍一下Intel FPGA针对OpenCL的SDK。
首先呢,我如果说到OpenCL,大家可能第一反应呢,它是不是一个C2H的工具?
C2H的工具,很多人也都知道,炒了很多年了。
C2H开发的时间不下于10年,甚至15年、20年都有。
但是并没有一个非常完美的、完备的C2H工具存在。
但是OpenCL的出现,实际上改变了一个这样的方式。
lcytms
发表于 2018-4-21 13:31:53
18
首先OpenCL它的编程对象,不是单个物理器件,不管你是C2H也好,还是Verilog也好,你的编程对象都是单个FPGA。
C语言的编程对象是单个CPU,但是实质上我们现在所面临的平台,并不是一个单个平台,我们总是在一个异构平台上进行开发。
通常情况下,我们CPU+FPGA,CPU+DSP,CPU+什么什么。
因为没有一种硬件电路能够完美到适合于所有不同的需求,然而我们的真实应用是由不同需求组成的,所以说我们所面向的硬件编程平台是异构平台。
用异构平台开发,怎么样来做这个事情呢?
那么就需要一种新的开发方式,能够在异构平台上进行开发,它是什么呢?
它就是OpenCL。
lcytms
发表于 2018-4-21 14:08:22
19
OpenCL,它的目标是把CPU、FPGA做成一个整体,从系统的角度来做一个开发。
除了标准的OpenCL的语法的一个实现以外,实际上Intel也做了一个关于OpenCL标准的一个扩展,就叫所谓的通道/Pipe特性。
这个通道/Pipe特性,它主要是Kernel和Kernel之间,能够直接进行数据交互,能够有所谓的IO通道把数据传进Kernel,Kernel传出IO通道。
为什么会有这样的需求呢?
因为大家知道,很多数据它本身存在流线数据结构,比较典型的有图像处理,比方说,第一步处理图像的灰度,第二个我处理图像的亮度,第三个我处理它的某种特征,第四个把它送出去了。
这样的一个流线数据处理的话,如果你需要CPU过多的干预,比如说,我第一个处理完了之后,数据应该导回CPU,CPU又送回去。
lcytms
发表于 2018-4-21 20:20:17
20
这一来一回,这种开销很多系统里面是不必要的,甚至是成为系统的瓶颈。
这里根据FPGA的特性,它有非常丰富的接口,它能够有能力把数据送进去,那么它扩展了一个特性,叫通道/Pipe。
接下来我们讨论一下关于抽象FPGA的问题。
前面我们提到了,我们是对一个平台进行开发,那么这个平台上面的话,是有两种器件。
一种是CPU,所谓的Host。
一种是FPGA,所谓的Device。
那么我们的输入是什么呢?
我们的输入是传统的C语言输入。
主机端的输入是主控方向。
这一端是采用传统的C编译器,传统的C语法来进行开发。
lcytms
发表于 2018-4-21 20:21:02
21
当你整个开发过程进行到某一步我需要加速的时候,这一部分工作我认为它是有高度的并行性,非常适合于这种并行化。
Device在处理的时候,会用一种特殊的函数,这个函数就是OpenCL里的kernel函数。
那么kernel函数,它的执行载体就不是CPU了,它的执行载体是什么呀?
就是加速器,Device。
所以在这个图上,可以看到有两条路径,第一条路径是蓝色的路径,是主机的一条路径。
在这条路径里面的话,你会发现它与传统的C2H非常地类似。
除了黄色部分的特殊函数以外。
黄色部分通常情况下就是CPU如何与加速去打交道,所定义的一整套机制。
这一整套机制,它提供了通用的一种接口。
从另一个角度讲,就隐藏了这些细节。
lcytms
发表于 2018-4-21 20:21:58
22
让不管是哪个开发者,当他使用Host与Device打交道的时候,他只需要关心基本的函数,而不需要管你下面是PCIe,还是以太网,不需要关心你是x1的,还是x4的,有多少流通量,不需要关心。
它把它抽象了,到上面做成标准的接口。
第二个方向是所谓的Device方向,这个方向会有Altera OpenCL的一些编译器,把它编译成Quartus能够认识的用Verilog来描述的硬件结构。
硬件结构会在Quartus做一个离线的编译,生成能够在FPGA上运行的文件。
然后完整地运行起来,这样就是一个OpenCL的开发的抽象模型。
对应的物理平台可以选啥?
Host可以选主机,而Device是什么呢?
一个PCI加速卡,这是最最常见的形态。
lcytms
发表于 2018-4-21 20:24:38
23
下面呢,是关于传统的主机程序的一个更加细节的一个描述。
它这个描述里面,不但描述了CPU与Device之间标准的API函数,而且通过这个例子表现出主机和加速器之间一个基本的配合方式。
这个配合方式做什么?
通常情况下,主机会通过第一个函数clEnqueueWriteBuffer把数据写到加速器里面去。
通过clEnqueueNDRange这个函数告诉加速器,你可以对这批数据进行处理。
当这个数据处理完了之后的话,会有一个事件来告诉CPU说我处理完了。
CPU这个时候会通过读Buffer的方式,把处理完的数据读回去。
这几个函数调用的话,反映了在OpenCL标准里面,主机和加速器如何配合工作的一个基本的思路。