谷歌TPU_脉动阵列实现矩阵乘法(附完整Verilog代码)

2024-03-09 10:30

本文主要是介绍谷歌TPU_脉动阵列实现矩阵乘法(附完整Verilog代码),希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

谷歌TPU_脉动阵列实现矩阵乘法(附完整Verilog代码)

  • 一、谷歌TPU介绍
    • TPU计算核心的硬件架构
  • 二、矩阵乘法单元硬件架构
  • 三、脉动阵列实现矩阵乘法原理
  • 四、Verilog实现
    • PE单元
    • 顶层文件
    • Testbench文件
    • 仿真结果

一、谷歌TPU介绍

  谷歌的 TPU(张量处理单元)是一种专门为机器学习工作负载优化的定制硬件加速器。TPU 通过高效地执行矩阵乘法、卷积运算和其他常见的神经网络操作,以提供比传统 CPU 或 GPU 更快的训练和推理性能。
  谷歌 TPU 的基本构建块是一个称为 TPU 芯片的 ASIC(应用特定集成电路),其中包含了数千个小型处理单元,它们被称为“计算核心”或“TPU 内核”。这些内核提供了高度并行的计算能力,并且专门优化了常见的矩阵操作,如卷积和矩阵乘法。每个 TPU 芯片还包含了多个存储器子系统,包括高速缓存、本地共享内存和全局存储器。数据可以在这些存储器之间传输,以支持不同类型的计算和数据流。为了实现更高的性能和可扩展性,多个 TPU 芯片可以组合成一个称为 TPU Pod 的集群。TPU Pod 中的每个 TPU 芯片都能够直接访问其他芯片的存储器,因此可以实现高效的数据通信和更大规模的计算。除了硬件之外,谷歌还提供了一系列的软件工具来支持 TPU 的使用。例如,TensorFlow 框架可以通过编写特定的代码来利用 TPU 的计算能力,并且谷歌还提供了一些高级优化工具,如 XLA 编译器,以进一步提高性能和效率。总的来说,谷歌 TPU 的硬件架构部分采用了定制化的设计,以支持高度并行的计算和专门优化的矩阵操作。TPU Pod 集群也提供了更高的可扩展性和性能,使得它们适合于大规模的深度学习任务。TPU 最初是为了支持谷歌的机器学习框架 TensorFlow 而开发的,但它也可以与其他机器学习框架一起使用。Google Cloud 平台上的用户可以通过 Cloud TPU 服务来访问这些加速器,以加快他们的机器学习工作负载。
  总的来说,TPU 是一种设计用于加速机器学习工作负载的定制硬件加速器,对于大规模的深度学习任务提供了高性能和能效。

TPU计算核心的硬件架构

  下图为TPU计算核心的硬件架构,主要包含以下几部分:

  1. 矩阵乘法单元(Matrix Multiply Unit):矩阵乘法是深度学习中常见的计算操作之一,TPU 的计算核心专门针对矩阵乘法进行了优化。它包含多个乘法和累加器单元,以高效地执行大规模矩阵乘法运算。
  2. 卷积单元(Convolution Unit):卷积操作是卷积神经网络(CNN)中常用的操作,TPU 的计算核心也针对卷积操作进行了优化。卷积单元具有特定的硬件结构,可以高效地执行卷积计算。
  3. 存储器子系统(Memory Subsystem):TPU 的计算核心包含多个存储器子系统,用于存储权重、输入数据和中间结果。这些存储器子系统包括高速缓存、本地共享内存和全局存储器,可以在不同的存储器之间进行数据传输,并且能够支持快速的访问和数据流。
  4. 控制逻辑(Control Logic):TPU 的计算核心还包括控制逻辑单元,用于指导和管理计算操作的执行。控制逻辑负责调度和协调不同的计算单元,并确保计算操作按照正确的顺序和时序进行。
      这些部分共同组成了一个 TPU 计算核心的架构。通过高度并行的设计和针对矩阵乘法、卷积等常见操作的优化,TPU 的计算核心可以提供高性能和能效,适用于大规模的深度学习任务。
      本文将介绍TPU中的矩阵乘法单元(Matrix Multiply Unit),并编写Verilog代码实现其功能,并仿真验证其功能,之后的文章会完成卷积单元(Convolution Unit)的部分,并进行开源。
    在这里插入图片描述

