聊聊FPGA/GPCPU/PCIE/Cache-Coherency/CAPI1.0

2015-05-28 冬瓜哥 大话存储

聊聊FPGA/GPCPU/PCIE/Cache-Coherency/CAPI1.0_通用

冬瓜哥和存储界的朋友们有个无声的约定,那就是,想知道产品/技术背后的奥秘,了解底层,剥掉厂商包装忽悠的外壳,那关注冬瓜哥是没错的,底层通,一通百通,逼格秒涨!冬瓜哥没有太多精力和兴趣去搜罗业界八卦并分析,聊八卦一向不是冬瓜哥的强项,虽然属于MKT的角色,但是身在曹营心在汉,你和咱说市场,咱就和你论技术,忽悠死你,哈哈~~。冬瓜哥认为,底层技术是终生受用的武器,冬瓜哥看任何产品或者说事物,都要看透其底层才可罢休,否则冬瓜哥会感觉很不爽。

闲话少说,今天我们说一说IBM搞的CAPICAPIOpenPower体系里的一个技术,其目的是让FPGA更好更方便的融入现有的系统。那么现有的FPGA是怎么被使用的呢?不如先说说什么是FPGA,要弄清楚什么是FPGA,就得先说说什么是CPU。可笑,CPU大家都知道,冬瓜哥这逼格咋降低了?笑而不语。

·        通用CPU是怎么运算的?