二、矩阵乘法单元硬件架构

  TPU 中的矩阵乘法单元(Matrix Multiply Unit)是其硬件架构中的关键部分,它专门针对大规模矩阵乘法操作进行了优化。下面是矩阵乘法单元的硬件架构主要特点:

  1. 数学计算单元:矩阵乘法单元包含大量的数学计算单元,用于执行乘法和累加操作。这些计算单元能够并行地处理多个元素,从而实现高效的矩阵乘法计算。
  2. 数据流水线:矩阵乘法单元通常采用数据流水线的设计,将矩阵乘法操作划分为多个阶段,并在不同阶段并行地处理不同的数据。这样可以充分利用硬件资源,提高计算效率。
  3. 数据存储和交换:矩阵乘法单元需要大量的数据存储和交换能力,以便及时获取输入数据、存储中间结果,并输出最终的计算结果。因此,在硬件架构中通常包括了高速缓存、寄存器文件等数据存储单元,以及专门的数据总线和交换逻辑。
  4. 控制逻辑和调度器:矩阵乘法单元中还包含了控制逻辑和调度器,用于管理和协调不同计算单元之间的工作。控制逻辑负责指导数据流的处理顺序,保证计算操作的正确执行。
      总的来说,矩阵乘法单元在硬件架构中具有高度并行的设计,以支持大规模矩阵乘法运算。它通过优化的数据流水线、数据存储和交换机制,以及有效的控制逻辑,实现了对矩阵乘法操作的高效执行。
      下图是TPU中乘法单元的硬件架构图,核心部分是多个Cell组成的计算阵列,阵列的左侧和上侧分别是处理后的两个矩阵的行和列数据,矩阵数据跟随时钟上升沿在阵列中有规律的流动,因此得名脉动阵列,使用脉动阵列实现矩阵乘还可以减少数据存取的次数,进而消除存储墙,实现高性能的存内计算。
    在这里插入图片描述

三、脉动阵列实现矩阵乘法原理

在这里插入图片描述
  如上图所示,以一个3乘3和3乘3的矩阵相乘为例,第一个矩阵的数据为[[X11,X12,X13],[X21,X22,X23],[X31,X32,X33]],第二个矩阵的数据为[[W11,W12,W13],[W21,W22,W23],[W31,W32,W33]]数据按上图顺序依次输入阵列,阵列单元PE完成乘加操作,并把来自左边的数据往右传,把来自上边的数据往下传,各PE单元中除了乘加单元,也有存放sum的寄存器,把和进行保存。对于n乘n和n乘n的矩阵,共需要n-2个周期,就能完成计算。
脉动阵列的特点:
• 每个PE只与其邻近的PE进行通信,PE之间的通信具有局部性,而且通信是规则的。
• 每一个PE都是相同的,但个别也可以不同(边缘的PE不同)。
• 通过时钟激励统一处理。

四、Verilog实现

PE单元

  PE单元实现乘加操作,并配有寄存器能存储和(sum)数据,Verilog代码如下:

module pe(clk,rst,left,up,down,right,sum_out);
input clk;
input rst;
input [3:0] left;
input [3:0] up;
output reg [3:0] down;
output reg [3:0] right;
output reg [7:0] sum_out;
wire [7:0] mult_out;
always@(posedge clk)beginif(rst) beginright<=0;down<=0;sum_out<=0;endelse begindown<=up;right<=left;sum_out<=sum_out+mult_out;end
end
multiply u_mult(.a(left),.b(up),.out(mult_out)
);endmodule

  PE中例化的乘法器,可自行设置,可根据需要设置为半精度、单精度、双精度等,在这里使用普通的十进制乘法器,代码如下:

module multiply(a,b,out);
input [3:0]a;
input [3:0]b;
output wire [7:0] out;
assign out=a*b;
endmodule

顶层文件

  脉动阵列顶层模块中例化了9个PE单元,顶层模块代码如下:

module top(clk,rst,en,in1,in2,out);
input clk;
input rst;
input en;
input [4*9-1:0] in1;
input [4*9-1:0] in2;
output reg [9*9-1:0] out;
reg [3:0] hang1 [0:4];
reg [3:0] hang2 [0:4];
reg [3:0] hang3 [0:4];
reg [3:0] lie1 [0:4];
reg [3:0] lie2 [0:4];
reg [3:0] lie3 [0:4];
reg [3:0] flag;
wire [3:0] down00,down01,down02,down10,down11,down12,down20,down21,down22;
wire [3:0] right00,right01,right02,right10,right11,right12,right20,right21,right22;
wire [7:0] sum00,sum01,sum02,sum10,sum11,sum12,sum20,sum21,sum22;
reg [3:0] left00;
reg [3:0] left10;
reg [3:0] left20;
reg [3:0] up00;
reg [3:0] up01;
reg [3:0] up02;
always@(posedge clk)beginif(rst)beginout<=0;endelse beginhang1[0]<=in1[3-:4];hang1[1]<=in1[7-:4];hang1[2]<=in1[11-:4];hang1[3]<=4'b0000;hang1[4]<=4'b0000;hang2[0]<=4'b0000;hang2[1]<=in1[15-:4];hang2[2]<=in1[19-:4];hang2[3]<=in1[23-:4];hang2[4]<=4'b0000;hang3[0]<=4'b0000;hang3[1]<=4'b0000;hang3[2]<=in1[27-:4];hang3[3]<=in1[31-:4];hang3[4]<=in1[35-:4];lie1[0]<=in2[3-:4];lie1[1]<=in2[15-:4];lie1[2]<=in2[27-:4];lie1[3]<=4'b0000;lie1[4]<=4'b0000;lie2[0]<=4'b0000;lie2[1]<=in2[7-:4];lie2[2]<=in2[19-:4];lie2[3]<=in2[31-:4];lie2[4]<=4'b0000;lie3[0]<=4'b0000;lie3[1]<=4'b0000;lie3[2]<=in2[11-:4];lie3[3]<=in2[23-:4];lie3[4]<=in2[35-:4];end
end
always@(posedge clk)if(rst)beginflag<=0;endelse if(en) begin//if(flag==4'd5)//flag<=0;//elseflag<=flag+1;end
always@(posedge clk)begincase(flag)0 : beginleft00<=hang1[0];left10<=hang2[0];left20<=hang3[0];up00<=lie1[0];up01<=lie2[0];up02<=lie3[0];end1 : beginleft00<=hang1[1];left10<=hang2[1];left20<=hang3[1];up00<=lie1[1];up01<=lie2[1];up02<=lie3[1];end2 : beginleft00<=hang1[2];left10<=hang2[2];left20<=hang3[2];up00<=lie1[2];up01<=lie2[2];up02<=lie3[2];end3 : beginleft00<=hang1[3];left10<=hang2[3];left20<=hang3[3];up00<=lie1[3];up01<=lie2[3];up02<=lie3[3];end4 : beginleft00<=hang1[4];left10<=hang2[4];left20<=hang3[4];up00<=lie1[4];up01<=lie2[4];up02<=lie3[4];enddefault : beginleft00<=0;left10<=0;left20<=0;up00<=0;up01<=0;up02<=0;endendcaseendpe pe00(.clk(clk),.rst(rst),.left(left00),.up(up00),.down(down00),.right(right00),.sum_out(sum00)
);
pe pe01(.clk(clk),.rst(rst),.left(right00),.up(up01),.down(down01),.right(right01),.sum_out(sum01)
);
pe pe02(.clk(clk),.rst(rst),.left(right01),.up(up02),.down(down02),.right(right02),.sum_out(sum02)
);
pe pe10(.clk(clk),.rst(rst),.left(left10),.up(down00),.down(down10),.right(right10),.sum_out(sum10)
);
pe pe11(.clk(clk),.rst(rst),.left(right10),.up(down01),.down(down11),.right(right11),.sum_out(sum11)
);
pe pe12(.clk(clk),.rst(rst),.left(right11),.up(down02),.down(down12),.right(right12),.sum_out(sum12)
);
pe pe20(.clk(clk),.rst(rst),.left(left20),.up(down10),.down(down20),.right(right20),.sum_out(sum20)
);
pe pe21(.clk(clk),.rst(rst),.left(right20),.up(down11),.down(down21),.right(right21),.sum_out(sum21)
);
pe pe22(.clk(clk),.rst(rst),.left(right21),.up(down12),.down(down22),.right(right22),.sum_out(sum22)
);endmodule

Testbench文件

  顶层模块的仿真测试文件如下:

`timescale 1ns / 1ps
module top_tb();
reg clk;
reg rst;
reg en;
reg [4*9-1:0] in1;
reg [4*9-1:0] in2;
wire [9*9-1:0] out;
initial beginclk=0;rst=0;in1=0;in2=0;en=0;#10rst=1;#10rst=0;in1=36'b0101_0010_0011_0011_0101_0010_0010_0100_0011;in2=36'b0101_0010_0011_0011_0101_0010_0010_0100_0011;#10en=1;#100$finish;end
always#5clk=~clk;
top u_top(.clk(clk),.rst(rst),.in1(in1),.in2(in2),.out(out),.en(en));endmodule

仿真结果

  仿真测试的功能是进行
[[3,4,2],
[2,5,3],
[3,2,5]]矩阵和
[[3,4,2],
[2,5,3],
[3,2,5]]相乘,
最后的结果是
[[23,36,28],
[25,39,34],
[28,32,37]]
  脉动阵列的数据流输入如下图所示:
在这里插入图片描述
  仿真结果波形图如下图所示:
在这里插入图片描述
  仿真结果数据正确,且各PE最终结果产生的时序正确。
  整体工程已上传个人github仓库,之后会完成谷歌TPU中的脉动阵列实现卷积操作的项目并开源。

这篇关于谷歌TPU_脉动阵列实现矩阵乘法(附完整Verilog代码)的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/790401

相关文章

Java计算经纬度距离的示例代码

《Java计算经纬度距离的示例代码》在Java中计算两个经纬度之间的距离,可以使用多种方法(代码示例均返回米为单位),文中整理了常用的5种方法,感兴趣的小伙伴可以了解一下... 目录1. Haversine公式(中等精度,推荐通用场景)2. 球面余弦定理(简单但精度较低)3. Vincenty公式(高精度,

QT6中绘制UI的两种方法详解与示例代码

《QT6中绘制UI的两种方法详解与示例代码》Qt6提供了两种主要的UI绘制技术:​​QML(QtMeta-ObjectLanguage)​​和​​C++Widgets​​,这两种技术各有优势,适用于不... 目录一、QML 技术详解1.1 QML 简介1.2 QML 的核心概念1.3 QML 示例:简单按钮

使用Java将实体类转换为JSON并输出到控制台的完整过程

《使用Java将实体类转换为JSON并输出到控制台的完整过程》在软件开发的过程中,Java是一种广泛使用的编程语言,而在众多应用中,数据的传输和存储经常需要使用JSON格式,用Java将实体类转换为J... 在软件开发的过程中,Java是一种广泛使用的编程语言,而在众多应用中,数据的传输和存储经常需要使用j

Java实现视频格式转换的完整指南

《Java实现视频格式转换的完整指南》在Java中实现视频格式的转换,通常需要借助第三方工具或库,因为视频的编解码操作复杂且性能需求较高,以下是实现视频格式转换的常用方法和步骤,需要的朋友可以参考下... 目录核心思路方法一:通过调用 FFmpeg 命令步骤示例代码说明优点方法二:使用 Jaffree(FF

基于C#实现MQTT通信实战

《基于C#实现MQTT通信实战》MQTT消息队列遥测传输,在物联网领域应用的很广泛,它是基于Publish/Subscribe模式,具有简单易用,支持QoS,传输效率高的特点,下面我们就来看看C#实现... 目录1、连接主机2、订阅消息3、发布消息MQTT(Message Queueing Telemetr

Java实现图片淡入淡出效果

《Java实现图片淡入淡出效果》在现代图形用户界面和游戏开发中,**图片淡入淡出(FadeIn/Out)**是一种常见且实用的视觉过渡效果,它可以用于启动画面、场景切换、轮播图、提示框弹出等场景,通过... 目录1. 项目背景详细介绍2. 项目需求详细介绍2.1 功能需求2.2 非功能需求3. 相关技术详细

Python实现获取带合并单元格的表格数据

《Python实现获取带合并单元格的表格数据》由于在日常运维中经常出现一些合并单元格的表格,如果要获取数据比较麻烦,所以本文我们就来聊聊如何使用Python实现获取带合并单元格的表格数据吧... 由于在日常运维中经常出现一些合并单元格的表格,如果要获取数据比较麻烦,现将将封装成类,并通过调用list_exc

使用animation.css库快速实现CSS3旋转动画效果

《使用animation.css库快速实现CSS3旋转动画效果》随着Web技术的不断发展,动画效果已经成为了网页设计中不可或缺的一部分,本文将深入探讨animation.css的工作原理,如何使用以及... 目录1. css3动画技术简介2. animation.css库介绍2.1 animation.cs

Java进行日期解析与格式化的实现代码

《Java进行日期解析与格式化的实现代码》使用Java搭配ApacheCommonsLang3和Natty库,可以实现灵活高效的日期解析与格式化,本文将通过相关示例为大家讲讲具体的实践操作,需要的可以... 目录一、背景二、依赖介绍1. Apache Commons Lang32. Natty三、核心实现代

SpringBoot实现接口数据加解密的三种实战方案

《SpringBoot实现接口数据加解密的三种实战方案》在金融支付、用户隐私信息传输等场景中,接口数据若以明文传输,极易被中间人攻击窃取,SpringBoot提供了多种优雅的加解密实现方案,本文将从原... 目录一、为什么需要接口数据加解密?二、核心加解密算法选择1. 对称加密(AES)2. 非对称加密(R