我们都知道所谓GPCPU(通用目的CPU,也就是什么都能算,但又什么都算不快的CPU,所以其通用,比如Intel x86AMD x86PowerPowerPCMIPSARMDragonSon/GodSon(国产)等。而FPGA就是专门为了某种某类计算而专门优化其内部的逻辑电路的一种专用CPUGPCPU内部的ALU包含多种运算器比如加减乘除以及逻辑(比如xorandornot)运算以及整数和浮点运算,我们开始菜单计算器,算加减法,代码指令便会把对应的数据导入到CPU的寄存器,CPU收到之后便会将操作数输入到运算器的输入端,并在下一个时钟周期获取到计算结果并输出到寄存器,然后写回到主存。当然,GPCPU内部花费了大量的资源(逻辑电路)去做优化,包括缓存管理、流水线、多发射、分支预测、乱序执行等等,一条指令要最终得到执行,都要经过这些关卡的一层层处理,所以,对于那些遵纪守法的代码(比如,顺着来没有任何判断跳转)来讲其时延无疑会增加,但是目前随着业务越来越复杂,应用程序的判断条件越来越多,所以这些优化会增加最终性能,虽然时延相对上提高了,但是性能绝对上是增加了,因为如果误判了一个分支,那么整个流水线已经预读入的代码就会被冲刷走重新读入,这个时延反而会更大。

有人问了,我不打开计算器,就运行个QQ,难道还要算加减法么?如果没有什么加减乘除运算,CPU运行QQ到底是运行了些什么东西?这问题问得好,问的逼格高,一般人是根本不去想QQ运行时候底层都做了什么的。其实GPCPU大多时候还真没有在算加减乘除,而更多地是做协调工作了,也就是把内存里某段数据读出来,稍加改动或者根本不动,又写到内存其他地方去。这不闲的么,CPU就干这个?是的。比如QQ要发送一句话给某个好友,其需要调用TCP协议栈顶上的soket API,后者就是一段常驻内存的OS内核代码,那么QQ.exe如何将这句话传递给这段代码?QQ.exe会让CPU把这句话在当前内存的地址告诉socket API代码,其会将这个地址以及其他参数写入到某个CPU寄存器,对应机器指令就是“mov 内存地址寄存器A”类似这种,然后QQ.exe调用socket API,对应机器指令就是“call socket API的内存地址CPU就会把QQ.exe当前的地址暂存起来以便后续返回继续执行(这叫压栈),然后再跳转到socket API地址来执行socket代码(从内存中该地址读出socket代码执行),socket代码执行之后,会在CPU寄存器内发现之前传递过来的参数(要发送数据的内容等),然后按照这个参数向下调用TCP协议栈将数据打包,分段,贴上IP标签,最后调用以太网卡驱动程序,调用过程与上述类似,然后发送到网卡。这个过程,在主路径上,加减乘除运算并不是必须的,但是在辅路径上,比如程序需要记住当前发送了多少内容了,TCP协议栈也要记录当前发送了多少个分段了,这些就需要CPU做加法操作,来计数;另外,在遇到if代码的时候,cpu会比对多个输入条件,对应机器指令是comp(比较)以及jmpz/jmpnz(遇零跳转/非零跳转)等此时会用到减法器或者比较器,这恐怕是通用场景下用得最多的ALU运算器了。所以,上述这个过程,根本就不是一个大运算量的过程。但是你如果去听mp3,解码RMVB电影,那就需要大运算量了,这些场景也是专用场景。

·        专用FPGA又是怎么计算的?

通用CPU做通用场景的代码执行,很强,什么都能干,听着歌聊着QQ做着ppt,再加上个SSD,体验流畅的感觉。但是让你算一算分子动力学,某个分子内的原子是怎么运动的?算一算人脸识别?搞搞搜索?那通用CPU就歇菜了。此时,加减乘除、逻辑、整数、浮点统统一起上,通用场景下使用比例较少的这些ALU,但是专用场景下,这些ALU反而不够用了,一个是数量太少,一个是位宽太低。比如XOR运算器,如果位宽只有64bit,每个时钟周期只能将两个64bitXOR,如果我要XOR 两份1GB的数据,就需要1GB/64bit=?(自己算)个时钟周期,才能算完。此时,专用计算就派上用场了,也就是所谓的硬加速总体来讲硬加速有4种实现手段:露点、加宽、并行、直译。露,就是直接把最终的运算单元给露出来,抛掉那些什么分支预测等流水线步骤;宽,就是把运算器位宽直接加大,一个周期多算一些数据;并就是把多种分支直接并行检测,也就是把比较器/减法器直接并行化,结果相OR或者AND,来判断后续路径;直译就是把多种条件直接用译码器做出来,一个周期输出结果。所有这些都需要电路层面的改动,这就产生了FPGA现场可编程门电路阵列FGPA内部就是一堆的直译表(DRAM,用户自己写好逻辑然后输入进去),再加上一些外围接口,和一些固定的算法器件比如Flash控制器常用的LDPC硬核。NIC、存储IO卡、防火墙、路由器等,内部都使用了应加速,比如网卡收到一个以太网帧,其需要解析帧头,这种工作如果交给GPCPU的话,那就太慢了,来,先从内存读入代码看看要让爷我干点啥?译完了码,来,进流水线等着吧,我顺便去做个分支预判,找一找历史预判数据,下一位!进了流水线后,亲,你先排在后面吧因为你要的资源和别人有冲突。最后操作数到达ALU,尼玛,就这么点位宽?小爷这吨位起码得1Mbit位宽才放得下!亲,下次再来吧,来之前先进闸刀给你闸成多个64bit,然后每次算64bit吧。。而硬加速直接把这个帧载入寄存器,其中电路直接导向各个译码器,直译出下一步的操作,比如需要比对ALC,那么就多个目标地址/源地址并行比较一个周期输出,这样才能保证速度。

·        专用FPGA怎么与系统对接?

目前的FPGA都是使用PCIEhost通信的,也就是做成一张PCIE卡查到主板PCIE槽上。主程序通过驱动程序,将需要运算的数据指针告诉FPGA,然后FPGA从主存DMA读取待计算数据然后计算,算完后DMA回主存并通知主程序。

·        多核心多CPU系统以及PCIE设备

聊聊FPGA/GPCPU/PCIE/Cache-Coherency/CAPI1.0_产品_02

所有CPU看到单一物理地址空间,所有Threads看到单一虚拟地址空间,PCIE物理地址空间映射到CPU物理地址空间,CPU物理地址空间也映射到PCIE物理地址空间。

聊聊FPGA/GPCPU/PCIE/Cache-Coherency/CAPI1.0_产品_03

数据出了ALU,面对的一张复杂的路由网络,目的地址为内存地址,但是其相对外部网络的复杂性在于,目标的位置是不固定的,还可能有多份拷贝。Need Coherency!硬件透明搞定Cache CoherencyCC不负责多线程并发访问cache line时的互斥,互斥需要程序显式发出lock,底层硬件会锁住总线访问周期。

·        PCIE设备如何与CPU交互?

聊聊FPGA/GPCPU/PCIE/Cache-Coherency/CAPI1.0_朋友_04

1.   BusDriverPCIE设备地址空间映射到CPU物理地址空间并将PCIE地址空间写入PCIE设备寄存器。

2.   HostDriver读出PCIE设备寄存器获取该设备对应的PCIE物理地址空间并ioremap()到内核虚拟地址空间

3.   HostDriver 申请DMA缓存并向PCIE设备映射的虚拟地址空间写入控制字、基地址等,这些信息便被写入设备寄存器,从而触发PCIE设备根据基地址从主存DMA拿到需要的指令和数据后进行处理。

4.   PCIE设备对主存DMA时,RC自动执行Probe操作以保证CacheCoherency

·        当前交互方式存在的不足

1.   执行路径长而且全软件参与:应用call->传输协议栈(如有)->Host驱动->PCIE设备->DMAà中断服务->Host驱动->传输协议栈(如有)->应用buffer

2.   PCIE设备与CPU看到不同的物理地址空间,RC进行映射和转换。驱动程序申请内存之后得用pci_map_single()映射成PCIE物理地址。

3.   用户态程序必须主动从内核地址空间mmap()才可以直接与PCIE设备DMA互传数据。用户态程序必须区分不同的地址段。

·        CAPI1.0版本如何解决当前的问题?

聊聊FPGA/GPCPU/PCIE/Cache-Coherency/CAPI1.0_八卦_05

AFU—Acceleration Function Unit,主加速逻辑部分,用户写入自己设计的逻辑和Firmware

PSL—Power Service Layer, 提供接口给AFU用于读写主存和V2P地址翻译(与CPU侧使用同一个页表,并包含TLB),同时负责Probe CAPP实现全局cc,并提供CachePSLIBM作为硬核IP提供给FPGA开发者。

CAPP—Coherent Attached Processor Proxy, 相当于FPGA侧的ccAgent,但是被放在了CPU侧,其维护一个filter目录并接受来自其他CPUProbe,未过滤掉的Probe转发PSL

·        性能能提高多少?

聊聊FPGA/GPCPU/PCIE/Cache-Coherency/CAPI1.0_通用_06

上图是IBM自己的一个测试,利用CAPI enabled FC HBA(基于FGPA),与传统方式相对比,性能提升非常大,我没有是测过,对其底层的机制有点怀疑,FPGA后端同样使用传统的FC控制器以及驱动程序连接AFA阵列,这与直接把FC卡插在主机上相比,增加了一层CAPI,只会时延更高,但是结果却是时延下降,由于IBM并没有提供更多信息,所以这里不好判断。

·        CAPI1.0暂时做不到的事情,Maybe in future

聊聊FPGA/GPCPU/PCIE/Cache-Coherency/CAPI1.0_包装_07

o    CPU侧看不到AFU上的地址空间(MMIO控制寄存器地址除外)

o    AFU只能给一个进程使用:进程Open AFU之后便独占之。

o    如果可以把FPGA直接接入CPUFSB,是不是会更快?Maybe in future